LCOV - code coverage report
Current view: top level - dev/ata - ata.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 88 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ata.c,v 1.36 2017/12/30 20:46:59 guenther Exp $      */
       2             : /*      $NetBSD: ata.c,v 1.9 1999/04/15 09:41:09 bouyer Exp $      */
       3             : /*
       4             :  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  * 1. Redistributions of source code must retain the above copyright
      10             :  *    notice, this list of conditions and the following disclaimer.
      11             :  * 2. Redistributions in binary form must reproduce the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer in the
      13             :  *    documentation and/or other materials provided with the distribution.
      14             :  *
      15             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      16             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      17             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      18             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      19             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      20             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      21             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      22             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      23             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      24             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      25             :  */
      26             : 
      27             : #include <sys/param.h>
      28             : #include <sys/systm.h>
      29             : #include <sys/kernel.h>
      30             : #include <sys/stat.h>
      31             : #include <sys/malloc.h>
      32             : #include <sys/device.h>
      33             : #include <sys/syslog.h>
      34             : #include <sys/pool.h>
      35             : 
      36             : #include <machine/bus.h>
      37             : 
      38             : #include <dev/ata/atareg.h>
      39             : #include <dev/ata/atavar.h>
      40             : #include <dev/ic/wdcreg.h>
      41             : 
      42             : #define DEBUG_FUNCS  0x08
      43             : #define DEBUG_PROBE  0x10
      44             : #ifdef WDCDEBUG
      45             : extern int wdcdebug_mask; /* init'ed in wdc.c */
      46             : #define WDCDEBUG_PRINT(args, level) do {        \
      47             :         if ((wdcdebug_mask & (level)) != 0) \
      48             :                 printf args;                    \
      49             : } while (0)
      50             : #else
      51             : #define WDCDEBUG_PRINT(args, level)
      52             : #endif
      53             : 
      54             : #define ATAPARAMS_SIZE 512
      55             : 
      56             : /* Get the disk's parameters */
      57             : int
      58           0 : ata_get_params(struct ata_drive_datas *drvp, u_int8_t flags,
      59             :     struct ataparams *prms)
      60             : {
      61             :         char *tb;
      62           0 :         struct wdc_command wdc_c;
      63             :         int i;
      64             :         u_int16_t *p;
      65             :         int ret;
      66             : 
      67             :         WDCDEBUG_PRINT(("ata_get_params\n"), DEBUG_FUNCS);
      68             : 
      69           0 :         bzero(&wdc_c, sizeof(struct wdc_command));
      70             : 
      71           0 :         if (drvp->drive_flags & DRIVE_ATA) {
      72           0 :                 wdc_c.r_command = WDCC_IDENTIFY;
      73           0 :                 wdc_c.r_st_bmask = WDCS_DRDY;
      74           0 :                 wdc_c.r_st_pmask = 0;
      75           0 :                 wdc_c.timeout = 3000; /* 3s */
      76           0 :         } else if (drvp->drive_flags & DRIVE_ATAPI) {
      77           0 :                 wdc_c.r_command = ATAPI_IDENTIFY_DEVICE;
      78           0 :                 wdc_c.r_st_bmask = 0;
      79           0 :                 wdc_c.r_st_pmask = 0;
      80           0 :                 wdc_c.timeout = 10000; /* 10s */
      81             :         } else {
      82             :                 WDCDEBUG_PRINT(("ata_get_params: no disks\n"),
      83             :                     DEBUG_FUNCS|DEBUG_PROBE);
      84           0 :                 return CMD_ERR;
      85             :         }
      86             : 
      87           0 :         tb = dma_alloc(ATAPARAMS_SIZE, PR_NOWAIT | PR_ZERO);
      88           0 :         if (tb == NULL)
      89           0 :                 return CMD_AGAIN;
      90           0 :         wdc_c.flags = AT_READ | flags;
      91           0 :         wdc_c.data = tb;
      92           0 :         wdc_c.bcount = ATAPARAMS_SIZE;
      93             : 
      94           0 :         if ((ret = wdc_exec_command(drvp, &wdc_c)) != WDC_COMPLETE) {
      95             :                 WDCDEBUG_PRINT(("%s: wdc_exec_command failed: %d\n",
      96             :                     __func__, ret), DEBUG_PROBE);
      97           0 :                 dma_free(tb, ATAPARAMS_SIZE);
      98           0 :                 return CMD_AGAIN;
      99             :         }
     100             : 
     101           0 :         if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
     102             :                 WDCDEBUG_PRINT(("%s: IDENTIFY failed: 0x%x\n", __func__,
     103             :                     wdc_c.flags), DEBUG_PROBE);
     104             : 
     105           0 :                 dma_free(tb, ATAPARAMS_SIZE);
     106           0 :                 return CMD_ERR;
     107             :         } else {
     108             : #if BYTE_ORDER == BIG_ENDIAN
     109             :                 /* All the fields in the params structure are 16-bit
     110             :                    integers except for the ID strings which are char
     111             :                    strings.  The 16-bit integers are currently in
     112             :                    memory in little-endian, regardless of architecture.
     113             :                    So, they need to be swapped on big-endian architectures
     114             :                    before they are accessed through the ataparams structure.
     115             : 
     116             :                    The swaps below avoid touching the char strings.
     117             :                 */
     118             : 
     119             :                 swap16_multi((u_int16_t *)tb, 10);
     120             :                 swap16_multi((u_int16_t *)tb + 20, 3);
     121             :                 swap16_multi((u_int16_t *)tb + 47, ATAPARAMS_SIZE / 2 - 47);
     122             : #endif
     123             :                 /* Read in parameter block. */
     124           0 :                 bcopy(tb, prms, sizeof(struct ataparams));
     125             : 
     126             :                 /*
     127             :                  * Shuffle string byte order.
     128             :                  * ATAPI Mitsumi and NEC drives don't need this.
     129             :                  */
     130           0 :                 if ((prms->atap_config & WDC_CFG_ATAPI_MASK) ==
     131           0 :                     WDC_CFG_ATAPI &&
     132           0 :                     ((prms->atap_model[0] == 'N' &&
     133           0 :                         prms->atap_model[1] == 'E') ||
     134           0 :                      (prms->atap_model[0] == 'F' &&
     135           0 :                          prms->atap_model[1] == 'X'))) {
     136           0 :                         dma_free(tb, ATAPARAMS_SIZE);
     137           0 :                         return CMD_OK;
     138             :                 }
     139           0 :                 for (i = 0; i < sizeof(prms->atap_model); i += 2) {
     140           0 :                         p = (u_short *)(prms->atap_model + i);
     141           0 :                         *p = swap16(*p);
     142             :                 }
     143           0 :                 for (i = 0; i < sizeof(prms->atap_serial); i += 2) {
     144           0 :                         p = (u_short *)(prms->atap_serial + i);
     145           0 :                         *p = swap16(*p);
     146             :                 }
     147           0 :                 for (i = 0; i < sizeof(prms->atap_revision); i += 2) {
     148           0 :                         p = (u_short *)(prms->atap_revision + i);
     149           0 :                         *p = swap16(*p);
     150             :                 }
     151             : 
     152           0 :                 dma_free(tb, ATAPARAMS_SIZE);
     153           0 :                 return CMD_OK;
     154             :         }
     155           0 : }
     156             : 
     157             : int
     158           0 : ata_set_mode(struct ata_drive_datas *drvp, u_int8_t mode, u_int8_t flags)
     159             : {
     160           0 :         struct wdc_command wdc_c;
     161             : 
     162             :         WDCDEBUG_PRINT(("%s: mode=0x%x, flags=0x%x\n", __func__,
     163             :             mode, flags), DEBUG_PROBE);
     164             : 
     165           0 :         bzero(&wdc_c, sizeof(struct wdc_command));
     166             : 
     167           0 :         wdc_c.r_command = SET_FEATURES;
     168           0 :         wdc_c.r_st_bmask = 0;
     169           0 :         wdc_c.r_st_pmask = 0;
     170           0 :         wdc_c.r_features = WDSF_SET_MODE;
     171           0 :         wdc_c.r_count = mode;
     172           0 :         wdc_c.flags = flags;
     173           0 :         wdc_c.timeout = 1000; /* 1s */
     174           0 :         if (wdc_exec_command(drvp, &wdc_c) != WDC_COMPLETE)
     175           0 :                 return CMD_AGAIN;
     176             : 
     177             :         WDCDEBUG_PRINT(("%s: after wdc_exec_command() wdc_c.flags=0x%x\n",
     178             :             __func__, wdc_c.flags), DEBUG_PROBE);
     179             : 
     180           0 :         if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
     181           0 :                 return CMD_ERR;
     182             :         }
     183           0 :         return CMD_OK;
     184           0 : }
     185             : 
     186             : void
     187           0 : ata_dmaerr(struct ata_drive_datas *drvp)
     188             : {
     189             :         /*
     190             :          * Downgrade decision: if we get NERRS_MAX in NXFER.
     191             :          * We start with n_dmaerrs set to NERRS_MAX-1 so that the
     192             :          * first error within the first NXFER ops will immediately trigger
     193             :          * a downgrade.
     194             :          * If we got an error and n_xfers is bigger than NXFER reset counters.
     195             :          */
     196           0 :         drvp->n_dmaerrs++;
     197           0 :         if (drvp->n_dmaerrs >= NERRS_MAX && drvp->n_xfers <= NXFER) {
     198           0 :                 wdc_downgrade_mode(drvp);
     199           0 :                 drvp->n_dmaerrs = NERRS_MAX-1;
     200           0 :                 drvp->n_xfers = 0;
     201           0 :                 return;
     202             :         }
     203           0 :         if (drvp->n_xfers > NXFER) {
     204           0 :                 drvp->n_dmaerrs = 1; /* just got an error */
     205           0 :                 drvp->n_xfers = 1; /* restart counting from this error */
     206           0 :         }
     207           0 : }
     208             : 
     209             : void
     210           0 : ata_perror(struct ata_drive_datas *drvp, int errno, char *buf, size_t buf_len)
     211             : {
     212             :         static char *errstr0_3[] = {"address mark not found",
     213             :             "track 0 not found", "aborted command", "media change requested",
     214             :             "id not found", "media changed", "uncorrectable data error",
     215             :             "bad block detected"};
     216             :         static char *errstr4_5[] = {"",
     217             :             "no media/write protected", "aborted command",
     218             :             "media change requested", "id not found", "media changed",
     219             :             "uncorrectable data error", "interface CRC error"};
     220             :         char **errstr;
     221             :         int i;
     222             :         char *sep = "";
     223             :         size_t len = 0;
     224             : 
     225           0 :         if (drvp->ata_vers >= 4)
     226           0 :                 errstr = errstr4_5;
     227             :         else
     228             :                 errstr = errstr0_3;
     229             : 
     230           0 :         if (errno == 0) {
     231           0 :                 snprintf(buf, buf_len, "error not notified");
     232           0 :         }
     233             : 
     234           0 :         for (i = 0; i < 8; i++) {
     235           0 :                 if (errno & (1 << i)) {
     236           0 :                         snprintf(buf + len, buf_len - len, "%s%s", sep,
     237           0 :                             errstr[i]);
     238           0 :                         len = strlen(buf);
     239             :                         sep = ", ";
     240           0 :                 }
     241             :         }
     242           0 : }

Generated by: LCOV version 1.13