The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/drivers/at_wini/at_wini.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* This file contains the device dependent part of a driver for the IBM-AT
    2  * winchester controller.  Written by Adri Koppes.
    3  *
    4  * The file contains one entry point:
    5  *
    6  *   at_winchester_task:        main entry when system is brought up
    7  *
    8  * Changes:
    9  *   Aug 19, 2005   ATA PCI support, supports SATA  (Ben Gras)
   10  *   Nov 18, 2004   moved AT disk driver to user-space  (Jorrit N. Herder)
   11  *   Aug 20, 2004   watchdogs replaced by sync alarms  (Jorrit N. Herder)
   12  *   Mar 23, 2000   added ATAPI CDROM support  (Michael Temari)
   13  *   May 14, 2000   d-d/i rewrite  (Kees J. Bot)
   14  *   Apr 13, 1992   device dependent/independent split  (Kees J. Bot)
   15  */
   16 
   17 #include "at_wini.h"
   18 #include "../libpci/pci.h"
   19 
   20 #include <minix/sysutil.h>
   21 #include <minix/keymap.h>
   22 #include <sys/ioc_disk.h>
   23 
   24 #define ATAPI_DEBUG         0   /* To debug ATAPI code. */
   25 
   26 /* I/O Ports used by winchester disk controllers. */
   27 
   28 /* Read and write registers */
   29 #define REG_CMD_BASE0   0x1F0   /* command base register of controller 0 */
   30 #define REG_CMD_BASE1   0x170   /* command base register of controller 1 */
   31 #define REG_CTL_BASE0   0x3F6   /* control base register of controller 0 */
   32 #define REG_CTL_BASE1   0x376   /* control base register of controller 1 */
   33 
   34 #define REG_DATA            0   /* data register (offset from the base reg.) */
   35 #define REG_PRECOMP         1   /* start of write precompensation */
   36 #define REG_COUNT           2   /* sectors to transfer */
   37 #define REG_SECTOR          3   /* sector number */
   38 #define REG_CYL_LO          4   /* low byte of cylinder number */
   39 #define REG_CYL_HI          5   /* high byte of cylinder number */
   40 #define REG_LDH             6   /* lba, drive and head */
   41 #define   LDH_DEFAULT           0xA0    /* ECC enable, 512 bytes per sector */
   42 #define   LDH_LBA               0x40    /* Use LBA addressing */
   43 #define   ldh_init(drive)       (LDH_DEFAULT | ((drive) << 4))
   44 
   45 /* Read only registers */
   46 #define REG_STATUS          7   /* status */
   47 #define   STATUS_BSY            0x80    /* controller busy */
   48 #define   STATUS_RDY            0x40    /* drive ready */
   49 #define   STATUS_WF             0x20    /* write fault */
   50 #define   STATUS_SC             0x10    /* seek complete (obsolete) */
   51 #define   STATUS_DRQ            0x08    /* data transfer request */
   52 #define   STATUS_CRD            0x04    /* corrected data */
   53 #define   STATUS_IDX            0x02    /* index pulse */
   54 #define   STATUS_ERR            0x01    /* error */
   55 #define   STATUS_ADMBSY        0x100    /* administratively busy (software) */
   56 #define REG_ERROR           1   /* error code */
   57 #define   ERROR_BB              0x80    /* bad block */
   58 #define   ERROR_ECC             0x40    /* bad ecc bytes */
   59 #define   ERROR_ID              0x10    /* id not found */
   60 #define   ERROR_AC              0x04    /* aborted command */
   61 #define   ERROR_TK              0x02    /* track zero error */
   62 #define   ERROR_DM              0x01    /* no data address mark */
   63 
   64 /* Write only registers */
   65 #define REG_COMMAND         7   /* command */
   66 #define   CMD_IDLE              0x00    /* for w_command: drive idle */
   67 #define   CMD_RECALIBRATE       0x10    /* recalibrate drive */
   68 #define   CMD_READ              0x20    /* read data */
   69 #define   CMD_READ_EXT          0x24    /* read data (LBA48 addressed) */
   70 #define   CMD_WRITE             0x30    /* write data */
   71 #define   CMD_WRITE_EXT         0x34    /* write data (LBA48 addressed) */
   72 #define   CMD_READVERIFY        0x40    /* read verify */
   73 #define   CMD_FORMAT            0x50    /* format track */
   74 #define   CMD_SEEK              0x70    /* seek cylinder */
   75 #define   CMD_DIAG              0x90    /* execute device diagnostics */
   76 #define   CMD_SPECIFY           0x91    /* specify parameters */
   77 #define   ATA_IDENTIFY          0xEC    /* identify drive */
   78 /* #define REG_CTL              0x206   */ /* control register */
   79 #define REG_CTL         0       /* control register */
   80 #define   CTL_NORETRY           0x80    /* disable access retry */
   81 #define   CTL_NOECC             0x40    /* disable ecc retry */
   82 #define   CTL_EIGHTHEADS        0x08    /* more than eight heads */
   83 #define   CTL_RESET             0x04    /* reset controller */
   84 #define   CTL_INTDISABLE        0x02    /* disable interrupts */
   85 
   86 #if ENABLE_ATAPI
   87 #define   ERROR_SENSE           0xF0    /* sense key mask */
   88 #define     SENSE_NONE          0x00    /* no sense key */
   89 #define     SENSE_RECERR        0x10    /* recovered error */
   90 #define     SENSE_NOTRDY        0x20    /* not ready */
   91 #define     SENSE_MEDERR        0x30    /* medium error */
   92 #define     SENSE_HRDERR        0x40    /* hardware error */
   93 #define     SENSE_ILRQST        0x50    /* illegal request */
   94 #define     SENSE_UATTN         0x60    /* unit attention */
   95 #define     SENSE_DPROT         0x70    /* data protect */
   96 #define     SENSE_ABRT          0xb0    /* aborted command */
   97 #define     SENSE_MISCOM        0xe0    /* miscompare */
   98 #define   ERROR_MCR             0x08    /* media change requested */
   99 #define   ERROR_ABRT            0x04    /* aborted command */
  100 #define   ERROR_EOM             0x02    /* end of media detected */
  101 #define   ERROR_ILI             0x01    /* illegal length indication */
  102 #define REG_FEAT            1   /* features */
  103 #define   FEAT_OVERLAP          0x02    /* overlap */
  104 #define   FEAT_DMA              0x01    /* dma */
  105 #define REG_IRR             2   /* interrupt reason register */
  106 #define   IRR_REL               0x04    /* release */
  107 #define   IRR_IO                0x02    /* direction for xfer */
  108 #define   IRR_COD               0x01    /* command or data */
  109 #define REG_SAMTAG          3
  110 #define REG_CNT_LO          4   /* low byte of cylinder number */
  111 #define REG_CNT_HI          5   /* high byte of cylinder number */
  112 #define REG_DRIVE           6   /* drive select */
  113 #endif
  114 
  115 #define REG_STATUS          7   /* status */
  116 #define   STATUS_BSY            0x80    /* controller busy */
  117 #define   STATUS_DRDY           0x40    /* drive ready */
  118 #define   STATUS_DMADF          0x20    /* dma ready/drive fault */
  119 #define   STATUS_SRVCDSC        0x10    /* service or dsc */
  120 #define   STATUS_DRQ            0x08    /* data transfer request */
  121 #define   STATUS_CORR           0x04    /* correctable error occurred */
  122 #define   STATUS_CHECK          0x01    /* check error */
  123 
  124 #ifdef ENABLE_ATAPI
  125 #define   ATAPI_PACKETCMD       0xA0    /* packet command */
  126 #define   ATAPI_IDENTIFY        0xA1    /* identify drive */
  127 #define   SCSI_READ10           0x28    /* read from disk */
  128 #define   SCSI_SENSE            0x03    /* sense request */
  129 
  130 #define CD_SECTOR_SIZE          2048    /* sector size of a CD-ROM */
  131 #endif /* ATAPI */
  132 
  133 /* Interrupt request lines. */
  134 #define NO_IRQ           0      /* no IRQ set yet */
  135 
  136 #define ATAPI_PACKETSIZE        12
  137 #define SENSE_PACKETSIZE        18
  138 
  139 /* Common command block */
  140 struct command {
  141   u8_t  precomp;        /* REG_PRECOMP, etc. */
  142   u8_t  count;
  143   u8_t  sector;
  144   u8_t  cyl_lo;
  145   u8_t  cyl_hi;
  146   u8_t  ldh;
  147   u8_t  command;
  148 };
  149 
  150 /* Error codes */
  151 #define ERR              (-1)   /* general error */
  152 #define ERR_BAD_SECTOR   (-2)   /* block marked bad detected */
  153 
  154 /* Some controllers don't interrupt, the clock will wake us up. */
  155 #define WAKEUP          (32*HZ) /* drive may be out for 31 seconds max */
  156 
  157 /* Miscellaneous. */
  158 #define MAX_DRIVES         8
  159 #define COMPAT_DRIVES      4
  160 #if _WORD_SIZE > 2
  161 #define MAX_SECS         256    /* controller can transfer this many sectors */
  162 #else
  163 #define MAX_SECS         127    /* but not to a 16 bit process */
  164 #endif
  165 #define MAX_ERRORS         4    /* how often to try rd/wt before quitting */
  166 #define NR_MINORS       (MAX_DRIVES * DEV_PER_DRIVE)
  167 #define SUB_PER_DRIVE   (NR_PARTITIONS * NR_PARTITIONS)
  168 #define NR_SUBDEVS      (MAX_DRIVES * SUB_PER_DRIVE)
  169 #define DELAY_USECS     1000    /* controller timeout in microseconds */
  170 #define DELAY_TICKS        1    /* controller timeout in ticks */
  171 #define DEF_TIMEOUT_TICKS       300     /* controller timeout in ticks */
  172 #define RECOVERY_USECS 500000   /* controller recovery time in microseconds */
  173 #define RECOVERY_TICKS    30    /* controller recovery time in ticks */
  174 #define INITIALIZED     0x01    /* drive is initialized */
  175 #define DEAF            0x02    /* controller must be reset */
  176 #define SMART           0x04    /* drive supports ATA commands */
  177 #if ENABLE_ATAPI
  178 #define ATAPI           0x08    /* it is an ATAPI device */
  179 #else
  180 #define ATAPI              0    /* don't bother with ATAPI; optimise out */
  181 #endif
  182 #define IDENTIFIED      0x10    /* w_identify done successfully */
  183 #define IGNORING        0x20    /* w_identify failed once */
  184 
  185 /* Timeouts and max retries. */
  186 int timeout_ticks = DEF_TIMEOUT_TICKS, max_errors = MAX_ERRORS;
  187 int wakeup_ticks = WAKEUP;
  188 long w_standard_timeouts = 0, w_pci_debug = 0, w_instance = 0,
  189  w_lba48 = 0, atapi_debug = 0;
  190 
  191 int w_testing = 0, w_silent = 0;
  192 
  193 int w_next_drive = 0;
  194 
  195 /* Variables. */
  196 
  197 /* The struct wini is indexed by controller first, then drive (0-3).
  198  * Controller 0 is always the 'compatability' ide controller, at
  199  * the fixed locations, whether present or not.
  200  */
  201 PRIVATE struct wini {           /* main drive struct, one entry per drive */
  202   unsigned state;               /* drive state: deaf, initialized, dead */
  203   unsigned w_status;            /* device status register */
  204   unsigned base_cmd;            /* command base register */
  205   unsigned base_ctl;            /* control base register */
  206   unsigned irq;                 /* interrupt request line */
  207   unsigned irq_mask;            /* 1 << irq */
  208   unsigned irq_need_ack;        /* irq needs to be acknowledged */
  209   int irq_hook_id;              /* id of irq hook at the kernel */
  210   int lba48;                    /* supports lba48 */
  211   unsigned lcylinders;          /* logical number of cylinders (BIOS) */
  212   unsigned lheads;              /* logical number of heads */
  213   unsigned lsectors;            /* logical number of sectors per track */
  214   unsigned pcylinders;          /* physical number of cylinders (translated) */
  215   unsigned pheads;              /* physical number of heads */
  216   unsigned psectors;            /* physical number of sectors per track */
  217   unsigned ldhpref;             /* top four bytes of the LDH (head) register */
  218   unsigned precomp;             /* write precompensation cylinder / 4 */
  219   unsigned max_count;           /* max request for this drive */
  220   unsigned open_ct;             /* in-use count */
  221   struct device part[DEV_PER_DRIVE];    /* disks and partitions */
  222   struct device subpart[SUB_PER_DRIVE]; /* subpartitions */
  223 } wini[MAX_DRIVES], *w_wn;
  224 
  225 PRIVATE int w_device = -1;
  226 PRIVATE int w_controller = -1;
  227 PRIVATE int w_major = -1;
  228 PRIVATE char w_id_string[40];
  229 
  230 PRIVATE int win_tasknr;                 /* my task number */
  231 PRIVATE int w_command;                  /* current command in execution */
  232 PRIVATE u8_t w_byteval;                 /* used for SYS_IRQCTL */
  233 PRIVATE int w_drive;                    /* selected drive */
  234 PRIVATE int w_controller;               /* selected controller */
  235 PRIVATE struct device *w_dv;            /* device's base and size */
  236 
  237 FORWARD _PROTOTYPE( void init_params, (void)                            );
  238 FORWARD _PROTOTYPE( void init_drive, (struct wini *, int, int, int, 
  239                                         int, int, int));
  240 FORWARD _PROTOTYPE( void init_params_pci, (int)                         );
  241 FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr)  );
  242 FORWARD _PROTOTYPE( struct device *w_prepare, (int dev)                 );
  243 FORWARD _PROTOTYPE( int w_identify, (void)                              );
  244 FORWARD _PROTOTYPE( char *w_name, (void)                                );
  245 FORWARD _PROTOTYPE( int w_specify, (void)                               );
  246 FORWARD _PROTOTYPE( int w_io_test, (void)                               );
  247 FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position,
  248                                         iovec_t *iov, unsigned nr_req)  );
  249 FORWARD _PROTOTYPE( int com_out, (struct command *cmd)                  );
  250 FORWARD _PROTOTYPE( void w_need_reset, (void)                           );
  251 FORWARD _PROTOTYPE( void ack_irqs, (unsigned int)                       );
  252 FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
  253 FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr)    );
  254 FORWARD _PROTOTYPE( int w_hw_int, (struct driver *dp, message *m_ptr)   );
  255 FORWARD _PROTOTYPE( int com_simple, (struct command *cmd)               );
  256 FORWARD _PROTOTYPE( void w_timeout, (void)                              );
  257 FORWARD _PROTOTYPE( int w_reset, (void)                                 );
  258 FORWARD _PROTOTYPE( void w_intr_wait, (void)                            );
  259 FORWARD _PROTOTYPE( int at_intr_wait, (void)                            );
  260 FORWARD _PROTOTYPE( int w_waitfor, (int mask, int value)                );
  261 FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry)          );
  262 #if ENABLE_ATAPI
  263 FORWARD _PROTOTYPE( int atapi_sendpacket, (u8_t *packet, unsigned cnt)  );
  264 FORWARD _PROTOTYPE( int atapi_intr_wait, (void)                         );
  265 FORWARD _PROTOTYPE( int atapi_open, (void)                              );
  266 FORWARD _PROTOTYPE( void atapi_close, (void)                            );
  267 FORWARD _PROTOTYPE( int atapi_transfer, (int proc_nr, int opcode,
  268                         off_t position, iovec_t *iov, unsigned nr_req)  );
  269 #endif
  270 
  271 /* Entry points to this driver. */
  272 PRIVATE struct driver w_dtab = {
  273   w_name,               /* current device's name */
  274   w_do_open,            /* open or mount request, initialize device */
  275   w_do_close,           /* release device */
  276   do_diocntl,           /* get or set a partition's geometry */
  277   w_prepare,            /* prepare for I/O on a given minor device */
  278   w_transfer,           /* do the I/O */
  279   nop_cleanup,          /* nothing to clean up */
  280   w_geometry,           /* tell the geometry of the disk */
  281   nop_signal,           /* no cleanup needed on shutdown */
  282   nop_alarm,            /* ignore leftover alarms */
  283   nop_cancel,           /* ignore CANCELs */
  284   nop_select,           /* ignore selects */
  285   w_other,              /* catch-all for unrecognized commands and ioctls */
  286   w_hw_int              /* leftover hardware interrupts */
  287 };
  288 
  289 /*===========================================================================*
  290  *                              at_winchester_task                           *
  291  *===========================================================================*/
  292 PUBLIC int main()
  293 {
  294 /* Install signal handlers. Ask PM to transform signal into message. */
  295   struct sigaction sa;
  296 
  297   sa.sa_handler = SIG_MESS;
  298   sigemptyset(&sa.sa_mask);
  299   sa.sa_flags = 0;
  300   if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno);
  301 
  302   /* Set special disk parameters then call the generic main loop. */
  303   init_params();
  304   signal(SIGTERM, SIG_IGN);
  305   driver_task(&w_dtab);
  306   return(OK);
  307 }
  308 
  309 /*===========================================================================*
  310  *                              init_params                                  *
  311  *===========================================================================*/
  312 PRIVATE void init_params()
  313 {
  314 /* This routine is called at startup to initialize the drive parameters. */
  315 
  316   u16_t parv[2];
  317   unsigned int vector, size;
  318   int drive, nr_drives;
  319   struct wini *wn;
  320   u8_t params[16];
  321   int s;
  322 
  323   /* Boot variables. */
  324   env_parse("ata_std_timeout", "d", 0, &w_standard_timeouts, 0, 1);
  325   env_parse("ata_pci_debug", "d", 0, &w_pci_debug, 0, 1);
  326   env_parse("ata_instance", "d", 0, &w_instance, 0, 8);
  327   env_parse("ata_lba48", "d", 0, &w_lba48, 0, 1);
  328   env_parse("atapi_debug", "d", 0, &atapi_debug, 0, 1);
  329 
  330   if (w_instance == 0) {
  331           /* Get the number of drives from the BIOS data area */
  332           if ((s=sys_vircopy(SELF, BIOS_SEG, NR_HD_DRIVES_ADDR, 
  333                         SELF, D, (vir_bytes) params, NR_HD_DRIVES_SIZE)) != OK)
  334                 panic(w_name(), "Couldn't read BIOS", s);
  335           if ((nr_drives = params[0]) > 2) nr_drives = 2;
  336 
  337           for (drive = 0, wn = wini; drive < COMPAT_DRIVES; drive++, wn++) {
  338                 if (drive < nr_drives) {
  339                     /* Copy the BIOS parameter vector */
  340                     vector = (drive == 0) ? BIOS_HD0_PARAMS_ADDR:BIOS_HD1_PARAMS_ADDR;
  341                     size = (drive == 0) ? BIOS_HD0_PARAMS_SIZE:BIOS_HD1_PARAMS_SIZE;
  342                     if ((s=sys_vircopy(SELF, BIOS_SEG, vector,
  343                                         SELF, D, (vir_bytes) parv, size)) != OK)
  344                                 panic(w_name(), "Couldn't read BIOS", s);
  345         
  346                         /* Calculate the address of the parameters and copy them */
  347                         if ((s=sys_vircopy(
  348                                 SELF, BIOS_SEG, hclick_to_physb(parv[1]) + parv[0],
  349                                 SELF, D, (phys_bytes) params, 16L))!=OK)
  350                             panic(w_name(),"Couldn't copy parameters", s);
  351         
  352                         /* Copy the parameters to the structures of the drive */
  353                         wn->lcylinders = bp_cylinders(params);
  354                         wn->lheads = bp_heads(params);
  355                         wn->lsectors = bp_sectors(params);
  356                         wn->precomp = bp_precomp(params) >> 2;
  357                 }
  358 
  359                 /* Fill in non-BIOS parameters. */
  360                 init_drive(wn,
  361                         drive < 2 ? REG_CMD_BASE0 : REG_CMD_BASE1,
  362                         drive < 2 ? REG_CTL_BASE0 : REG_CTL_BASE1,
  363                         NO_IRQ, 0, 0, drive);
  364                 w_next_drive++;
  365         }
  366   }
  367 
  368   /* Look for controllers on the pci bus. Skip none the first instance,
  369    * skip one and then 2 for every instance, for every next instance.
  370    */
  371   if (w_instance == 0)
  372         init_params_pci(0);
  373   else
  374         init_params_pci(w_instance*2-1);
  375 
  376 }
  377 
  378 #define ATA_IF_NOTCOMPAT1 (1L << 0)
  379 #define ATA_IF_NOTCOMPAT2 (1L << 2)
  380 
  381 /*===========================================================================*
  382  *                              init_drive                                   *
  383  *===========================================================================*/
  384 PRIVATE void init_drive(struct wini *w, int base_cmd, int base_ctl, int irq, int ack, int hook, int drive)
  385 {
  386         w->state = 0;
  387         w->w_status = 0;
  388         w->base_cmd = base_cmd;
  389         w->base_ctl = base_ctl;
  390         w->irq = irq;
  391         w->irq_mask = 1 << irq;
  392         w->irq_need_ack = ack;
  393         w->irq_hook_id = hook;
  394         w->ldhpref = ldh_init(drive);
  395         w->max_count = MAX_SECS << SECTOR_SHIFT;
  396         w->lba48 = 0;
  397 }
  398 
  399 /*===========================================================================*
  400  *                              init_params_pci                              *
  401  *===========================================================================*/
  402 PRIVATE void init_params_pci(int skip)
  403 {
  404   int r, devind, drive;
  405   u16_t vid, did;
  406   pci_init();
  407   for(drive = w_next_drive; drive < MAX_DRIVES; drive++)
  408         wini[drive].state = IGNORING;
  409   for(r = pci_first_dev(&devind, &vid, &did);
  410         r != 0 && w_next_drive < MAX_DRIVES; r = pci_next_dev(&devind, &vid, &did)) {
  411         int interface, irq, irq_hook;
  412         /* Base class must be 01h (mass storage), subclass must
  413          * be 01h (ATA).
  414          */
  415         if (pci_attr_r8(devind, PCI_BCR) != 0x01 ||
  416            pci_attr_r8(devind, PCI_SCR) != 0x01) {
  417            continue;
  418         }
  419         /* Found a controller.
  420          * Programming interface register tells us more.
  421          */
  422         interface = pci_attr_r8(devind, PCI_PIFR);
  423         irq = pci_attr_r8(devind, PCI_ILR);
  424 
  425         /* Any non-compat drives? */
  426         if (interface & (ATA_IF_NOTCOMPAT1 | ATA_IF_NOTCOMPAT2)) {
  427                 int s;
  428                 irq_hook = irq;
  429                 if (skip > 0) {
  430                         if (w_pci_debug) printf("atapci skipping controller (remain %d)\n", skip);
  431                         skip--;
  432                         continue;
  433                 }
  434                 if ((s=sys_irqsetpolicy(irq, 0, &irq_hook)) != OK) {
  435                         printf("atapci: couldn't set IRQ policy %d\n", irq);
  436                         continue;
  437                 }
  438                 if ((s=sys_irqenable(&irq_hook)) != OK) {
  439                         printf("atapci: couldn't enable IRQ line %d\n", irq);
  440                         continue;
  441                 }
  442         } else {
  443                 /* If not.. this is not the ata-pci controller we're
  444                  * looking for.
  445                  */
  446                 if (w_pci_debug) printf("atapci skipping compatability controller\n");
  447                 continue;
  448         }
  449 
  450         /* Primary channel not in compatability mode? */
  451         if (interface & ATA_IF_NOTCOMPAT1) {
  452                 u32_t base_cmd, base_ctl;
  453                 base_cmd = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
  454                 base_ctl = pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0;
  455                 if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) {
  456                         init_drive(&wini[w_next_drive],
  457                                 base_cmd, base_ctl, irq, 1, irq_hook, 0);
  458                         init_drive(&wini[w_next_drive+1],
  459                                 base_cmd, base_ctl, irq, 1, irq_hook, 1);
  460                         if (w_pci_debug)
  461                                 printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq);
  462                 } else printf("atapci: ignored drives on primary channel, base %x\n", base_cmd);
  463         }
  464 
  465         /* Secondary channel not in compatability mode? */
  466         if (interface & ATA_IF_NOTCOMPAT2) {
  467                 u32_t base_cmd, base_ctl;
  468                 base_cmd = pci_attr_r32(devind, PCI_BAR_3) & 0xffffffe0;
  469                 base_ctl = pci_attr_r32(devind, PCI_BAR_4) & 0xffffffe0;
  470                 if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) {
  471                         init_drive(&wini[w_next_drive+2],
  472                                 base_cmd, base_ctl, irq, 1, irq_hook, 2);
  473                         init_drive(&wini[w_next_drive+3],
  474                                 base_cmd, base_ctl, irq, 1, irq_hook, 3);
  475                         if (w_pci_debug)
  476                                 printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq);
  477                 } else printf("atapci: ignored drives on secondary channel, base %x\n", base_cmd);
  478         }
  479         w_next_drive += 4;
  480   }
  481 }
  482 
  483 /*===========================================================================*
  484  *                              w_do_open                                    *
  485  *===========================================================================*/
  486 PRIVATE int w_do_open(dp, m_ptr)
  487 struct driver *dp;
  488 message *m_ptr;
  489 {
  490 /* Device open: Initialize the controller and read the partition table. */
  491 
  492   struct wini *wn;
  493 
  494   if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  495 
  496   wn = w_wn;
  497 
  498   /* If we've probed it before and it failed, don't probe it again. */
  499   if (wn->state & IGNORING) return ENXIO;
  500 
  501   /* If we haven't identified it yet, or it's gone deaf, 
  502    * (re-)identify it.
  503    */
  504   if (!(wn->state & IDENTIFIED) || (wn->state & DEAF)) {
  505         /* Try to identify the device. */
  506         if (w_identify() != OK) {
  507 #if VERBOSE
  508                 printf("%s: probe failed\n", w_name());
  509 #endif
  510                 if (wn->state & DEAF) w_reset();
  511                 wn->state = IGNORING;
  512                 return(ENXIO);
  513         }
  514           /* Do a test transaction unless it's a CD drive (then
  515            * we can believe the controller, and a test may fail
  516            * due to no CD being in the drive). If it fails, ignore
  517            * the device forever.
  518            */
  519           if (!(wn->state & ATAPI) && w_io_test() != OK) {
  520                 wn->state |= IGNORING;
  521                 return(ENXIO);
  522           }
  523 
  524 #if VERBOSE
  525           printf("%s: AT driver detected ", w_name());
  526           if (wn->state & (SMART|ATAPI)) {
  527                 printf("%.40s\n", w_id_string);
  528           } else {
  529                 printf("%ux%ux%u\n", wn->pcylinders, wn->pheads, wn->psectors);
  530           }
  531 #endif
  532   }
  533 
  534 #if ENABLE_ATAPI
  535    if ((wn->state & ATAPI) && (m_ptr->COUNT & W_BIT))
  536         return(EACCES);
  537 #endif
  538 
  539    /* If it's not an ATAPI device, then don't open with RO_BIT. */
  540    if (!(wn->state & ATAPI) && (m_ptr->COUNT & RO_BIT)) return EACCES;
  541 
  542   /* Partition the drive if it's being opened for the first time,
  543    * or being opened after being closed.
  544    */
  545   if (wn->open_ct == 0) {
  546 #if ENABLE_ATAPI
  547         if (wn->state & ATAPI) {
  548                 int r;
  549                 if ((r = atapi_open()) != OK) return(r);
  550         }
  551 #endif
  552 
  553         /* Partition the disk. */
  554         partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY, wn->state & ATAPI);
  555   }
  556   wn->open_ct++;
  557   return(OK);
  558 }
  559 
  560 /*===========================================================================*
  561  *                              w_prepare                                    *
  562  *===========================================================================*/
  563 PRIVATE struct device *w_prepare(int device)
  564 {
  565 /* Prepare for I/O on a device. */
  566 struct wini *prev_wn;
  567 prev_wn = w_wn;
  568   w_device = device;
  569 
  570   if (device < NR_MINORS) {                     /* d0, d0p[0-3], d1, ... */
  571         w_drive = device / DEV_PER_DRIVE;       /* save drive number */
  572         w_wn = &wini[w_drive];
  573         w_dv = &w_wn->part[device % DEV_PER_DRIVE];
  574   } else
  575   if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/
  576         w_drive = device / SUB_PER_DRIVE;
  577         w_wn = &wini[w_drive];
  578         w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
  579   } else {
  580         w_device = -1;
  581         return(NIL_DEV);
  582   }
  583   return(w_dv);
  584 }
  585 
  586 /*===========================================================================*
  587  *                              w_identify                                   *
  588  *===========================================================================*/
  589 PRIVATE int w_identify()
  590 {
  591 /* Find out if a device exists, if it is an old AT disk, or a newer ATA
  592  * drive, a removable media device, etc.
  593  */
  594 
  595   struct wini *wn = w_wn;
  596   struct command cmd;
  597   int i, s;
  598   unsigned long size;
  599 #define id_byte(n)      (&tmp_buf[2 * (n)])
  600 #define id_word(n)      (((u16_t) id_byte(n)[0] <<  0) \
  601                         |((u16_t) id_byte(n)[1] <<  8))
  602 #define id_longword(n)  (((u32_t) id_byte(n)[0] <<  0) \
  603                         |((u32_t) id_byte(n)[1] <<  8) \
  604                         |((u32_t) id_byte(n)[2] << 16) \
  605                         |((u32_t) id_byte(n)[3] << 24))
  606 
  607   /* Try to identify the device. */
  608   cmd.ldh     = wn->ldhpref;
  609   cmd.command = ATA_IDENTIFY;
  610   if (com_simple(&cmd) == OK) {
  611         /* This is an ATA device. */
  612         wn->state |= SMART;
  613 
  614         /* Device information. */
  615         if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, SECTOR_SIZE)) != OK)
  616                 panic(w_name(),"Call to sys_insw() failed", s);
  617 
  618         /* Why are the strings byte swapped??? */
  619         for (i = 0; i < 40; i++) w_id_string[i] = id_byte(27)[i^1];
  620 
  621         /* Preferred CHS translation mode. */
  622         wn->pcylinders = id_word(1);
  623         wn->pheads = id_word(3);
  624         wn->psectors = id_word(6);
  625         size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;
  626 
  627         if ((id_byte(49)[1] & 0x02) && size > 512L*1024*2) {
  628                 /* Drive is LBA capable and is big enough to trust it to
  629                  * not make a mess of it.
  630                  */
  631                 wn->ldhpref |= LDH_LBA;
  632                 size = id_longword(60);
  633 
  634                 if (w_lba48 && ((id_word(83)) & (1L << 10))) {
  635                         /* Drive is LBA48 capable (and LBA48 is turned on). */
  636                         if (id_word(102) || id_word(103)) {
  637                                 /* If no. of sectors doesn't fit in 32 bits,
  638                                  * trunacte to this. So it's LBA32 for now.
  639                                  * This can still address devices up to 2TB
  640                                  * though.
  641                                  */
  642                                 size = ULONG_MAX;
  643                         } else {
  644                                 /* Actual number of sectors fits in 32 bits. */
  645                                 size = id_longword(100);
  646                         }
  647 
  648                         wn->lba48 = 1;
  649                 }
  650         }
  651 
  652         if (wn->lcylinders == 0) {
  653                 /* No BIOS parameters?  Then make some up. */
  654                 wn->lcylinders = wn->pcylinders;
  655                 wn->lheads = wn->pheads;
  656                 wn->lsectors = wn->psectors;
  657                 while (wn->lcylinders > 1024) {
  658                         wn->lheads *= 2;
  659                         wn->lcylinders /= 2;
  660                 }
  661         }
  662 #if ENABLE_ATAPI
  663   } else
  664   if (cmd.command = ATAPI_IDENTIFY, com_simple(&cmd) == OK) {
  665         /* An ATAPI device. */
  666         wn->state |= ATAPI;
  667 
  668         /* Device information. */
  669         if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, 512)) != OK)
  670                 panic(w_name(),"Call to sys_insw() failed", s);
  671 
  672         /* Why are the strings byte swapped??? */
  673         for (i = 0; i < 40; i++) w_id_string[i] = id_byte(27)[i^1];
  674 
  675         size = 0;       /* Size set later. */
  676 #endif
  677   } else {
  678         /* Not an ATA device; no translations, no special features.  Don't
  679          * touch it unless the BIOS knows about it.
  680          */
  681         if (wn->lcylinders == 0) { return(ERR); }       /* no BIOS parameters */
  682         wn->pcylinders = wn->lcylinders;
  683         wn->pheads = wn->lheads;
  684         wn->psectors = wn->lsectors;
  685         size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;
  686   }
  687 
  688   /* Size of the whole drive */
  689   wn->part[0].dv_size = mul64u(size, SECTOR_SIZE);
  690 
  691   /* Reset/calibrate (where necessary) */
  692   if (w_specify() != OK && w_specify() != OK) {
  693         return(ERR);
  694   }
  695 
  696   if (wn->irq == NO_IRQ) {
  697           /* Everything looks OK; register IRQ so we can stop polling. */
  698           wn->irq = w_drive < 2 ? AT_WINI_0_IRQ : AT_WINI_1_IRQ;
  699           wn->irq_hook_id = wn->irq;    /* id to be returned if interrupt occurs */
  700           if ((s=sys_irqsetpolicy(wn->irq, IRQ_REENABLE, &wn->irq_hook_id)) != OK) 
  701                 panic(w_name(), "couldn't set IRQ policy", s);
  702           if ((s=sys_irqenable(&wn->irq_hook_id)) != OK)
  703                 panic(w_name(), "couldn't enable IRQ line", s);
  704   }
  705   wn->state |= IDENTIFIED;
  706   return(OK);
  707 }
  708 
  709 /*===========================================================================*
  710  *                              w_name                                       *
  711  *===========================================================================*/
  712 PRIVATE char *w_name()
  713 {
  714 /* Return a name for the current device. */
  715   static char name[] = "AT-D0";
  716 
  717   name[4] = '' + w_drive;
  718   return name;
  719 }
  720 
  721 /*===========================================================================*
  722  *                              w_io_test                                    *
  723  *===========================================================================*/
  724 PRIVATE int w_io_test(void)
  725 {
  726         int r, save_dev;
  727         int save_timeout, save_errors, save_wakeup;
  728         iovec_t iov;
  729 #ifdef CD_SECTOR_SIZE
  730         static char buf[CD_SECTOR_SIZE];
  731 #else
  732         static char buf[SECTOR_SIZE];
  733 #endif
  734 
  735         iov.iov_addr = (vir_bytes) buf;
  736         iov.iov_size = sizeof(buf);
  737         save_dev = w_device;
  738 
  739         /* Reduce timeout values for this test transaction. */
  740         save_timeout = timeout_ticks;
  741         save_errors = max_errors;
  742         save_wakeup = wakeup_ticks;
  743 
  744         if (!w_standard_timeouts) {
  745                 timeout_ticks = HZ * 4;
  746                 wakeup_ticks = HZ * 6;
  747                 max_errors = 3;
  748         }
  749 
  750         w_testing = 1;
  751 
  752         /* Try I/O on the actual drive (not any (sub)partition). */
  753         if (w_prepare(w_drive * DEV_PER_DRIVE) == NIL_DEV)
  754                 panic(w_name(), "Couldn't switch devices", NO_NUM);
  755 
  756         r = w_transfer(SELF, DEV_GATHER, 0, &iov, 1);
  757 
  758         /* Switch back. */
  759         if (w_prepare(save_dev) == NIL_DEV)
  760                 panic(w_name(), "Couldn't switch back devices", NO_NUM);
  761 
  762         /* Restore parameters. */
  763         timeout_ticks = save_timeout;
  764         max_errors = save_errors;
  765         wakeup_ticks = save_wakeup;
  766         w_testing = 0;
  767 
  768         /* Test if everything worked. */
  769         if (r != OK || iov.iov_size != 0) {
  770                 return ERR;
  771         }
  772 
  773         /* Everything worked. */
  774 
  775         return OK;
  776 }
  777 
  778 /*===========================================================================*
  779  *                              w_specify                                    *
  780  *===========================================================================*/
  781 PRIVATE int w_specify()
  782 {
  783 /* Routine to initialize the drive after boot or when a reset is needed. */
  784 
  785   struct wini *wn = w_wn;
  786   struct command cmd;
  787 
  788   if ((wn->state & DEAF) && w_reset() != OK) {
  789         return(ERR);
  790   }
  791 
  792   if (!(wn->state & ATAPI)) {
  793         /* Specify parameters: precompensation, number of heads and sectors. */
  794         cmd.precomp = wn->precomp;
  795         cmd.count   = wn->psectors;
  796         cmd.ldh     = w_wn->ldhpref | (wn->pheads - 1);
  797         cmd.command = CMD_SPECIFY;              /* Specify some parameters */
  798 
  799         /* Output command block and see if controller accepts the parameters. */
  800         if (com_simple(&cmd) != OK) return(ERR);
  801 
  802         if (!(wn->state & SMART)) {
  803                 /* Calibrate an old disk. */
  804                 cmd.sector  = 0;
  805                 cmd.cyl_lo  = 0;
  806                 cmd.cyl_hi  = 0;
  807                 cmd.ldh     = w_wn->ldhpref;
  808                 cmd.command = CMD_RECALIBRATE;
  809 
  810                 if (com_simple(&cmd) != OK) return(ERR);
  811         }
  812   }
  813   wn->state |= INITIALIZED;
  814   return(OK);
  815 }
  816 
  817 /*===========================================================================*
  818  *                              do_transfer                                  *
  819  *===========================================================================*/
  820 PRIVATE int do_transfer(struct wini *wn, unsigned int precomp, unsigned int count,
  821         unsigned int sector, unsigned int opcode)
  822 {
  823         struct command cmd;
  824         unsigned secspcyl = wn->pheads * wn->psectors;
  825 
  826         cmd.precomp = precomp;
  827         cmd.count   = count;
  828         cmd.command = opcode == DEV_SCATTER ? CMD_WRITE : CMD_READ;
  829         /* 
  830         if (w_lba48 && wn->lba48) {
  831         } else  */
  832         if (wn->ldhpref & LDH_LBA) {
  833                 cmd.sector  = (sector >>  0) & 0xFF;
  834                 cmd.cyl_lo  = (sector >>  8) & 0xFF;
  835                 cmd.cyl_hi  = (sector >> 16) & 0xFF;
  836                 cmd.ldh     = wn->ldhpref | ((sector >> 24) & 0xF);
  837         } else {
  838                 int cylinder, head, sec;
  839                 cylinder = sector / secspcyl;
  840                 head = (sector % secspcyl) / wn->psectors;
  841                 sec = sector % wn->psectors;
  842                 cmd.sector  = sec + 1;
  843                 cmd.cyl_lo  = cylinder & BYTE;
  844                 cmd.cyl_hi  = (cylinder >> 8) & BYTE;
  845                 cmd.ldh     = wn->ldhpref | head;
  846         }
  847 
  848         return com_out(&cmd);
  849 }
  850 
  851 /*===========================================================================*
  852  *                              w_transfer                                   *
  853  *===========================================================================*/
  854 PRIVATE int w_transfer(proc_nr, opcode, position, iov, nr_req)
  855 int proc_nr;                    /* process doing the request */
  856 int opcode;                     /* DEV_GATHER or DEV_SCATTER */
  857 off_t position;                 /* offset on device to read or write */
  858 iovec_t *iov;                   /* pointer to read or write request vector */
  859 unsigned nr_req;                /* length of request vector */
  860 {
  861   struct wini *wn = w_wn;
  862   iovec_t *iop, *iov_end = iov + nr_req;
  863   int r, s, errors;
  864   unsigned long block;
  865   unsigned long dv_size = cv64ul(w_dv->dv_size);
  866   unsigned cylinder, head, sector, nbytes;
  867 
  868 #if ENABLE_ATAPI
  869   if (w_wn->state & ATAPI) {
  870         return atapi_transfer(proc_nr, opcode, position, iov, nr_req);
  871   }
  872 #endif
  873 
  874   
  875 
  876   /* Check disk address. */
  877   if ((position & SECTOR_MASK) != 0) return(EINVAL);
  878 
  879   errors = 0;
  880 
  881   while (nr_req > 0) {
  882         /* How many bytes to transfer? */
  883         nbytes = 0;
  884         for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size;
  885         if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
  886 
  887         /* Which block on disk and how close to EOF? */
  888         if (position >= dv_size) return(OK);            /* At EOF */
  889         if (position + nbytes > dv_size) nbytes = dv_size - position;
  890         block = div64u(add64ul(w_dv->dv_base, position), SECTOR_SIZE);
  891 
  892         if (nbytes >= wn->max_count) {
  893                 /* The drive can't do more then max_count at once. */
  894                 nbytes = wn->max_count;
  895         }
  896 
  897         /* First check to see if a reinitialization is needed. */
  898         if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
  899 
  900         /* Tell the controller to transfer nbytes bytes. */
  901         r = do_transfer(wn, wn->precomp, ((nbytes >> SECTOR_SHIFT) & BYTE),
  902                 block, opcode);
  903 
  904         while (r == OK && nbytes > 0) {
  905                 /* For each sector, wait for an interrupt and fetch the data
  906                  * (read), or supply data to the controller and wait for an
  907                  * interrupt (write).
  908                  */
  909 
  910                 if (opcode == DEV_GATHER) {
  911                         /* First an interrupt, then data. */
  912                         if ((r = at_intr_wait()) != OK) {
  913                                 /* An error, send data to the bit bucket. */
  914                                 if (w_wn->w_status & STATUS_DRQ) {
  915         if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, SECTOR_SIZE)) != OK)
  916                 panic(w_name(),"Call to sys_insw() failed", s);
  917                                 }
  918                                 break;
  919                         }
  920                 }
  921 
  922                 /* Wait for data transfer requested. */
  923                 if (!w_waitfor(STATUS_DRQ, STATUS_DRQ)) { r = ERR; break; }
  924 
  925                 /* Copy bytes to or from the device's buffer. */
  926                 if (opcode == DEV_GATHER) {
  927         if ((s=sys_insw(wn->base_cmd + REG_DATA, proc_nr, (void *) iov->iov_addr, SECTOR_SIZE)) != OK)
  928                 panic(w_name(),"Call to sys_insw() failed", s);
  929                 } else {
  930         if ((s=sys_outsw(wn->base_cmd + REG_DATA, proc_nr, (void *) iov->iov_addr, SECTOR_SIZE)) != OK)
  931                 panic(w_name(),"Call to sys_insw() failed", s);
  932 
  933                         /* Data sent, wait for an interrupt. */
  934                         if ((r = at_intr_wait()) != OK) break;
  935                 }
  936 
  937                 /* Book the bytes successfully transferred. */
  938                 nbytes -= SECTOR_SIZE;
  939                 position += SECTOR_SIZE;
  940                 iov->iov_addr += SECTOR_SIZE;
  941                 if ((iov->iov_size -= SECTOR_SIZE) == 0) { iov++; nr_req--; }
  942         }
  943 
  944         /* Any errors? */
  945         if (r != OK) {
  946                 /* Don't retry if sector marked bad or too many errors. */
  947                 if (r == ERR_BAD_SECTOR || ++errors == max_errors) {
  948                         w_command = CMD_IDLE;
  949                         return(EIO);
  950                 }
  951         }
  952   }
  953 
  954   w_command = CMD_IDLE;
  955   return(OK);
  956 }
  957 
  958 /*===========================================================================*
  959  *                              com_out                                      *
  960  *===========================================================================*/
  961 PRIVATE int com_out(cmd)
  962 struct command *cmd;            /* Command block */
  963 {
  964 /* Output the command block to the winchester controller and return status */
  965 
  966   struct wini *wn = w_wn;
  967   unsigned base_cmd = wn->base_cmd;
  968   unsigned base_ctl = wn->base_ctl;
  969   pvb_pair_t outbyte[7];                /* vector for sys_voutb() */
  970   int s;                                /* status for sys_(v)outb() */
  971 
  972   if (w_wn->state & IGNORING) return ERR;
  973 
  974   if (!w_waitfor(STATUS_BSY, 0)) {
  975         printf("%s: controller not ready\n", w_name());
  976         return(ERR);
  977   }
  978 
  979   /* Select drive. */
  980   if ((s=sys_outb(base_cmd + REG_LDH, cmd->ldh)) != OK)
  981         panic(w_name(),"Couldn't write register to select drive",s);
  982 
  983   if (!w_waitfor(STATUS_BSY, 0)) {
  984         printf("%s: com_out: drive not ready\n", w_name());
  985         return(ERR);
  986   }
  987 
  988   /* Schedule a wakeup call, some controllers are flaky. This is done with
  989    * a synchronous alarm. If a timeout occurs a SYN_ALARM message is sent
  990    * from HARDWARE, so that w_intr_wait() can call w_timeout() in case the
  991    * controller was not able to execute the command. Leftover timeouts are
  992    * simply ignored by the main loop. 
  993    */
  994   sys_setalarm(wakeup_ticks, 0);
  995 
  996   wn->w_status = STATUS_ADMBSY;
  997   w_command = cmd->command;
  998   pv_set(outbyte[0], base_ctl + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0);
  999   pv_set(outbyte[1], base_cmd + REG_PRECOMP, cmd->precomp);
 1000   pv_set(outbyte[2], base_cmd + REG_COUNT, cmd->count);
 1001   pv_set(outbyte[3], base_cmd + REG_SECTOR, cmd->sector);
 1002   pv_set(outbyte[4], base_cmd + REG_CYL_LO, cmd->cyl_lo);
 1003   pv_set(outbyte[5], base_cmd + REG_CYL_HI, cmd->cyl_hi);
 1004   pv_set(outbyte[6], base_cmd + REG_COMMAND, cmd->command);
 1005   if ((s=sys_voutb(outbyte,7)) != OK)
 1006         panic(w_name(),"Couldn't write registers with sys_voutb()",s);
 1007   return(OK);
 1008 }
 1009 
 1010 /*===========================================================================*
 1011  *                              w_need_reset                                 *
 1012  *===========================================================================*/
 1013 PRIVATE void w_need_reset()
 1014 {
 1015 /* The controller needs to be reset. */
 1016   struct wini *wn;
 1017   int dr = 0;
 1018 
 1019   for (wn = wini; wn < &wini[MAX_DRIVES]; wn++, dr++) {
 1020         if (wn->base_cmd == w_wn->base_cmd) {
 1021                 wn->state |= DEAF;
 1022                 wn->state &= ~INITIALIZED;
 1023         }
 1024   }
 1025 }
 1026 
 1027 /*===========================================================================*
 1028  *                              w_do_close                                   *
 1029  *===========================================================================*/
 1030 PRIVATE int w_do_close(dp, m_ptr)
 1031 struct driver *dp;
 1032 message *m_ptr;
 1033 {
 1034 /* Device close: Release a device. */
 1035   if (w_prepare(m_ptr->DEVICE) == NIL_DEV)
 1036         return(ENXIO);
 1037   w_wn->open_ct--;
 1038 #if ENABLE_ATAPI
 1039   if (w_wn->open_ct == 0 && (w_wn->state & ATAPI)) atapi_close();
 1040 #endif
 1041   return(OK);
 1042 }
 1043 
 1044 /*===========================================================================*
 1045  *                              com_simple                                   *
 1046  *===========================================================================*/
 1047 PRIVATE int com_simple(cmd)
 1048 struct command *cmd;            /* Command block */
 1049 {
 1050 /* A simple controller command, only one interrupt and no data-out phase. */
 1051   int r;
 1052 
 1053   if (w_wn->state & IGNORING) return ERR;
 1054 
 1055   if ((r = com_out(cmd)) == OK) r = at_intr_wait();
 1056   w_command = CMD_IDLE;
 1057   return(r);
 1058 }
 1059 
 1060 /*===========================================================================*
 1061  *                              w_timeout                                    *
 1062  *===========================================================================*/
 1063 PRIVATE void w_timeout(void)
 1064 {
 1065   struct wini *wn = w_wn;
 1066 
 1067   switch (w_command) {
 1068   case CMD_IDLE:
 1069         break;          /* fine */
 1070   case CMD_READ:
 1071   case CMD_WRITE:
 1072         /* Impossible, but not on PC's:  The controller does not respond. */
 1073 
 1074         /* Limiting multisector I/O seems to help. */
 1075         if (wn->max_count > 8 * SECTOR_SIZE) {
 1076                 wn->max_count = 8 * SECTOR_SIZE;
 1077         } else {
 1078                 wn->max_count = SECTOR_SIZE;
 1079         }
 1080         /*FALL THROUGH*/
 1081   default:
 1082         /* Some other command. */
 1083         if (w_testing)  wn->state |= IGNORING;  /* Kick out this drive. */
 1084         else if (!w_silent) printf("%s: timeout on command %02x\n", w_name(), w_command);
 1085         w_need_reset();
 1086         wn->w_status = 0;
 1087   }
 1088 }
 1089 
 1090 /*===========================================================================*
 1091  *                              w_reset                                      *
 1092  *===========================================================================*/
 1093 PRIVATE int w_reset()
 1094 {
 1095 /* Issue a reset to the controller.  This is done after any catastrophe,
 1096  * like the controller refusing to respond.
 1097  */
 1098   int s;
 1099   struct wini *wn = w_wn;
 1100 
 1101   /* Don't bother if this drive is forgotten. */
 1102   if (w_wn->state & IGNORING) return ERR;
 1103 
 1104   /* Wait for any internal drive recovery. */
 1105   tickdelay(RECOVERY_TICKS);
 1106 
 1107   /* Strobe reset bit */
 1108   if ((s=sys_outb(wn->base_ctl + REG_CTL, CTL_RESET)) != OK)
 1109         panic(w_name(),"Couldn't strobe reset bit",s);
 1110   tickdelay(DELAY_TICKS);
 1111   if ((s=sys_outb(wn->base_ctl + REG_CTL, 0)) != OK)
 1112         panic(w_name(),"Couldn't strobe reset bit",s);
 1113   tickdelay(DELAY_TICKS);
 1114 
 1115   /* Wait for controller ready */
 1116   if (!w_waitfor(STATUS_BSY, 0)) {
 1117         printf("%s: reset failed, drive busy\n", w_name());
 1118         return(ERR);
 1119   }
 1120 
 1121   /* The error register should be checked now, but some drives mess it up. */
 1122 
 1123   for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
 1124         if (wn->base_cmd == w_wn->base_cmd) {
 1125                 wn->state &= ~DEAF;
 1126                 if (w_wn->irq_need_ack) {
 1127                         /* Make sure irq is actually enabled.. */
 1128                         sys_irqenable(&w_wn->irq_hook_id);
 1129                 }
 1130         }
 1131   }
 1132                 
 1133 
 1134   return(OK);
 1135 }
 1136 
 1137 /*===========================================================================*
 1138  *                              w_intr_wait                                  *
 1139  *===========================================================================*/
 1140 PRIVATE void w_intr_wait()
 1141 {
 1142 /* Wait for a task completion interrupt. */
 1143 
 1144   message m;
 1145 
 1146   if (w_wn->irq != NO_IRQ) {
 1147         /* Wait for an interrupt that sets w_status to "not busy". */
 1148         while (w_wn->w_status & (STATUS_ADMBSY|STATUS_BSY)) {
 1149                 receive(ANY, &m);               /* expect HARD_INT message */
 1150                 if (m.m_type == SYN_ALARM) {    /* but check for timeout */
 1151                     w_timeout();                /* a.o. set w_status */
 1152                 } else if (m.m_type == HARD_INT) {
 1153                     sys_inb(w_wn->base_cmd + REG_STATUS, &w_wn->w_status);
 1154                     ack_irqs(m.NOTIFY_ARG);
 1155                 } else if (m.m_type == DEV_PING) {
 1156                     notify(m.m_source);
 1157                 } else {
 1158                         printf("AT_WINI got unexpected message %d from %d\n",
 1159                                 m.m_type, m.m_source);
 1160                 }
 1161         }
 1162   } else {
 1163         /* Interrupt not yet allocated; use polling. */
 1164         (void) w_waitfor(STATUS_BSY, 0);
 1165   }
 1166 }
 1167 
 1168 /*===========================================================================*
 1169  *                              at_intr_wait                                 *
 1170  *===========================================================================*/
 1171 PRIVATE int at_intr_wait()
 1172 {
 1173 /* Wait for an interrupt, study the status bits and return error/success. */
 1174   int r;
 1175   int s,inbval;         /* read value with sys_inb */ 
 1176 
 1177   w_intr_wait();
 1178   if ((w_wn->w_status & (STATUS_BSY | STATUS_WF | STATUS_ERR)) == 0) {
 1179         r = OK;
 1180   } else {
 1181         if ((s=sys_inb(w_wn->base_cmd + REG_ERROR, &inbval)) != OK)
 1182                 panic(w_name(),"Couldn't read register",s);
 1183         if ((w_wn->w_status & STATUS_ERR) && (inbval & ERROR_BB)) {
 1184                 r = ERR_BAD_SECTOR;     /* sector marked bad, retries won't help */
 1185         } else {
 1186                 r = ERR;                /* any other error */
 1187         }
 1188   }
 1189   w_wn->w_status |= STATUS_ADMBSY;      /* assume still busy with I/O */
 1190   return(r);
 1191 }
 1192 
 1193 /*===========================================================================*
 1194  *                              w_waitfor                                    *
 1195  *===========================================================================*/
 1196 PRIVATE int w_waitfor(mask, value)
 1197 int mask;                       /* status mask */
 1198 int value;                      /* required status */
 1199 {
 1200 /* Wait until controller is in the required state.  Return zero on timeout.
 1201  * An alarm that set a timeout flag is used. TIMEOUT is in micros, we need
 1202  * ticks. Disabling the alarm is not needed, because a static flag is used
 1203  * and a leftover timeout cannot do any harm.
 1204  */
 1205   clock_t t0, t1;
 1206   int s;
 1207   getuptime(&t0);
 1208   do {
 1209         if ((s=sys_inb(w_wn->base_cmd + REG_STATUS, &w_wn->w_status)) != OK)
 1210                 panic(w_name(),"Couldn't read register",s);
 1211         if ((w_wn->w_status & mask) == value) {
 1212                 return 1;
 1213         }
 1214   } while ((s=getuptime(&t1)) == OK && (t1-t0) < timeout_ticks );
 1215   if (OK != s) printf("AT_WINI: warning, get_uptime failed: %d\n",s);
 1216 
 1217   w_need_reset();                       /* controller gone deaf */
 1218   return(0);
 1219 }
 1220 
 1221 /*===========================================================================*
 1222  *                              w_geometry                                   *
 1223  *===========================================================================*/
 1224 PRIVATE void w_geometry(entry)
 1225 struct partition *entry;
 1226 {
 1227   struct wini *wn = w_wn;
 1228 
 1229   if (wn->state & ATAPI) {              /* Make up some numbers. */
 1230         entry->cylinders = div64u(wn->part[0].dv_size, SECTOR_SIZE) / (64*32);
 1231         entry->heads = 64;
 1232         entry->sectors = 32;
 1233   } else {                              /* Return logical geometry. */
 1234         entry->cylinders = wn->lcylinders;
 1235         entry->heads = wn->lheads;
 1236         entry->sectors = wn->lsectors;
 1237   }
 1238 }
 1239 
 1240 #if ENABLE_ATAPI
 1241 /*===========================================================================*
 1242  *                              atapi_open                                   *
 1243  *===========================================================================*/
 1244 PRIVATE int atapi_open()
 1245 {
 1246 /* Should load and lock the device and obtain its size.  For now just set the
 1247  * size of the device to something big.  What is really needed is a generic
 1248  * SCSI layer that does all this stuff for ATAPI and SCSI devices (kjb). (XXX)
 1249  */
 1250   w_wn->part[0].dv_size = mul64u(800L*1024, 1024);
 1251   return(OK);
 1252 }
 1253 
 1254 /*===========================================================================*
 1255  *                              atapi_close                                  *
 1256  *===========================================================================*/
 1257 PRIVATE void atapi_close()
 1258 {
 1259 /* Should unlock the device.  For now do nothing.  (XXX) */
 1260 }
 1261 
 1262 void sense_request(void)
 1263 {
 1264         int r, i;
 1265         static u8_t sense[100], packet[ATAPI_PACKETSIZE];
 1266 
 1267         packet[0] = SCSI_SENSE;
 1268         packet[1] = 0;
 1269         packet[2] = 0;
 1270         packet[3] = 0;
 1271         packet[4] = SENSE_PACKETSIZE;
 1272         packet[5] = 0;
 1273         packet[7] = 0;
 1274         packet[8] = 0;
 1275         packet[9] = 0;
 1276         packet[10] = 0;
 1277         packet[11] = 0;
 1278 
 1279         for(i = 0; i < SENSE_PACKETSIZE; i++) sense[i] = 0xff;
 1280         r = atapi_sendpacket(packet, SENSE_PACKETSIZE);
 1281         if (r != OK) { printf("request sense command failed\n"); return; }
 1282         if (atapi_intr_wait() <= 0) { printf("WARNING: request response failed\n"); }
 1283 
 1284         if (sys_insw(w_wn->base_cmd + REG_DATA, SELF, (void *) sense, SENSE_PACKETSIZE) != OK)
 1285                 printf("WARNING: sense reading failed\n");
 1286 
 1287         printf("sense data:");
 1288         for(i = 0; i < SENSE_PACKETSIZE; i++) printf(" %02x", sense[i]);
 1289         printf("\n");
 1290 }
 1291 
 1292 /*===========================================================================*
 1293  *                              atapi_transfer                               *
 1294  *===========================================================================*/
 1295 PRIVATE int atapi_transfer(proc_nr, opcode, position, iov, nr_req)
 1296 int proc_nr;                    /* process doing the request */
 1297 int opcode;                     /* DEV_GATHER or DEV_SCATTER */
 1298 off_t position;                 /* offset on device to read or write */
 1299 iovec_t *iov;                   /* pointer to read or write request vector */
 1300 unsigned nr_req;                /* length of request vector */
 1301 {
 1302   struct wini *wn = w_wn;
 1303   iovec_t *iop, *iov_end = iov + nr_req;
 1304   int r, s, errors, fresh;
 1305   u64_t pos;
 1306   unsigned long block;
 1307   unsigned long dv_size = cv64ul(w_dv->dv_size);
 1308   unsigned nbytes, nblocks, count, before, chunk;
 1309   static u8_t packet[ATAPI_PACKETSIZE];
 1310 
 1311   errors = fresh = 0;
 1312 
 1313   while (nr_req > 0 && !fresh) {
 1314         /* The Minix block size is smaller than the CD block size, so we
 1315          * may have to read extra before or after the good data.
 1316          */
 1317         pos = add64ul(w_dv->dv_base, position);
 1318         block = div64u(pos, CD_SECTOR_SIZE);
 1319         before = rem64u(pos, CD_SECTOR_SIZE);
 1320 
 1321         /* How many bytes to transfer? */
 1322         nbytes = count = 0;
 1323         for (iop = iov; iop < iov_end; iop++) {
 1324                 nbytes += iop->iov_size;
 1325                 if ((before + nbytes) % CD_SECTOR_SIZE == 0) count = nbytes;
 1326         }
 1327 
 1328         /* Does one of the memory chunks end nicely on a CD sector multiple? */
 1329         if (count != 0) nbytes = count;
 1330 
 1331         /* Data comes in as words, so we have to enforce even byte counts. */
 1332         if ((before | nbytes) & 1) return(EINVAL);
 1333 
 1334         /* Which block on disk and how close to EOF? */
 1335         if (position >= dv_size) return(OK);            /* At EOF */
 1336         if (position + nbytes > dv_size) nbytes = dv_size - position;
 1337 
 1338         nblocks = (before + nbytes + CD_SECTOR_SIZE - 1) / CD_SECTOR_SIZE;
 1339         if (ATAPI_DEBUG) {
 1340                 printf("block=%lu, before=%u, nbytes=%u, nblocks=%u\n",
 1341                         block, before, nbytes, nblocks);
 1342         }
 1343 
 1344         /* First check to see if a reinitialization is needed. */
 1345         if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
 1346 
 1347         /* Build an ATAPI command packet. */
 1348         packet[0] = SCSI_READ10;
 1349         packet[1] = 0;
 1350         packet[2] = (block >> 24) & 0xFF;
 1351         packet[3] = (block >> 16) & 0xFF;
 1352         packet[4] = (block >>  8) & 0xFF;
 1353         packet[5] = (block >>  0) & 0xFF;
 1354         packet[7] = (nblocks >> 8) & 0xFF;
 1355         packet[8] = (nblocks >> 0) & 0xFF;
 1356         packet[9] = 0;
 1357         packet[10] = 0;
 1358         packet[11] = 0;
 1359 
 1360         /* Tell the controller to execute the packet command. */
 1361         r = atapi_sendpacket(packet, nblocks * CD_SECTOR_SIZE);
 1362         if (r != OK) goto err;
 1363 
 1364         /* Read chunks of data. */
 1365         while ((r = atapi_intr_wait()) > 0) {
 1366                 count = r;
 1367 
 1368                 if (ATAPI_DEBUG) {
 1369                         printf("before=%u, nbytes=%u, count=%u\n",
 1370                                 before, nbytes, count);
 1371                 }
 1372 
 1373                 while (before > 0 && count > 0) {       /* Discard before. */
 1374                         chunk = before;
 1375                         if (chunk > count) chunk = count;
 1376                         if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
 1377         if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, chunk)) != OK)
 1378                 panic(w_name(),"Call to sys_insw() failed", s);
 1379                         before -= chunk;
 1380                         count -= chunk;
 1381                 }
 1382 
 1383                 while (nbytes > 0 && count > 0) {       /* Requested data. */
 1384                         chunk = nbytes;
 1385                         if (chunk > count) chunk = count;
 1386                         if (chunk > iov->iov_size) chunk = iov->iov_size;
 1387         if ((s=sys_insw(wn->base_cmd + REG_DATA, proc_nr, (void *) iov->iov_addr, chunk)) != OK)
 1388                 panic(w_name(),"Call to sys_insw() failed", s);
 1389                         position += chunk;
 1390                         nbytes -= chunk;
 1391                         count -= chunk;
 1392                         iov->iov_addr += chunk;
 1393                         fresh = 0;
 1394                         if ((iov->iov_size -= chunk) == 0) {
 1395                                 iov++;
 1396                                 nr_req--;
 1397                                 fresh = 1;      /* new element is optional */
 1398                         }
 1399                 }
 1400 
 1401                 while (count > 0) {             /* Excess data. */
 1402                         chunk = count;
 1403                         if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
 1404         if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, chunk)) != OK)
 1405                 panic(w_name(),"Call to sys_insw() failed", s);
 1406                         count -= chunk;
 1407                 }
 1408         }
 1409 
 1410         if (r < 0) {
 1411   err:          /* Don't retry if too many errors. */
 1412                 if (atapi_debug) sense_request();
 1413                 if (++errors == max_errors) {
 1414                         w_command = CMD_IDLE;
 1415                         if (atapi_debug) printf("giving up (%d)\n", errors);
 1416                         return(EIO);
 1417                 }
 1418                 if (atapi_debug) printf("retry (%d)\n", errors);
 1419         }
 1420   }
 1421 
 1422   w_command = CMD_IDLE;
 1423   return(OK);
 1424 }
 1425 
 1426 /*===========================================================================*
 1427  *                              atapi_sendpacket                             *
 1428  *===========================================================================*/
 1429 PRIVATE int atapi_sendpacket(packet, cnt)
 1430 u8_t *packet;
 1431 unsigned cnt;
 1432 {
 1433 /* Send an Atapi Packet Command */
 1434   struct wini *wn = w_wn;
 1435   pvb_pair_t outbyte[6];                /* vector for sys_voutb() */
 1436   int s;
 1437 
 1438   if (wn->state & IGNORING) return ERR;
 1439 
 1440   /* Select Master/Slave drive */
 1441   if ((s=sys_outb(wn->base_cmd + REG_DRIVE, wn->ldhpref)) != OK)
 1442         panic(w_name(),"Couldn't select master/ slave drive",s);
 1443 
 1444   if (!w_waitfor(STATUS_BSY | STATUS_DRQ, 0)) {
 1445         printf("%s: atapi_sendpacket: drive not ready\n", w_name());
 1446         return(ERR);
 1447   }
 1448 
 1449   /* Schedule a wakeup call, some controllers are flaky. This is done with
 1450    * a synchronous alarm. If a timeout occurs a SYN_ALARM message is sent
 1451    * from HARDWARE, so that w_intr_wait() can call w_timeout() in case the
 1452    * controller was not able to execute the command. Leftover timeouts are
 1453    * simply ignored by the main loop. 
 1454    */
 1455   sys_setalarm(wakeup_ticks, 0);
 1456 
 1457 #if _WORD_SIZE > 2
 1458   if (cnt > 0xFFFE) cnt = 0xFFFE;       /* Max data per interrupt. */
 1459 #endif
 1460 
 1461   w_command = ATAPI_PACKETCMD;
 1462   pv_set(outbyte[0], wn->base_cmd + REG_FEAT, 0);
 1463   pv_set(outbyte[1], wn->base_cmd + REG_IRR, 0);
 1464   pv_set(outbyte[2], wn->base_cmd + REG_SAMTAG, 0);
 1465   pv_set(outbyte[3], wn->base_cmd + REG_CNT_LO, (cnt >> 0) & 0xFF);
 1466   pv_set(outbyte[4], wn->base_cmd + REG_CNT_HI, (cnt >> 8) & 0xFF);
 1467   pv_set(outbyte[5], wn->base_cmd + REG_COMMAND, w_command);
 1468   if (atapi_debug) printf("cmd: %x  ", w_command);
 1469   if ((s=sys_voutb(outbyte,6)) != OK)
 1470         panic(w_name(),"Couldn't write registers with sys_voutb()",s);
 1471 
 1472   if (!w_waitfor(STATUS_BSY | STATUS_DRQ, STATUS_DRQ)) {
 1473         printf("%s: timeout (BSY|DRQ -> DRQ)\n", w_name());
 1474         return(ERR);
 1475   }
 1476   wn->w_status |= STATUS_ADMBSY;                /* Command not at all done yet. */
 1477 
 1478   /* Send the command packet to the device. */
 1479   if ((s=sys_outsw(wn->base_cmd + REG_DATA, SELF, packet, ATAPI_PACKETSIZE)) != OK)
 1480         panic(w_name(),"sys_outsw() failed", s);
 1481 
 1482  {
 1483  int p;
 1484  if (atapi_debug) {
 1485         printf("sent command:");
 1486          for(p = 0; p < ATAPI_PACKETSIZE; p++) { printf(" %02x", packet[p]); }
 1487          printf("\n");
 1488         }
 1489  }
 1490   return(OK);
 1491 }
 1492 
 1493 
 1494 #endif /* ENABLE_ATAPI */
 1495 
 1496 /*===========================================================================*
 1497  *                              w_other                                      *
 1498  *===========================================================================*/
 1499 PRIVATE int w_other(dr, m)
 1500 struct driver *dr;
 1501 message *m;
 1502 {
 1503         int r, timeout, prev;
 1504 
 1505         if (m->m_type != DEV_IOCTL ) {
 1506                 return EINVAL;
 1507         }
 1508 
 1509         if (m->REQUEST == DIOCTIMEOUT) {
 1510                 if ((r=sys_datacopy(m->PROC_NR, (vir_bytes)m->ADDRESS,
 1511                         SELF, (vir_bytes)&timeout, sizeof(timeout))) != OK)
 1512                         return r;
 1513         
 1514                 if (timeout == 0) {
 1515                         /* Restore defaults. */
 1516                         timeout_ticks = DEF_TIMEOUT_TICKS;
 1517                         max_errors = MAX_ERRORS;
 1518                         wakeup_ticks = WAKEUP;
 1519                         w_silent = 0;
 1520                 } else if (timeout < 0) {
 1521                         return EINVAL;
 1522                 } else  {
 1523                         prev = wakeup_ticks;
 1524         
 1525                         if (!w_standard_timeouts) {
 1526                                 /* Set (lower) timeout, lower error
 1527                                  * tolerance and set silent mode.
 1528                                  */
 1529                                 wakeup_ticks = timeout;
 1530                                 max_errors = 3;
 1531                                 w_silent = 1;
 1532         
 1533                                 if (timeout_ticks > timeout)
 1534                                         timeout_ticks = timeout;
 1535                         }
 1536         
 1537                         if ((r=sys_datacopy(SELF, (vir_bytes)&prev, 
 1538                                 m->PROC_NR, (vir_bytes)m->ADDRESS, sizeof(prev))) != OK)
 1539                                 return r;
 1540                 }
 1541         
 1542                 return OK;
 1543         } else  if (m->REQUEST == DIOCOPENCT) {
 1544                 int count;
 1545                 if (w_prepare(m->DEVICE) == NIL_DEV) return ENXIO;
 1546                 count = w_wn->open_ct;
 1547                 if ((r=sys_datacopy(SELF, (vir_bytes)&count, 
 1548                         m->PROC_NR, (vir_bytes)m->ADDRESS, sizeof(count))) != OK)
 1549                         return r;
 1550                 return OK;
 1551         }
 1552         return EINVAL;
 1553 }
 1554 
 1555 /*===========================================================================*
 1556  *                              w_hw_int                                     *
 1557  *===========================================================================*/
 1558 PRIVATE int w_hw_int(dr, m)
 1559 struct driver *dr;
 1560 message *m;
 1561 {
 1562   /* Leftover interrupt(s) received; ack it/them. */
 1563   ack_irqs(m->NOTIFY_ARG);
 1564 
 1565   return OK;
 1566 }
 1567 
 1568 
 1569 /*===========================================================================*
 1570  *                              ack_irqs                                     *
 1571  *===========================================================================*/
 1572 PRIVATE void ack_irqs(unsigned int irqs)
 1573 {
 1574   unsigned int drive;
 1575   for (drive = 0; drive < MAX_DRIVES && irqs; drive++) {
 1576         if (!(wini[drive].state & IGNORING) && wini[drive].irq_need_ack &&
 1577                 (wini[drive].irq_mask & irqs)) {
 1578                 if (sys_inb((wini[drive].base_cmd + REG_STATUS), &wini[drive].w_status) != OK)
 1579                         printf("couldn't ack irq on drive %d\n", drive);
 1580                 if (sys_irqenable(&wini[drive].irq_hook_id) != OK)
 1581                         printf("couldn't re-enable drive %d\n", drive);
 1582                 irqs &= ~wini[drive].irq_mask;
 1583         }
 1584   }
 1585 }
 1586 
 1587 
 1588 #define STSTR(a) if (status & STATUS_ ## a) { strcat(str, #a); strcat(str, " "); }
 1589 #define ERRSTR(a) if (e & ERROR_ ## a) { strcat(str, #a); strcat(str, " "); }
 1590 char *strstatus(int status)
 1591 {
 1592         static char str[200];
 1593         str[0] = '\0';
 1594 
 1595         STSTR(BSY);
 1596         STSTR(DRDY);
 1597         STSTR(DMADF);
 1598         STSTR(SRVCDSC);
 1599         STSTR(DRQ);
 1600         STSTR(CORR);
 1601         STSTR(CHECK);
 1602         return str;
 1603 }
 1604 
 1605 char *strerr(int e)
 1606 {
 1607         static char str[200];
 1608         str[0] = '\0';
 1609 
 1610         ERRSTR(BB);
 1611         ERRSTR(ECC);
 1612         ERRSTR(ID);
 1613         ERRSTR(AC);
 1614         ERRSTR(TK);
 1615         ERRSTR(DM);
 1616 
 1617         return str;
 1618 }
 1619 
 1620 #if ENABLE_ATAPI
 1621 
 1622 /*===========================================================================*
 1623  *                              atapi_intr_wait                              *
 1624  *===========================================================================*/
 1625 PRIVATE int atapi_intr_wait()
 1626 {
 1627 /* Wait for an interrupt and study the results.  Returns a number of bytes
 1628  * that need to be transferred, or an error code.
 1629  */
 1630   struct wini *wn = w_wn;
 1631   pvb_pair_t inbyte[4];         /* vector for sys_vinb() */
 1632   int s;                        /* status for sys_vinb() */
 1633   int e;
 1634   int len;
 1635   int irr;
 1636   int r;
 1637   int phase;
 1638 
 1639   w_intr_wait();
 1640 
 1641   /* Request series of device I/O. */
 1642   inbyte[0].port = wn->base_cmd + REG_ERROR;
 1643   inbyte[1].port = wn->base_cmd + REG_CNT_LO;
 1644   inbyte[2].port = wn->base_cmd + REG_CNT_HI;
 1645   inbyte[3].port = wn->base_cmd + REG_IRR;
 1646   if ((s=sys_vinb(inbyte, 4)) != OK)
 1647         panic(w_name(),"ATAPI failed sys_vinb()", s);
 1648   e = inbyte[0].value;
 1649   len = inbyte[1].value;
 1650   len |= inbyte[2].value << 8;
 1651   irr = inbyte[3].value;
 1652 
 1653 #if ATAPI_DEBUG
 1654         printf("wn %p  S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn, wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
 1655 #endif
 1656   if (wn->w_status & (STATUS_BSY | STATUS_CHECK)) {
 1657         if (atapi_debug) {
 1658                 printf("atapi fail:  S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
 1659         }
 1660         return ERR;
 1661   }
 1662 
 1663   phase = (wn->w_status & STATUS_DRQ) | (irr & (IRR_COD | IRR_IO));
 1664 
 1665   switch (phase) {
 1666   case IRR_COD | IRR_IO:
 1667         if (ATAPI_DEBUG) printf("ACD: Phase Command Complete\n");
 1668         r = OK;
 1669         break;
 1670   case 0:
 1671         if (ATAPI_DEBUG) printf("ACD: Phase Command Aborted\n");
 1672         r = ERR;
 1673         break;
 1674   case STATUS_DRQ | IRR_COD:
 1675         if (ATAPI_DEBUG) printf("ACD: Phase Command Out\n");
 1676         r = ERR;
 1677         break;
 1678   case STATUS_DRQ:
 1679         if (ATAPI_DEBUG) printf("ACD: Phase Data Out %d\n", len);
 1680         r = len;
 1681         break;
 1682   case STATUS_DRQ | IRR_IO:
 1683         if (ATAPI_DEBUG) printf("ACD: Phase Data In %d\n", len);
 1684         r = len;
 1685         break;
 1686   default:
 1687         if (ATAPI_DEBUG) printf("ACD: Phase Unknown\n");
 1688         r = ERR;
 1689         break;
 1690   }
 1691 
 1692 #if 0
 1693   /* retry if the media changed */
 1694   XXX while (phase == (IRR_IO | IRR_COD) && (wn->w_status & STATUS_CHECK)
 1695         && (e & ERROR_SENSE) == SENSE_UATTN && --try > 0);
 1696 #endif
 1697 
 1698   wn->w_status |= STATUS_ADMBSY;        /* Assume not done yet. */
 1699   return(r);
 1700 }
 1701 #endif /* ENABLE_ATAPI */

Cache object: 466ee477b32a3756fec170c3911a1667


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.