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/i386/isa/atapi.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 /*
    2  * Device-independent level for ATAPI drivers.
    3  *
    4  * Copyright (C) 1995 Cronyx Ltd.
    5  * Author Serge Vakulenko, <vak@cronyx.ru>
    6  *
    7  * This software is distributed with NO WARRANTIES, not even the implied
    8  * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    9  *
   10  * Authors grant any other persons or organisations permission to use
   11  * or modify this software as long as this message is kept with the software,
   12  * all derivative works or modified versions.
   13  *
   14  * Version 1.9, Mon Oct  9 22:34:47 MSK 1995
   15  *
   16  * $FreeBSD$
   17  */
   18 
   19 /*
   20  * The ATAPI level is implemented as a machine-dependent layer
   21  * between the device driver and the IDE controller.
   22  * All the machine- and controller dependency is isolated inside
   23  * the ATAPI level, while all the device dependency is located
   24  * in the device subdriver.
   25  *
   26  * It seems that an ATAPI bus will became popular for medium-speed
   27  * storage devices such as CD-ROMs, magneto-optical disks, tape streamers etc.
   28  *
   29  * To ease the development of new ATAPI drivers, the subdriver
   30  * interface was designed to be as simple as possible.
   31  *
   32  * Three routines are available for the subdriver to access the device:
   33  *
   34  *      struct atapires atapi_request_wait (ata, unit, cmd, a1, a2, a3, a4, a5,
   35  *              a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, addr, count);
   36  *      struct atapi *ata;  -- atapi controller descriptor
   37  *      int unit;           -- device unit number on the IDE bus
   38  *      u_char cmd;         -- ATAPI command code
   39  *      u_char a1..a15;     -- ATAPI command arguments
   40  *      char *addr;         -- address of the data buffer for i/o
   41  *      int count;          -- data length, >0 for read ops, <0 for write ops
   42  *
   43  * The atapi_request_wait() function puts the op in the queue of ATAPI
   44  * commands for the IDE controller, starts the controller, the waits for
   45  * operation to be completed (using tsleep).
   46  * The function should be called from the user phase only (open(), close(),
   47  * ioctl() etc).
   48  * Ata and unit args are the values which the subdriver gets from the ATAPI
   49  * level via attach() call.
   50  * Buffer pointed to by *addr should be placed in core memory, static
   51  * or dynamic, but not in stack.
   52  * The function returns the error code structure, which consists of:
   53  * - atapi driver code value
   54  * - controller status port value
   55  * - controller error port value
   56  *
   57  *      struct atapires atapi_request_immediate (ata, unit, cmd, a1, a2, a3,
   58  *              a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,
   59  *              addr, count);
   60  *
   61  * The atapi_request_immediate() function is similar to atapi_request_wait(),
   62  * but it does not use interrupts for performing the request.
   63  * It should be used during an attach phase to get parameters from the device.
   64  *
   65  *      void atapi_request_callback (ata, unit, cmd, a1, a2, a3, a4, a5,
   66  *              a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,
   67  *              addr, count, done, x, y);
   68  *      struct atapi *ata;  -- atapi controller descriptor
   69  *      int unit;           -- device unit number on the IDE bus
   70  *      u_char cmd;         -- ATAPI command code
   71  *      u_char a1..a15;     -- ATAPI command arguments
   72  *      char *addr;         -- address of the data buffer for i/o
   73  *      int count;          -- data length, >0 for read ops, <0 for write ops
   74  *      void (*done)();     -- function to call when op finished
   75  *      void *x, *y;        -- arguments for done() function
   76  *
   77  * The atapi_request_callback() function puts the op in the queue of ATAPI
   78  * commands for the IDE controller, starts the controller, then returns.
   79  * When the operation finishes, then the callback function done()
   80  * will be called on the interrupt level.
   81  * The function is designed to be callable from the interrupt phase.
   82  * The done() functions is called with the following arguments:
   83  *      (void) (*done) (x, y, count, errcode)
   84  *      void *x, *y;             -- arguments from the atapi_request_callback()
   85  *      int count;               -- the data residual count
   86  *      struct atapires errcode; -- error code structure, see above
   87  *
   88  * The new driver could be added in three steps:
   89  * 1. Add entries for the new driver to bdevsw and cdevsw tables in conf.c.
   90  *    You will need to make at least three routines: open(), close(),
   91  *    strategy() and possibly ioctl().
   92  * 2. Make attach() routine, which should allocate all the needed data
   93  *    structures and print the device description string (see xxxattach()).
   94  * 3. Add an appropriate case to the switch in atapi_attach() routine,
   95  *    call attach() routine of the new driver here.  Add the appropriate
   96  *    #include line at the top of attach.c.
   97  * That's all!
   98  *
   99  * Use #define DEBUG in atapi.c to enable tracing of all i/o operations
  100  * on the IDE bus.
  101  */
  102 #undef DEBUG
  103 
  104 #include "wdc.h"
  105 
  106 #include "wcd.h"
  107 #include "wfd.h"
  108 #include "wst.h"
  109 /* #include "wmd.h" -- add your driver here */
  110 
  111 #if NWDC > 0
  112 
  113 #include <sys/param.h>
  114 #include <sys/systm.h>
  115 #include <sys/malloc.h>
  116 
  117 #include <machine/clock.h>
  118 
  119 #include <i386/isa/atapi.h>
  120 
  121 /* this code is compiled part of the module */
  122 
  123 #ifdef DEBUG
  124 #   define print(s)     printf s
  125 #else
  126 #   define print(s)     {/*void*/}
  127 #endif
  128 
  129 /*
  130  * ATAPI packet command phase.
  131  */
  132 #define PHASE_CMDOUT    (ARS_DRQ | ARI_CMD)
  133 #define PHASE_DATAIN    (ARS_DRQ | ARI_IN)
  134 #define PHASE_DATAOUT   ARS_DRQ
  135 #define PHASE_COMPLETED (ARI_IN | ARI_CMD)
  136 #define PHASE_ABORTED   0                       /* nonstandard - for NEC 260 */
  137 
  138 static struct atapi atapitab[NWDC];
  139 
  140 static struct atapi_params *atapi_probe (int port, int unit);
  141 static int atapi_wait (int port, u_char bits_wanted);
  142 static void atapi_send_cmd (struct atapi *ata, struct atapicmd *ac);
  143 static int atapi_io (struct atapi *ata, struct atapicmd *ac);
  144 static int atapi_strt_cmd (struct atapi *ata, struct atapicmd *ac);
  145 static int atapi_wait_cmd (struct atapi *ata, struct atapicmd *ac);
  146 
  147 extern void wdstart (int ctrlr);
  148 extern int acdattach(struct atapi*, int, struct atapi_params*, int);
  149 extern int wfdattach(struct atapi*, int, struct atapi_params*, int);
  150 extern int wstattach(struct atapi*, int, struct atapi_params*, int);
  151 
  152 /*
  153  * Probe the ATAPI device at IDE controller `ctlr', drive `unit'.
  154  * Called at splbio().
  155  */
  156 int atapi_attach (int ctlr, int unit, int port)
  157 {
  158         struct atapi *ata = atapitab + ctlr;
  159         struct atapi_params *ap;
  160         char buf [sizeof(ap->model) + 1];
  161         char revbuf [sizeof(ap->revision) + 1];
  162         struct atapicmd *ac;
  163 
  164         print (("atapi%d.%d at 0x%x: attach called\n", ctlr, unit, port));
  165         ap = atapi_probe (port, unit);
  166         if (! ap)
  167                 return (0);
  168 
  169         bcopy (ap->model, buf, sizeof(buf)-1);
  170         buf[sizeof(buf)-1] = 0;
  171 
  172         bcopy (ap->revision, revbuf, sizeof(revbuf)-1);
  173         revbuf[sizeof(revbuf)-1] = 0;
  174 
  175         printf ("wdc%d: unit %d (atapi): <%s/%s>", ctlr, unit, buf, revbuf);
  176 
  177         /* device is removable */
  178         if (ap->removable)
  179                 printf (", removable");
  180 
  181         /* packet command size */
  182         switch (ap->cmdsz) {
  183         case AT_PSIZE_12: break;
  184         case AT_PSIZE_16: printf (", cmd16"); ata->cmd16 = 1; break;
  185         default:          printf (", cmd%d", ap->cmdsz);
  186         }
  187 
  188         /* DRQ type */
  189         switch (ap->drqtype) {
  190         case AT_DRQT_MPROC: ata->slow = 1; break;
  191         case AT_DRQT_INTR:  printf (", intr"); ata->intrcmd = 1; break;
  192         case AT_DRQT_ACCEL: printf (", accel"); ata->accel = 1; break;
  193         default:            printf (", drq%d", ap->drqtype);
  194         }
  195         if (ata->slow)
  196                 ata->intrcmd = 0;
  197 
  198         /* 
  199          * If we have two devices, one supporting INTR and one ACCEL, we
  200          * have to pessimise - clear INTR and set slow.
  201          */
  202         if (ata->accel && ata->intrcmd) {
  203         ata->intrcmd = 0;
  204         ata->slow = 1;
  205         }
  206 
  207         /* overlap operation supported */
  208         if (ap->ovlapflag)
  209                 printf (", ovlap");
  210 
  211         /* interleaved DMA supported */
  212         if (ap->idmaflag)
  213                 printf (", idma");
  214         /* DMA supported */
  215         else if (ap->dmaflag)
  216                 printf (", dma");
  217 
  218         /* IORDY can be disabled */
  219         if (ap->iordydis)
  220                 printf (", iordis");
  221         /* IORDY supported */
  222         else if (ap->iordyflag)
  223                 printf (", iordy");
  224 
  225         printf ("\n");
  226 
  227         ata->port = port;
  228         ata->ctrlr = ctlr;
  229         ata->attached[unit] = 0;
  230 #ifdef DEBUG
  231         ata->debug = 1;
  232 #else
  233         ata->debug = 0;
  234 #endif
  235         /* Initialize free queue. */
  236         ata->cmdrq[15].next = 0;
  237         for (ac = ata->cmdrq+14; ac >= ata->cmdrq; --ac)
  238                 ac->next = ac+1;
  239         ata->free = ata->cmdrq;
  240 
  241         if (ap->proto != AT_PROTO_ATAPI) {
  242                 printf ("wdc%d: unit %d: unknown ATAPI protocol=%d\n",
  243                         ctlr, unit, ap->proto);
  244                 free (ap, M_TEMP);
  245                 return (0);
  246         }
  247         switch (ap->devtype) {
  248         default:
  249                 /* unknown ATAPI device */
  250                 printf ("wdc%d: unit %d: unknown ATAPI type=%d\n",
  251                         ctlr, unit, ap->devtype);
  252                 break;
  253 
  254         case AT_TYPE_DIRECT:            /* direct-access */
  255 #if NWFD > 0
  256                 /* ATAPI Floppy(LS-120) */
  257                 if (wfdattach (ata, unit, ap, ata->debug) < 0)
  258                         break;
  259                         /* Device attached successfully. */
  260                 ata->attached[unit] = 1;
  261                 return (1);
  262 #else
  263                 printf ("wdc%d: ATAPI Floppies not configured\n", ctlr);
  264                 break;
  265 #endif
  266         case AT_TYPE_CDROM:             /* CD-ROM device */
  267 #if NWCD > 0
  268                 /* ATAPI CD-ROM & CD-R/RW drives */
  269                 if (acdattach (ata, unit, ap, ata->debug) < 0)
  270                         break;
  271                 ata->attached[unit] = 1;
  272                 return (1);
  273 #else
  274                 printf ("wdc%d: ATAPI CD-ROMs not configured\n", ctlr);
  275                 break;
  276 #endif
  277 
  278         case AT_TYPE_TAPE:              /* streaming tape */
  279 #if NWST > 0
  280                 /* ATAPI Streaming Tape */
  281                 if (wstattach (ata, unit, ap, ata->debug) < 0)
  282                         break;
  283                 /* Device attached successfully. */
  284                 ata->attached[unit] = 1;
  285                 return (1);
  286 #else
  287                 printf ("wdc%d: ATAPI streaming tapes not configured\n", ctlr);
  288 #endif
  289                 break;
  290 
  291         case AT_TYPE_OPTICAL:           /* optical disk */
  292 #if NWMD > 0
  293                 /* Add your driver here */
  294 #else
  295                 printf ("wdc%d: ATAPI optical disks not supported yet\n", ctlr);
  296 #endif
  297                 break;
  298         }
  299         /* Attach failed. */
  300         free (ap, M_TEMP);
  301         return (0);
  302 }
  303 
  304 static char *cmdname (u_char cmd)
  305 {
  306         static char buf[8];
  307 
  308         switch (cmd) {
  309         case 0x00: return ("TEST_UNIT_READY");
  310         case 0x01: return ("REZERO_UNIT");
  311         case 0x03: return ("REQUEST_SENSE");
  312         case 0x04: return ("FORMAT_UNIT");
  313         case 0x1b: return ("START_STOP");
  314         case 0x1e: return ("PREVENT_ALLOW");
  315         case 0x25: return ("READ_CAPACITY");
  316         case 0x28: return ("READ_BIG");
  317         case 0x2a: return ("WRITE_BIG");
  318         case 0x35: return ("SYNCHRONIZE_CACHE");
  319         case 0x42: return ("READ_SUBCHANNEL");
  320         case 0x43: return ("READ_TOC");
  321         case 0x51: return ("READ_DISC_INFO");
  322         case 0x52: return ("READ_TRACK_INFO");
  323         case 0x53: return ("RESERVE_TRACK");
  324         case 0x54: return ("SEND_OPC_INFO");
  325         case 0x55: return ("MODE_SELECT");
  326         case 0x58: return ("REPAIR_TRACK");
  327         case 0x59: return ("READ_MASTER_CUE");
  328         case 0x5a: return ("MODE_SENSE");
  329         case 0x5b: return ("CLOSE_TRACK/SESSION");
  330         case 0x5c: return ("READ_BUFFER_CAPACITY");
  331         case 0x5d: return ("SEND_CUE_SHEET");
  332         case 0x47: return ("PLAY_MSF");
  333         case 0x4b: return ("PAUSE");
  334         case 0x48: return ("PLAY_TRACK");
  335         case 0xa1: return ("BLANK_CMD");
  336         case 0xa5: return ("PLAY_BIG");
  337         case 0xb4: return ("PLAY_CD");
  338         case 0xbd: return ("ATAPI_MECH_STATUS"); 
  339         case 0xbe: return ("READ_CD");
  340         }
  341         snprintf (buf, sizeof(buf), "[0x%x]", cmd);
  342         return (buf);
  343 }
  344 
  345 static void bswap (char *buf, int len)
  346 {
  347         u_short *p = (u_short*) (buf + len);
  348         while (--p >= (u_short*) buf)
  349                 *p = ntohs (*p);
  350 }
  351 
  352 static void btrim (char *buf, int len)
  353 {
  354         char *p;
  355 
  356         /* Remove the trailing spaces. */
  357         for (p=buf; p<buf+len; ++p)
  358                 if (! *p)
  359                         *p = ' ';
  360         for (p=buf+len-1; p>=buf && *p==' '; --p)
  361                 *p = 0;
  362 }
  363 
  364 /*
  365  * Issue IDENTIFY command to ATAPI drive to ask it what it is.
  366  */
  367 static struct atapi_params *atapi_probe (int port, int unit)
  368 {
  369         struct atapi_params *ap;
  370         char tb [DEV_BSIZE];
  371 
  372         /* Wait for controller not busy. */
  373         outb (port + AR_DRIVE, unit ? ARD_DRIVE1 : ARD_DRIVE0);
  374         if (atapi_wait (port, 0) < 0) {
  375                 print (("atapiX.%d at 0x%x: controller busy, status=%b\n",
  376                         unit, port, inb (port + AR_STATUS), ARS_BITS));
  377                 return (0);
  378         }
  379 
  380         /* Issue ATAPI IDENTIFY command. */
  381         outb (port + AR_DRIVE, unit ? ARD_DRIVE1 : ARD_DRIVE0);
  382         outb (port + AR_COMMAND, ATAPIC_IDENTIFY);
  383 
  384         /* Check that device is present. */
  385         if (inb (port + AR_STATUS) == 0xff) {
  386                 print (("atapiX.%d at 0x%x: no device\n", unit, port));
  387                 if (unit == 1)
  388                         /* Select unit 0. */
  389                         outb (port + AR_DRIVE, ARD_DRIVE0);
  390                 return (0);
  391         }
  392 
  393         /* Wait for data ready. */
  394         if (atapi_wait (port, ARS_DRQ) != 0) {
  395                 print (("atapiX.%d at 0x%x: identify not ready, status=%b\n",
  396                         unit, port, inb (port + AR_STATUS), ARS_BITS));
  397                 if (unit == 1)
  398                         /* Select unit 0. */
  399                         outb (port + AR_DRIVE, ARD_DRIVE0);
  400                 return (0);
  401         }
  402 
  403         /* check that DRQ isn't a fake */
  404         if (inb (port + AR_STATUS) == 0xff) {
  405                 print (("atapiX.%d at 0x%x: no device\n", unit, port));
  406                 if (unit == 1)
  407                         /* Select unit 0. */
  408                         outb (port + AR_DRIVE, ARD_DRIVE0);
  409                 return (0);
  410         }
  411 
  412         /* Obtain parameters. */
  413         insw (port + AR_DATA, tb, sizeof(tb) / sizeof(short));
  414 
  415         ap = malloc (sizeof *ap, M_TEMP, M_NOWAIT);
  416         if (! ap)
  417                 return (0);
  418         bcopy (tb, ap, sizeof *ap);
  419 
  420         /*
  421          * Shuffle string byte order.
  422          * Mitsumi and NEC drives don't need this.
  423          */
  424         if (! ((ap->model[0] == 'N' && ap->model[1] == 'E') ||
  425             (ap->model[0] == 'F' && ap->model[1] == 'X')))
  426                 bswap (ap->model, sizeof(ap->model));
  427         bswap (ap->serial, sizeof(ap->serial));
  428         bswap (ap->revision, sizeof(ap->revision));
  429 
  430         /* Clean up the model name, serial and revision numbers. */
  431         btrim (ap->model, sizeof(ap->model));
  432         btrim (ap->serial, sizeof(ap->serial));
  433         btrim (ap->revision, sizeof(ap->revision));
  434         return (ap);
  435 }
  436 
  437 /*
  438  * Wait uninterruptibly until controller is not busy and certain
  439  * status bits are set.
  440  * The wait is usually short unless it is for the controller to process
  441  * an entire critical command.
  442  * Return 1 for (possibly stale) controller errors, -1 for timeout errors,
  443  * or 0 for no errors.
  444  */
  445 static int atapi_wait (int port, u_char bits_wanted)
  446 {
  447         int cnt;
  448         u_char s;
  449 
  450         /* Wait 5 sec for BUSY deassert. */
  451         for (cnt=500000; cnt>0; --cnt) {
  452                 s = inb (port + AR_STATUS);
  453                 if (! (s & ARS_BSY))
  454                         break;
  455                 DELAY (10);
  456         }
  457         if (cnt <= 0)
  458                 return (-1);
  459         if (! bits_wanted)
  460                 return (s & ARS_CHECK);
  461 
  462         /* Wait 50 msec for bits wanted. */
  463         for (cnt=5000; cnt>0; --cnt) {
  464                 s = inb (port + AR_STATUS);
  465                 if ((s & bits_wanted) == bits_wanted)
  466                         return (s & ARS_CHECK);
  467                 DELAY (10);
  468         }
  469         return (-1);
  470 }
  471 
  472 void atapi_debug (struct atapi *ata, int on)
  473 {
  474         ata->debug = on;
  475 }
  476 
  477 static struct atapicmd *atapi_alloc (struct atapi *ata)
  478 {
  479         struct atapicmd *ac;
  480 
  481         while (! ata->free)
  482                 tsleep ((caddr_t)ata, PRIBIO, "atacmd", 100);
  483         ac = ata->free;
  484         ata->free = ac->next;
  485         ac->busy = 1;
  486         return (ac);
  487 }
  488 
  489 static void atapi_free (struct atapi *ata, struct atapicmd *ac)
  490 {
  491         if (! ata->free)
  492                 wakeup ((caddr_t)ata);
  493         ac->busy = 0;
  494         ac->next = ata->free;
  495         ata->free = ac;
  496 }
  497 
  498 /*
  499  * Add new command request to the end of the queue.
  500  */
  501 static void atapi_enqueue (struct atapi *ata, struct atapicmd *ac)
  502 {
  503         ac->next = 0;
  504         if (ata->tail)
  505                 ata->tail->next = ac;
  506         else
  507                 ata->queue = ac;
  508         ata->tail = ac;
  509 }
  510 
  511 static void atapi_done (struct atapi *ata)
  512 {
  513         struct atapicmd *ac = ata->queue;
  514 
  515         if (! ac)
  516                 return; /* cannot happen */
  517 
  518         ata->queue = ac->next;
  519         if (! ata->queue)
  520                 ata->tail = 0;
  521 
  522         if (ac->callback) {
  523                 (*ac->callback) (ac->cbarg1, ac->cbarg2, ac->count, ac->result);
  524                 atapi_free (ata, ac);
  525         } else
  526                 wakeup ((caddr_t)ac);
  527 }
  528 
  529 /*
  530  * Start new packet op.  Called from wdstart().
  531  * Return 1 if op started, and we are waiting for interrupt.
  532  * Return 0 when idle.
  533  */
  534 int atapi_strt (int ctrlr)
  535 {
  536         struct atapi *ata = atapitab + ctrlr;
  537         struct atapicmd *ac;
  538 again:
  539         ac = ata->queue;
  540         if (! ac)
  541                 return (0);
  542 
  543         /* Start packet command. */
  544         if (atapi_strt_cmd (ata, ac) < 0) {
  545                 atapi_done (ata);
  546                 goto again;
  547         }
  548 
  549         if (ata->intrcmd)
  550                 /* Wait for interrupt before sending packet command */
  551                 return (1);
  552 
  553         /* Wait for DRQ. */
  554         if (atapi_wait_cmd (ata, ac) < 0) {
  555                 atapi_done (ata);
  556                 goto again;
  557         }
  558 
  559         /* Send packet command. */
  560         atapi_send_cmd (ata, ac);
  561         return (1);
  562 }
  563 
  564 /*
  565  * Start new packet op. Returns -1 on errors.
  566  */
  567 int atapi_strt_cmd (struct atapi *ata, struct atapicmd *ac)
  568 {
  569         ac->result.error = 0;
  570         ac->result.status = 0;
  571 
  572         outb (ata->port + AR_DRIVE, ac->unit ? ARD_DRIVE1 : ARD_DRIVE0);
  573         if (atapi_wait (ata->port, 0) < 0) {
  574                 printf ("atapi%d.%d: controller not ready for cmd\n",
  575                         ata->ctrlr, ac->unit);
  576                 ac->result.code = RES_NOTRDY;
  577                 return (-1);
  578         }
  579 
  580         /* Set up the controller registers. */
  581         outb (ata->port + AR_FEATURES, 0);
  582         outb (ata->port + AR_IREASON, 0);
  583         outb (ata->port + AR_TAG, 0);
  584         outb (ata->port + AR_CNTLO, ac->count & 0xff);
  585         outb (ata->port + AR_CNTHI, ac->count >> 8);
  586         outb (ata->port + AR_COMMAND, ATAPIC_PACKET);
  587 
  588         if (ata->debug)
  589                 printf ("atapi%d.%d: start\n", ata->ctrlr, ac->unit);
  590         return (0);
  591 }
  592 
  593 /*
  594  * Wait for DRQ before sending packet cmd. Returns -1 on errors.
  595  */
  596 int atapi_wait_cmd (struct atapi *ata, struct atapicmd *ac)
  597 {
  598         /* Wait for DRQ from 100 usec to 3 msec for slow devices */
  599         int cnt = ata->intrcmd ? 10000 : ata->slow ? 3000 : 100;
  600         int ireason = 0, phase = 0;
  601 
  602         /* Wait for command phase. */
  603         for (; cnt>0; cnt-=10) {
  604                 ireason = inb (ata->port + AR_IREASON);
  605                 ac->result.status = inb (ata->port + AR_STATUS);
  606                 phase = (ireason & (ARI_CMD | ARI_IN)) |
  607                         (ac->result.status & (ARS_DRQ | ARS_BSY));
  608                 if (phase == PHASE_CMDOUT)
  609                         break;
  610                 DELAY (10);
  611         }
  612 
  613         if (phase != PHASE_CMDOUT) {
  614                 ac->result.code = RES_NODRQ;
  615                 ac->result.error = inb (ata->port + AR_ERROR);
  616                 printf ("atapi%d.%d: invalid command phase, ireason=0x%x, status=%b, error=%b\n",
  617                         ata->ctrlr, ac->unit, ireason,
  618                         ac->result.status, ARS_BITS,
  619                         ac->result.error, AER_BITS);
  620                 return (-1);
  621         }
  622         return (0);
  623 }
  624 
  625 /*
  626  * Send packet cmd.
  627  */
  628 void atapi_send_cmd (struct atapi *ata, struct atapicmd *ac)
  629 {
  630         outsw (ata->port + AR_DATA, ac->cmd, ata->cmd16 ? 8 : 6);
  631         if (ata->debug)
  632                 printf ("atapi%d.%d: send cmd %s %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x\n",
  633                         ata->ctrlr, ac->unit, cmdname (ac->cmd[0]), ac->cmd[0],
  634                         ac->cmd[1], ac->cmd[2], ac->cmd[3], ac->cmd[4],
  635                         ac->cmd[5], ac->cmd[6], ac->cmd[7], ac->cmd[8],
  636                         ac->cmd[9], ac->cmd[10], ac->cmd[11], ac->cmd[12],
  637                         ac->cmd[13], ac->cmd[14], ac->cmd[15]);
  638 }
  639 
  640 /*
  641  * Interrupt routine for the controller.  Called from wdintr().
  642  * Finish the started op, wakeup wait-type commands,
  643  * run callbacks for callback-type commands, then return.
  644  * Do not start new op here, it will be done by wdstart,
  645  * which is called just after us.
  646  * Return 1 if op continues, and we are waiting for new interrupt.
  647  * Return 0 when idle.
  648  */
  649 int atapi_intr (int ctrlr)
  650 {
  651         struct atapi *ata = atapitab + ctrlr;
  652         struct atapicmd *ac = ata->queue;
  653 
  654         if (! ac) {
  655                 printf ("atapi%d: stray interrupt\n", ata->ctrlr);
  656                 return (0);
  657         }
  658         if (atapi_io (ata, ac) > 0)
  659                 return (1);
  660         atapi_done (ata);
  661         return (0);
  662 }
  663 
  664 /*
  665  * Process the i/o phase, transferring the command/data to/from the device.
  666  * Return 1 if op continues, and we are waiting for new interrupt.
  667  * Return 0 when idle.
  668  */
  669 int atapi_io (struct atapi *ata, struct atapicmd *ac)
  670 {
  671         u_char ireason;
  672         u_short len, i;
  673 
  674         if (atapi_wait (ata->port, 0) < 0) {
  675                 ac->result.status = inb (ata->port + AR_STATUS);
  676                 ac->result.error = inb (ata->port + AR_ERROR);
  677                 ac->result.code = RES_NOTRDY;
  678                 printf ("atapi%d.%d: controller not ready, status=%b, error=%b\n",
  679                         ata->ctrlr, ac->unit, ac->result.status, ARS_BITS,
  680                         ac->result.error, AER_BITS);
  681                 return (0);
  682         }
  683 
  684         ac->result.status = inb (ata->port + AR_STATUS);
  685         ac->result.error = inb (ata->port + AR_ERROR);
  686         len = inb (ata->port + AR_CNTLO);
  687         len |= inb (ata->port + AR_CNTHI) << 8;
  688         ireason = inb (ata->port + AR_IREASON);
  689 
  690         if (ata->debug) {
  691                 printf ("atapi%d.%d: intr ireason=0x%x, len=%d, status=%b, error=%b\n",
  692                         ata->ctrlr, ac->unit, ireason, len,
  693                         ac->result.status, ARS_BITS,
  694                         ac->result.error, AER_BITS);
  695         }
  696         switch ((ireason & (ARI_CMD | ARI_IN)) | (ac->result.status & ARS_DRQ)) {
  697         default:
  698                 printf ("atapi%d.%d: unknown phase\n", ata->ctrlr, ac->unit);
  699                 ac->result.code = RES_ERR;
  700                 break;
  701 
  702         case PHASE_CMDOUT:
  703                 /* Send packet command. */
  704                 if (! (ac->result.status & ARS_DRQ)) {
  705                         printf ("atapi%d.%d: no cmd drq\n",
  706                                 ata->ctrlr, ac->unit);
  707                         ac->result.code = RES_NODRQ;
  708                         break;
  709                 }
  710                 atapi_send_cmd (ata, ac);
  711                 return (1);
  712 
  713         case PHASE_DATAOUT:
  714                 /* Write data */
  715                 if (ac->count > 0) {
  716                         printf ("atapi%d.%d: invalid data direction\n",
  717                                 ata->ctrlr, ac->unit);
  718                         ac->result.code = RES_INVDIR;
  719                         break;
  720                 }
  721                 if (-ac->count < len) {
  722                         print (("atapi%d.%d: send data underrun, %d bytes left\n",
  723                                 ata->ctrlr, ac->unit, -ac->count));
  724                         ac->result.code = RES_UNDERRUN;
  725                         outsw (ata->port + AR_DATA, ac->addr,
  726                                 -ac->count / sizeof(short));
  727                         for (i= -ac->count; i<len; i+=sizeof(short))
  728                                 outw (ata->port + AR_DATA, 0);
  729                 } else
  730                         outsw (ata->port + AR_DATA, ac->addr,
  731                                 len / sizeof(short));
  732                 ac->addr += len;
  733                 ac->count += len;
  734                 return (1);
  735 
  736         case PHASE_DATAIN:
  737                 /* Read data */
  738                 if (ac->count < 0) {
  739                         printf ("atapi%d.%d: invalid data direction\n",
  740                                 ata->ctrlr, ac->unit);
  741                         ac->result.code = RES_INVDIR;
  742                         break;
  743                 }
  744                 if (ac->count < len) {
  745                         print (("atapi%d.%d: recv data overrun, %d bytes left\n",
  746                                 ata->ctrlr, ac->unit, ac->count));
  747                         ac->result.code = RES_OVERRUN;
  748                         insw (ata->port + AR_DATA, ac->addr,
  749                                 ac->count / sizeof(short));
  750                         for (i=ac->count; i<len; i+=sizeof(short))
  751                                 inw (ata->port + AR_DATA);
  752                 } else
  753                         insw (ata->port + AR_DATA, ac->addr,
  754                                 len / sizeof(short));
  755                 ac->addr += len;
  756                 ac->count -= len;
  757                 return (1);
  758 
  759         case PHASE_ABORTED:
  760         case PHASE_COMPLETED:
  761                 if (ac->result.status & (ARS_CHECK | ARS_DF))
  762                         ac->result.code = RES_ERR;
  763                 else if (ac->count < 0) {
  764                         print (("atapi%d.%d: send data overrun, %d bytes left\n",
  765                                 ata->ctrlr, ac->unit, -ac->count));
  766                         ac->result.code = RES_OVERRUN;
  767                 } else if (ac->count > 0) {
  768                         print (("atapi%d.%d: recv data underrun, %d bytes left\n",
  769                                 ata->ctrlr, ac->unit, ac->count));
  770                         ac->result.code = RES_UNDERRUN;
  771                         bzero (ac->addr, ac->count);
  772                 } else
  773                         ac->result.code = RES_OK;
  774                 break;
  775         }
  776         return (0);
  777 }
  778 
  779 /*
  780  * Queue new packet request, then call wdstart().
  781  * Called on splbio().
  782  */
  783 void atapi_request_callback (struct atapi *ata, int unit,
  784         u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4,
  785         u_char a5, u_char a6, u_char a7, u_char a8, u_char a9,
  786         u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15,
  787         char *addr, int count, atapi_callback_t *done, void *x, void *y)
  788 {
  789         struct atapicmd *ac;
  790 
  791         ac = atapi_alloc (ata);
  792         ac->cmd[0] = cmd;       ac->cmd[1] = a1;
  793         ac->cmd[2] = a2;        ac->cmd[3] = a3;
  794         ac->cmd[4] = a4;        ac->cmd[5] = a5;
  795         ac->cmd[6] = a6;        ac->cmd[7] = a7;
  796         ac->cmd[8] = a8;        ac->cmd[9] = a9;
  797         ac->cmd[10] = a10;      ac->cmd[11] = a11;
  798         ac->cmd[12] = a12;      ac->cmd[13] = a13;
  799         ac->cmd[14] = a14;      ac->cmd[15] = a15;
  800         ac->unit = unit;
  801         ac->addr = addr;
  802         ac->count = count;
  803         ac->callback = done;
  804         ac->cbarg1 = x;
  805         ac->cbarg2 = y;
  806 
  807         if (ata->debug)
  808                 printf ("atapi%d.%d: req cb %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x len=%d\n",
  809                         ata->ctrlr, ac->unit, ac->cmd[0], ac->cmd[1],
  810                         ac->cmd[2], ac->cmd[3], ac->cmd[4], ac->cmd[5],
  811                         ac->cmd[6], ac->cmd[7], ac->cmd[8], ac->cmd[9],
  812                         ac->cmd[10], ac->cmd[11], ac->cmd[12],
  813                         ac->cmd[13], ac->cmd[14], ac->cmd[15], count);
  814         atapi_enqueue (ata, ac);
  815         wdstart (ata->ctrlr);
  816 }
  817 
  818 /*
  819  * Queue new packet request, then call wdstart().
  820  * Wait until the request is finished.
  821  * Called on spl0().
  822  * Return atapi error.
  823  * Buffer pointed to by *addr should be placed in core memory, not in stack!
  824  */
  825 struct atapires atapi_request_wait (struct atapi *ata, int unit,
  826         u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4,
  827         u_char a5, u_char a6, u_char a7, u_char a8, u_char a9,
  828         u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15,
  829         char *addr, int count)
  830 {
  831         struct atapicmd *ac;
  832         int x = splbio ();
  833         struct atapires result;
  834 
  835         ac = atapi_alloc (ata);
  836         ac->cmd[0] = cmd;       ac->cmd[1] = a1;
  837         ac->cmd[2] = a2;        ac->cmd[3] = a3;
  838         ac->cmd[4] = a4;        ac->cmd[5] = a5;
  839         ac->cmd[6] = a6;        ac->cmd[7] = a7;
  840         ac->cmd[8] = a8;        ac->cmd[9] = a9;
  841         ac->cmd[10] = a10;      ac->cmd[11] = a11;
  842         ac->cmd[12] = a12;      ac->cmd[13] = a13;
  843         ac->cmd[14] = a14;      ac->cmd[15] = a15;
  844         ac->unit = unit;
  845         ac->addr = addr;
  846         ac->count = count;
  847         ac->callback = 0;
  848         ac->cbarg1 = 0;
  849         ac->cbarg2 = 0;
  850 
  851         if (ata->debug)
  852                 printf ("atapi%d.%d: req w %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x len=%d\n",
  853                         ata->ctrlr, ac->unit, ac->cmd[0], ac->cmd[1],
  854                         ac->cmd[2], ac->cmd[3], ac->cmd[4], ac->cmd[5],
  855                         ac->cmd[6], ac->cmd[7], ac->cmd[8], ac->cmd[9],
  856                         ac->cmd[10], ac->cmd[11], ac->cmd[12],
  857                         ac->cmd[13], ac->cmd[14], ac->cmd[15], count);
  858         atapi_enqueue (ata, ac);
  859         wdstart (ata->ctrlr);
  860         if (ata->tail == ac)
  861                 tsleep ((caddr_t)ac, PRIBIO, "atareq", 0);
  862 
  863         result = ac->result;
  864         atapi_free (ata, ac);
  865         splx (x);
  866         return (result);
  867 }
  868 
  869 /*
  870  * Perform a packet command on the device.
  871  * Should be called on splbio().
  872  * Return atapi error.
  873  */
  874 struct atapires atapi_request_immediate (struct atapi *ata, int unit,
  875         u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4,
  876         u_char a5, u_char a6, u_char a7, u_char a8, u_char a9,
  877         u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15,
  878         char *addr, int count)
  879 {
  880         struct atapicmd cmdbuf, *ac = &cmdbuf;
  881         int cnt;
  882 
  883         ac->cmd[0] = cmd;       ac->cmd[1] = a1;
  884         ac->cmd[2] = a2;        ac->cmd[3] = a3;
  885         ac->cmd[4] = a4;        ac->cmd[5] = a5;
  886         ac->cmd[6] = a6;        ac->cmd[7] = a7;
  887         ac->cmd[8] = a8;        ac->cmd[9] = a9;
  888         ac->cmd[10] = a10;      ac->cmd[11] = a11;
  889         ac->cmd[12] = a12;      ac->cmd[13] = a13;
  890         ac->cmd[14] = a14;      ac->cmd[15] = a15;
  891         ac->unit = unit;
  892         ac->addr = addr;
  893         ac->count = count;
  894         ac->callback = 0;
  895         ac->cbarg1 = 0;
  896         ac->cbarg2 = 0;
  897 
  898         if (ata->debug)
  899                 printf ("atapi%d.%d: req im %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x len=%d\n",
  900                         ata->ctrlr, ac->unit, ac->cmd[0], ac->cmd[1],
  901                         ac->cmd[2], ac->cmd[3], ac->cmd[4], ac->cmd[5],
  902                         ac->cmd[6], ac->cmd[7], ac->cmd[8], ac->cmd[9],
  903                         ac->cmd[10], ac->cmd[11], ac->cmd[12],
  904                         ac->cmd[13], ac->cmd[14], ac->cmd[15], count);
  905 
  906         /* Start packet command, wait for DRQ. */
  907         if (atapi_strt_cmd (ata, ac) >= 0 && atapi_wait_cmd (ata, ac) >= 0) {
  908                 /* Send packet command. */
  909                 atapi_send_cmd (ata, ac);
  910 
  911                 /* Wait for data i/o phase. */
  912                 for (cnt=20000; cnt>0; --cnt)
  913                         if (((inb (ata->port + AR_IREASON) & (ARI_CMD | ARI_IN)) |
  914                             (inb (ata->port + AR_STATUS) & ARS_DRQ)) != PHASE_CMDOUT)
  915                                 break;
  916 
  917                 /* Do all needed i/o. */
  918                 while (atapi_io (ata, ac))
  919                         /* Wait for DRQ deassert. */
  920                         for (cnt=2000; cnt>0; --cnt) {
  921                                 if (! (inb (ata->port + AR_STATUS) & ARS_DRQ))
  922                                         break;
  923                                 DELAY(10);
  924                         }
  925         }
  926         return (ac->result);
  927 }
  928 
  929 #endif /* NWDC */

Cache object: a41bff07b1f60f53abe0d80fea1ef6bc


[ 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.