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/pc/sdmylex.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  * Mylex MultiMaster (Buslogic BT-*) SCSI Host Adapter
    3  * in both 24-bit and 32-bit mode.
    4  * 24-bit mode works for Adaptec AHA-154xx series too.
    5  *
    6  * To do:
    7  *      allocate more Ccb's as needed, up to NMbox-1;
    8  *      add nmbox and nccb to Ctlr struct for the above;
    9  *      64-bit LUN/explicit wide support necessary?
   10  *
   11  */
   12 #include "u.h"
   13 #include "../port/lib.h"
   14 #include "mem.h"
   15 #include "dat.h"
   16 #include "fns.h"
   17 #include "io.h"
   18 #include "ureg.h"
   19 #include "../port/error.h"
   20 
   21 #include "../port/sd.h"
   22 
   23 #define K2BPA(va, tbdf) PADDR(va)
   24 #define BPA2K(pa, tbdf) KADDR(pa)
   25 
   26 extern SDifc sdmylexifc;
   27 
   28 enum {                                  /* registers */
   29         Rcontrol        = 0x00,         /* WO: control register */
   30         Rstatus         = 0x00,         /* RO: status register */
   31         Rcpr            = 0x01,         /* WO: command/parameter register */
   32         Rdatain         = 0x01,         /* RO: data-in register */
   33         Rinterrupt      = 0x02,         /* RO: interrupt register */
   34 };
   35 
   36 enum {                                  /* Rcontrol */
   37         Rsbus           = 0x10,         /* SCSI Bus Reset */
   38         Rint            = 0x20,         /* Interrupt Reset */
   39         Rsoft           = 0x40,         /* Soft Reset */
   40         Rhard           = 0x80,         /* Hard Reset */
   41 };
   42 
   43 enum {                                  /* Rstatus */
   44         Cmdinv          = 0x01,         /* Command Invalid */
   45         Dirrdy          = 0x04,         /* Data In Register Ready */
   46         Cprbsy          = 0x08,         /* Command/Parameter Register Busy */
   47         Hardy           = 0x10,         /* Host Adapter Ready */
   48         Inreq           = 0x20,         /* Initialisation Required */
   49         Dfail           = 0x40,         /* Diagnostic Failure */
   50         Dact            = 0x80,         /* Diagnostic Active */
   51 };
   52 
   53 enum {                                  /* Rcpr */
   54         Cinitialise     = 0x01,         /* Initialise Mailbox */
   55         Cstart          = 0x02,         /* Start Mailbox Command */
   56         Cinquiry        = 0x04,         /* Adapter Inquiry */
   57         Ceombri         = 0x05,         /* Enable OMBR Interrupt */
   58         Cinquire        = 0x0B,         /* Inquire Configuration */
   59         Cextbios        = 0x28,         /* AHA-1542: extended BIOS info. */
   60         Cmbienable      = 0x29,         /* AHA-1542: Mailbox interface enable */
   61         Ciem            = 0x81,         /* Initialise Extended Mailbox */
   62         Ciesi           = 0x8D,         /* Inquire Extended Setup Information */
   63         Cerrm           = 0x8F,         /* Enable strict round-robin mode */
   64         Cwide           = 0x96,         /* Wide CCB */
   65 };
   66 
   67 enum {                                  /* Rinterrupt */
   68         Imbl            = 0x01,         /* Incoming Mailbox Loaded */
   69         Mbor            = 0x02,         /* Mailbox Out Ready */
   70         Cmdc            = 0x04,         /* Command Complete */
   71         Rsts            = 0x08,         /* SCSI Reset State */
   72         Intv            = 0x80,         /* Interrupt Valid */
   73 };
   74 
   75 typedef struct Mbox24 Mbox24;
   76 struct Mbox24 {
   77         uchar   code;                   /* action/completion code */
   78         uchar   ccb[3];                 /* CCB pointer (MSB, ..., LSB) */
   79 };
   80 
   81 typedef struct Mbox32 Mbox32;
   82 struct Mbox32 {
   83         uchar   ccb[4];                 /* CCB pointer (LSB, ..., MSB) */
   84         uchar   btstat;                 /* BT-7[45]7[SD] status */
   85         uchar   sdstat;                 /* SCSI device status */
   86         uchar   pad;
   87         uchar   code;                   /* action/completion code */
   88 };
   89 
   90 enum {                                  /* mailbox commands */
   91         Mbfree          = 0x00,         /* Mailbox not in use */
   92 
   93         Mbostart        = 0x01,         /* Start a mailbox command */
   94         Mboabort        = 0x02,         /* Abort a mailbox command */
   95 
   96         Mbiok           = 0x01,         /* CCB completed without error */
   97         Mbiabort        = 0x02,         /* CCB aborted at request of host */
   98         Mbinx           = 0x03,         /* Aborted CCB not found */
   99         Mbierror        = 0x04,         /* CCB completed with error */
  100 };
  101 
  102 typedef struct Ccb24 Ccb24;
  103 typedef struct Ccb32 Ccb32;
  104 typedef union Ccb Ccb;
  105 
  106 typedef struct Ccb24 {
  107         uchar   opcode;                 /* Operation code */
  108         uchar   datadir;                /* Data direction control */
  109         uchar   cdblen;                 /* Length of CDB */
  110         uchar   senselen;               /* Length of sense area */
  111         uchar   datalen[3];             /* Data length (MSB, ..., LSB) */
  112         uchar   dataptr[3];             /* Data pointer (MSB, ..., LSB) */
  113         uchar   linkptr[3];             /* Link pointer (MSB, ..., LSB) */
  114         uchar   linkid;                 /* command linking identifier */
  115         uchar   btstat;                 /* BT-* adapter status */
  116         uchar   sdstat;                 /* SCSI device status */
  117         uchar   reserved[2];            /* */
  118         uchar   cs[12+0xFF];            /* Command descriptor block + Sense */
  119 
  120         void*   data;                   /* buffer if address > 24-bits */
  121 
  122         Rendez;
  123         int     done;                   /* command completed */
  124 
  125         Ccb*    ccb;                    /* link on free list */
  126 } Ccb24;
  127 
  128 
  129 typedef struct Ccb32 {
  130         uchar   opcode;                 /* Operation code */
  131         uchar   datadir;                /* Data direction control */
  132         uchar   cdblen;                 /* Length of CDB */
  133         uchar   senselen;               /* Length of sense area */
  134         uchar   datalen[4];             /* Data length (LSB, ..., MSB) */
  135         uchar   dataptr[4];             /* Data pointer (LSB, ..., MSB) */
  136         uchar   reserved[2];
  137         uchar   btstat;                 /* BT-* adapter status */
  138         uchar   sdstat;                 /* SCSI device status */
  139         uchar   targetid;               /* Target ID */
  140         uchar   luntag;                 /* LUN & tag */
  141         uchar   cdb[12];                /* Command descriptor block */
  142         uchar   ccbctl;                 /* CCB control */
  143         uchar   linkid;                 /* command linking identifier */
  144         uchar   linkptr[4];             /* Link pointer (LSB, ..., MSB) */
  145         uchar   senseptr[4];            /* Sense pointer (LSB, ..., MSB) */
  146         uchar   sense[0xFF];            /* Sense bytes */
  147 
  148         Rendez;
  149         int     done;                   /* command completed */
  150 
  151         Ccb*    ccb;                    /* link on free list */
  152 } Ccb32;
  153 
  154 typedef union Ccb {
  155         Ccb24;
  156         Ccb32;
  157 } Ccb;
  158 
  159 enum {                                  /* opcode */
  160         OInitiator      = 0x00,         /* initiator CCB */
  161         Ordl            = 0x03,         /* initiator CCB with
  162                                          * residual data length returned
  163                                          */
  164 };
  165 
  166 enum {                                  /* datadir */
  167         CCBdatain       = 0x08,         /* inbound, length is checked */
  168         CCBdataout      = 0x10,         /* outbound, length is checked */
  169 };
  170 
  171 enum {                                  /* btstat */
  172         Eok             = 0x00,         /* normal completion with no errors */
  173 };
  174 
  175 enum {                                  /* luntag */
  176         TagEnable       = 0x20,         /* Tag enable */
  177         SQTag           = 0x00,         /* Simple Queue Tag */
  178         HQTag           = 0x40,         /* Head of Queue Tag */
  179         OQTag           = 0x80,         /* Ordered Queue Tag */
  180 };
  181 
  182 enum {                                  /* CCB control */
  183         NoDisc          = 0x08,         /* No disconnect */
  184         NoUnd           = 0x10,         /* No underrrun error report */
  185         NoData          = 0x20,         /* No data transfer */
  186         NoStat          = 0x40,         /* No CCB status if zero */
  187         NoIntr          = 0x80,         /* No Interrupts */
  188 };
  189 
  190 typedef struct Ctlr Ctlr;
  191 struct Ctlr {
  192         int     port;                   /* I/O port */
  193         int     id;                     /* adapter SCSI id */
  194         int     bus;                    /* 24 or 32 -bit */
  195         int     irq;
  196         int     wide;
  197         Pcidev* pcidev;
  198         SDev*   sdev;
  199         int     spurious;
  200 
  201         Lock    issuelock;
  202 
  203         Lock    ccblock;
  204         QLock   ccbq;
  205         Rendez  ccbr;
  206 
  207         Lock    mboxlock;
  208         void*   mb;                     /* mailbox out + mailbox in */
  209         int     mbox;                   /* current mailbox out index into mb */
  210         int     mbix;                   /* current mailbox in index into mb */
  211 
  212         Lock    cachelock;
  213         Ccb*    ccb;                    /* list of free Ccb's */
  214         Ccb**   cache;                  /* last completed Ccb */
  215 };
  216 
  217 /*
  218  * The number of mailboxes should be a multiple of 8 (4 for Mbox32)
  219  * to ensure the boundary between the out and in mailboxes doesn't
  220  * straddle a cache-line boundary.
  221  * The number of Ccb's should be less than the number of mailboxes to
  222  * ensure no queueing is necessary on mailbox allocation.
  223  */
  224 enum {
  225         NMbox           = 8*8,          /* number of Mbox's */
  226         NCcb            = NMbox-1,      /* number of Ccb's */
  227 };
  228 
  229 #define PADDR24(a, n)   ((PADDR(a)+(n)) <= (1<<24))
  230 
  231 static void
  232 ccbfree(Ctlr* ctlr, Ccb* ccb)
  233 {
  234         lock(&ctlr->ccblock);
  235         if(ctlr->bus == 24)
  236                 ((Ccb24*)ccb)->ccb = ctlr->ccb;
  237         else
  238                 ((Ccb32*)ccb)->ccb = ctlr->ccb;
  239         if(ctlr->ccb == nil)
  240                 wakeup(&ctlr->ccbr);
  241         ctlr->ccb = ccb;
  242         unlock(&ctlr->ccblock);
  243 }
  244 
  245 static int
  246 ccbavailable(void* a)
  247 {
  248         return ((Ctlr*)a)->ccb != nil;
  249 }
  250 
  251 static Ccb*
  252 ccballoc(Ctlr* ctlr)
  253 {
  254         Ccb *ccb;
  255 
  256         for(;;){
  257                 lock(&ctlr->ccblock);
  258                 if((ccb = ctlr->ccb) != nil){
  259                         if(ctlr->bus == 24)
  260                                  ctlr->ccb = ((Ccb24*)ccb)->ccb;
  261                         else
  262                                  ctlr->ccb = ((Ccb32*)ccb)->ccb;
  263                         unlock(&ctlr->ccblock);
  264                         break;
  265                 }
  266 
  267                 unlock(&ctlr->ccblock);
  268                 qlock(&ctlr->ccbq);
  269                 if(waserror()){
  270                         qunlock(&ctlr->ccbq);
  271                         continue;
  272                 }
  273                 sleep(&ctlr->ccbr, ccbavailable, ctlr);
  274                 qunlock(&ctlr->ccbq);
  275                 poperror();
  276         }
  277 
  278         return ccb;
  279 }
  280 
  281 static int
  282 done24(void* arg)
  283 {
  284         return ((Ccb24*)arg)->done;
  285 }
  286 
  287 static int
  288 mylex24rio(SDreq* r)
  289 {
  290         ulong p;
  291         Ctlr *ctlr;
  292         Ccb24 *ccb;
  293         Mbox24 *mb;
  294         uchar *data, lun, *sense;
  295         int d, n, btstat, sdstat, target;
  296 
  297         ctlr = r->unit->dev->ctlr;
  298         target = r->unit->subno;
  299         lun = (r->cmd[1]>>5) & 0x07;
  300 
  301         /*
  302          * Ctlr->cache holds the last completed Ccb for this target if it
  303          * returned 'check condition'.
  304          * If this command is a request-sense and there is valid sense data
  305          * from the last completed Ccb, return it immediately.
  306          */
  307         lock(&ctlr->cachelock);
  308         if((ccb = ctlr->cache[target]) != nil){
  309                 ctlr->cache[target] = nil;
  310                 if(r->cmd[0] == 0x03
  311                 && ccb->sdstat == SDcheck && lun == ((ccb->cs[1]>>5) & 0x07)){
  312                         unlock(&ctlr->cachelock);
  313                         if(r->dlen){
  314                                 sense = &ccb->cs[ccb->cdblen];
  315                                 n = 8+sense[7];
  316                                 if(n > r->dlen)
  317                                         n = r->dlen;
  318                                 memmove(r->data, sense, n);
  319                                 r->rlen = n;
  320                         }
  321                         ccbfree(ctlr, (Ccb*)ccb);
  322                         return SDok;
  323                 }
  324         }
  325         unlock(&ctlr->cachelock);
  326         if(ccb == nil)
  327                 ccb = ccballoc(ctlr);
  328 
  329         /*
  330          * Check if the transfer is to memory above the 24-bit limit the
  331          * controller can address. If it is, try to allocate a temporary
  332          * buffer as a staging area.
  333          */
  334         n = r->dlen;
  335         if(n && !PADDR24(r->data, n)){
  336                 data = mallocz(n, 0);
  337                 if(data == nil || !PADDR24(data, n)){
  338                         if(data != nil){
  339                                 free(data);
  340                                 ccb->data = nil;
  341                         }
  342                         ccbfree(ctlr, (Ccb*)ccb);
  343                         return SDmalloc;
  344                 }
  345                 if(r->write)
  346                         memmove(data, r->data, n);
  347                 ccb->data = r->data;
  348         }
  349         else
  350                 data = r->data;
  351 
  352         /*
  353          * Fill in the ccb.
  354          */
  355         ccb->opcode = Ordl;
  356 
  357         ccb->datadir = (target<<5)|lun;
  358         if(n == 0)
  359                 ccb->datadir |= CCBdataout|CCBdatain;
  360         else if(!r->write)
  361                 ccb->datadir |= CCBdatain;
  362         else
  363                 ccb->datadir |= CCBdataout;
  364 
  365         ccb->cdblen = r->clen;
  366         ccb->senselen = 0xFF;
  367 
  368         ccb->datalen[0] = n>>16;
  369         ccb->datalen[1] = n>>8;
  370         ccb->datalen[2] = n;
  371         if(data == nil)
  372                 p = 0;
  373         else
  374                 p = PADDR(data);
  375         ccb->dataptr[0] = p>>16;
  376         ccb->dataptr[1] = p>>8;
  377         ccb->dataptr[2] = p;
  378 
  379         ccb->linkptr[0] = ccb->linkptr[1] = ccb->linkptr[2] = 0;
  380         ccb->linkid = 0;
  381         ccb->btstat = ccb->sdstat = 0;
  382         ccb->reserved[0] = ccb->reserved[1] = 0;
  383 
  384         memmove(ccb->cs, r->cmd, r->clen);
  385 
  386         /*
  387          * There's one more mbox than there there is
  388          * ccb so there is always one free.
  389          */
  390         lock(&ctlr->mboxlock);
  391         mb = ctlr->mb;
  392         mb += ctlr->mbox;
  393         p = PADDR(ccb);
  394         mb->ccb[0] = p>>16;
  395         mb->ccb[1] = p>>8;
  396         mb->ccb[2] = p;
  397         mb->code = Mbostart;
  398         ctlr->mbox++;
  399         if(ctlr->mbox >= NMbox)
  400                 ctlr->mbox = 0;
  401 
  402         /*
  403          * This command does not require Hardy
  404          * and doesn't generate a Cmdc interrupt.
  405          */
  406         ccb->done = 0;
  407         outb(ctlr->port+Rcpr, Cstart);
  408         unlock(&ctlr->mboxlock);
  409 
  410         /*
  411          * Wait for the request to complete and return the status.
  412          * Since the buffer is not reference counted cannot return
  413          * until the DMA is done writing into the buffer so the caller
  414          * cannot free the buffer prematurely.
  415          */
  416         while(waserror())
  417                 ;
  418         sleep(ccb, done24, ccb);
  419         poperror();
  420 
  421         /*
  422          * Save the status and patch up the number of
  423          * bytes actually transferred.
  424          * There's a firmware bug on some 956C controllers
  425          * which causes the return count from a successful
  426          * READ CAPACITY not be updated, so fix it here.
  427          */
  428         sdstat = ccb->sdstat;
  429         btstat = ccb->btstat;
  430 
  431         d = ccb->datalen[0]<<16;
  432         d |= ccb->datalen[1]<<8;
  433         d |= ccb->datalen[2];
  434         if(ccb->cs[0] == 0x25 && sdstat == SDok)
  435                 d = 0;
  436         n -= d;
  437         r->rlen = n;
  438 
  439         /*
  440          * Tidy things up if a staging area was used for the data,
  441          */
  442         if(ccb->data != nil){
  443                 if(sdstat == SDok && btstat == 0 && !r->write)
  444                         memmove(ccb->data, data, n);
  445                 free(data);
  446                 ccb->data = nil;
  447         }
  448 
  449         /*
  450          * If there was a check-condition, save the
  451          * ccb for a possible request-sense command.
  452          */
  453         if(sdstat == SDcheck){
  454                 if(r->flags & SDnosense){
  455                         lock(&ctlr->cachelock);
  456                         if(ctlr->cache[target])
  457                                 ccbfree(ctlr, ctlr->cache[target]);
  458                         ctlr->cache[target] = (Ccb*)ccb;
  459                         unlock(&ctlr->cachelock);
  460                         return SDcheck;
  461                 }
  462                 sense = &ccb->cs[ccb->cdblen];
  463                 n = 8+sense[7];
  464                 if(n > sizeof(r->sense)-1)
  465                         n = sizeof(r->sense)-1;
  466                 memmove(r->sense, sense, n);
  467                 r->flags |= SDvalidsense;
  468         }
  469         ccbfree(ctlr, (Ccb*)ccb);
  470 
  471         if(btstat){
  472                 if(btstat == 0x11)
  473                         return SDtimeout;
  474                 return SDeio;
  475         }
  476         return sdstat;
  477 }
  478 
  479 static void
  480 mylex24interrupt(Ureg*, void* arg)
  481 {
  482         ulong pa;
  483         Ctlr *ctlr;
  484         Ccb24 *ccb;
  485         Mbox24 *mb, *mbox;
  486         int port, rinterrupt, rstatus;
  487 
  488         ctlr = arg;
  489         port = ctlr->port;
  490 
  491         /*
  492          * Save and clear the interrupt(s). The only
  493          * interrupts expected are Cmdc, which is ignored,
  494          * and Imbl which means something completed.
  495          * There's one spurious interrupt left over from
  496          * initialisation, ignore it.
  497          */
  498         rinterrupt = inb(port+Rinterrupt);
  499         rstatus = inb(port+Rstatus);
  500         outb(port+Rcontrol, Rint);
  501         if((rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
  502                 print("%s: interrupt 0x%2.2ux\n",
  503                         ctlr->sdev->name, rinterrupt);
  504         if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
  505                 print("%s: command invalid\n", ctlr->sdev->name);
  506 
  507         /*
  508          * Look for something in the mail.
  509          * If there is, save the status, free the mailbox
  510          * and wakeup whoever.
  511          */
  512         mb = ctlr->mb;
  513         for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
  514                 pa = (mbox->ccb[0]<<16)|(mbox->ccb[1]<<8)|mbox->ccb[2];
  515                 ccb = BPA2K(pa, BUSUNKNOWN);
  516                 mbox->code = 0;
  517                 ccb->done = 1;
  518                 wakeup(ccb);
  519 
  520                 ctlr->mbix++;
  521                 if(ctlr->mbix >= NMbox+NMbox)
  522                         ctlr->mbix = NMbox;
  523         }
  524 }
  525 
  526 static int
  527 done32(void* arg)
  528 {
  529         return ((Ccb32*)arg)->done;
  530 }
  531 
  532 static int
  533 mylex32rio(SDreq* r)
  534 {
  535         ulong p;
  536         uchar lun;
  537         Ctlr *ctlr;
  538         Ccb32 *ccb;
  539         Mbox32 *mb;
  540         int d, n, btstat, sdstat, target;
  541 
  542         ctlr = r->unit->dev->ctlr;
  543         target = r->unit->subno;
  544         lun = (r->cmd[1]>>5) & 0x07;
  545 
  546         /*
  547          * Ctlr->cache holds the last completed Ccb for this target if it
  548          * returned 'check condition'.
  549          * If this command is a request-sense and there is valid sense data
  550          * from the last completed Ccb, return it immediately.
  551          */
  552         lock(&ctlr->cachelock);
  553         if((ccb = ctlr->cache[target]) != nil){
  554                 ctlr->cache[target] = nil;
  555                 if(r->cmd[0] == 0x03
  556                 && ccb->sdstat == SDcheck && lun == (ccb->luntag & 0x07)){
  557                         unlock(&ctlr->cachelock);
  558                         if(r->dlen){
  559                                 n = 8+ccb->sense[7];
  560                                 if(n > r->dlen)
  561                                         n = r->dlen;
  562                                 memmove(r->data, ccb->sense, n);
  563                                 r->rlen = n;
  564                         }
  565                         ccbfree(ctlr, (Ccb*)ccb);
  566                         return SDok;
  567                 }
  568         }
  569         unlock(&ctlr->cachelock);
  570         if(ccb == nil)
  571                 ccb = ccballoc(ctlr);
  572 
  573         /*
  574          * Fill in the ccb.
  575          */
  576         ccb->opcode = Ordl;
  577 
  578         n = r->dlen;
  579         if(n == 0)
  580                 ccb->datadir = CCBdataout|CCBdatain;
  581         else if(!r->write)
  582                 ccb->datadir = CCBdatain;
  583         else
  584                 ccb->datadir = CCBdataout;
  585 
  586         ccb->cdblen = r->clen;
  587 
  588         ccb->datalen[0] = n;
  589         ccb->datalen[1] = n>>8;
  590         ccb->datalen[2] = n>>16;
  591         ccb->datalen[3] = n>>24;
  592         if(r->data == nil)
  593                 p = 0;
  594         else
  595                 p = PADDR(r->data);
  596         ccb->dataptr[0] = p;
  597         ccb->dataptr[1] = p>>8;
  598         ccb->dataptr[2] = p>>16;
  599         ccb->dataptr[3] = p>>24;
  600 
  601         ccb->targetid = target;
  602         ccb->luntag = lun;
  603         if(r->unit->inquiry[7] & 0x02)
  604                 if(ctlr->wide)
  605                         ccb->datadir |= SQTag|TagEnable;
  606                 else
  607                         ccb->luntag |= SQTag|TagEnable;
  608         memmove(ccb->cdb, r->cmd, r->clen);
  609         ccb->btstat = ccb->sdstat = 0;
  610         ccb->ccbctl = 0;
  611 
  612         /*
  613          * There's one more mbox than there there is
  614          * ccb so there is always one free.
  615          */
  616         lock(&ctlr->mboxlock);
  617         mb = ctlr->mb;
  618         mb += ctlr->mbox;
  619         p = PADDR(ccb);
  620         mb->ccb[0] = p;
  621         mb->ccb[1] = p>>8;
  622         mb->ccb[2] = p>>16;
  623         mb->ccb[3] = p>>24;
  624         mb->code = Mbostart;
  625         ctlr->mbox++;
  626         if(ctlr->mbox >= NMbox)
  627                 ctlr->mbox = 0;
  628 
  629         /*
  630          * This command does not require Hardy
  631          * and doesn't generate a Cmdc interrupt.
  632          */
  633         ccb->done = 0;
  634         outb(ctlr->port+Rcpr, Cstart);
  635         unlock(&ctlr->mboxlock);
  636 
  637         /*
  638          * Wait for the request to complete and return the status.
  639          * Since the buffer is not reference counted cannot return
  640          * until the DMA is done writing into the buffer so the caller
  641          * cannot free the buffer prematurely.
  642          */
  643         while(waserror())
  644                 ;
  645         sleep(ccb, done32, ccb);
  646         poperror();
  647 
  648         /*
  649          * Save the status and patch up the number of
  650          * bytes actually transferred.
  651          * There's a firmware bug on some 956C controllers
  652          * which causes the return count from a successful
  653          * READ CAPACITY not to be updated, so fix it here.
  654          */
  655         sdstat = ccb->sdstat;
  656         btstat = ccb->btstat;
  657 
  658         d = ccb->datalen[0];
  659         d |= (ccb->datalen[1]<<8);
  660         d |= (ccb->datalen[2]<<16);
  661         d |= (ccb->datalen[3]<<24);
  662         if(ccb->cdb[0] == 0x25 && sdstat == SDok)
  663                 d = 0;
  664         n -= d;
  665         r->rlen = n;
  666 
  667         /*
  668          * If there was a check-condition, save the
  669          * ccb for a possible request-sense command.
  670          */
  671         if(sdstat == SDcheck){
  672                 if(r->flags & SDnosense){
  673                         lock(&ctlr->cachelock);
  674                         if(ctlr->cache[target])
  675                                 ccbfree(ctlr, ctlr->cache[target]);
  676                         ctlr->cache[target] = (Ccb*)ccb;
  677                         unlock(&ctlr->cachelock);
  678                         return SDcheck;
  679                 }
  680                 n = 8+ccb->sense[7];
  681                 if(n > sizeof(r->sense)-1)
  682                         n = sizeof(r->sense)-1;
  683                 memmove(r->sense, ccb->sense, n);
  684                 r->flags |= SDvalidsense;
  685         }
  686         ccbfree(ctlr, (Ccb*)ccb);
  687 
  688         if(btstat){
  689                 if(btstat == 0x11)
  690                         return SDtimeout;
  691                 return SDeio;
  692         }
  693         return sdstat;
  694 }
  695 
  696 static void
  697 mylex32interrupt(Ureg*, void* arg)
  698 {
  699         ulong pa;
  700         Ctlr *ctlr;
  701         Ccb32 *ccb;
  702         Mbox32 *mb, *mbox;
  703         int port, rinterrupt, rstatus;
  704 
  705         ctlr = arg;
  706         port = ctlr->port;
  707 
  708         /*
  709          * Save and clear the interrupt(s). The only
  710          * interrupts expected are Cmdc, which is ignored,
  711          * and Imbl which means something completed.
  712          * There's one spurious interrupt left over from
  713          * initialisation, ignore it.
  714          * In order to share PCI IRQs, just ignore spurious interrupts.
  715          */
  716         rinterrupt = inb(port+Rinterrupt);
  717         rstatus = inb(port+Rstatus);
  718         outb(port+Rcontrol, Rint);
  719         if(0 && (rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
  720                 print("%s: interrupt 0x%2.2ux\n",
  721                         ctlr->sdev->name, rinterrupt);
  722         if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
  723                 print("%s: command invalid\n", ctlr->sdev->name);
  724 
  725         /*
  726          * Look for something in the mail.
  727          * If there is, free the mailbox and wakeup whoever.
  728          */
  729         mb = ctlr->mb;
  730         for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
  731                 pa = (mbox->ccb[3]<<24)
  732                     |(mbox->ccb[2]<<16)
  733                     |(mbox->ccb[1]<<8)
  734                     |mbox->ccb[0];
  735                 if(ctlr->pcidev)
  736                         ccb = BPA2K(pa, ctlr->pcidev->tbdf);
  737                 else
  738                         ccb = BPA2K(pa, BUSUNKNOWN);
  739                 mbox->code = 0;
  740                 ccb->done = 1;
  741                 wakeup(ccb);
  742 
  743                 ctlr->mbix++;
  744                 if(ctlr->mbix >= NMbox+NMbox)
  745                         ctlr->mbix = NMbox;
  746         }
  747 }
  748 
  749 static int
  750 mylexrio(SDreq* r)
  751 {
  752         int subno;
  753         Ctlr *ctlr;
  754 
  755         subno = r->unit->subno;
  756         ctlr = r->unit->dev->ctlr;
  757         if(subno == ctlr->id || (!ctlr->wide && subno >= 8))
  758                 r->status = SDtimeout;
  759         else if(ctlr->bus == 24)
  760                 r->status = mylex24rio(r);
  761         else
  762                 r->status = mylex32rio(r);
  763         return r->status;
  764 }
  765 
  766 /*
  767  * Issue a command to a controller. The command and its length is
  768  * contained in cmd and cmdlen. If any data is to be
  769  * returned, datalen should be non-zero, and the returned data
  770  * will be placed in data.
  771  * If Cmdc is set, bail out, the invalid command will be handled
  772  * when the interrupt is processed.
  773  */
  774 static void
  775 issueio(int port, uchar* cmd, int cmdlen, uchar* data, int datalen)
  776 {
  777         int len;
  778 
  779         if(cmd[0] != Cstart && cmd[0] != Ceombri){
  780                 while(!(inb(port+Rstatus) & Hardy))
  781                         ;
  782         }
  783         outb(port+Rcpr, cmd[0]);
  784 
  785         len = 1;
  786         while(len < cmdlen){
  787                 if(!(inb(port+Rstatus) & Cprbsy)){
  788                         outb(port+Rcpr, cmd[len]);
  789                         len++;
  790                 }
  791                 if(inb(port+Rinterrupt) & Cmdc)
  792                         return;
  793         }
  794 
  795         if(datalen){
  796                 len = 0;
  797                 while(len < datalen){
  798                         if(inb(port+Rstatus) & Dirrdy){
  799                                 data[len] = inb(port+Rdatain);
  800                                 len++;
  801                         }
  802                         if(inb(port+Rinterrupt) & Cmdc)
  803                                 return;
  804                 }
  805         }
  806 }
  807 
  808 /*
  809  * Issue a command to a controller, wait for it to complete then
  810  * try to reset the interrupt. Should only be called at initialisation.
  811  */
  812 static int
  813 issue(Ctlr* ctlr, uchar* cmd, int cmdlen, uchar* data, int datalen)
  814 {
  815         int port;
  816         uchar rinterrupt, rstatus;
  817         static Lock mylexissuelock;
  818 
  819         port = ctlr->port;
  820 
  821         ilock(&ctlr->issuelock);
  822         issueio(port, cmd, cmdlen, data, datalen);
  823 
  824         while(!((rinterrupt = inb(port+Rinterrupt)) & Cmdc))
  825                 ;
  826 
  827         rstatus = inb(port+Rstatus);
  828         outb(port+Rcontrol, Rint);
  829         iunlock(&ctlr->issuelock);
  830 
  831         if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
  832                 return 0;
  833         return 1;
  834 }
  835 
  836 static SDev*
  837 mylexprobe(int port, int irq)
  838 {
  839         SDev *sdev;
  840         Ctlr *ctlr;
  841         uchar cmd[6], data[256];
  842         int clen, dlen, timeo;
  843         static int count;
  844 
  845         if(ioalloc(port, 0x3, 0, "mylex") < 0)
  846                 return nil;
  847         ctlr = nil;
  848         sdev = nil;
  849         /*
  850          * Attempt to hard-reset the board and reset
  851          * the SCSI bus. If the board state doesn't settle to
  852          * idle with mailbox initialisation required, either
  853          * it isn't a compatible board or it's broken.
  854          * If the controller has SCAM set this can take a while.
  855          */
  856         if(getconf("*noscsireset") != nil)
  857                 outb(port+Rcontrol, Rhard);
  858         else
  859                 outb(port+Rcontrol, Rhard|Rsbus);
  860         for(timeo = 0; timeo < 100; timeo++){
  861                 if(inb(port+Rstatus) == (Inreq|Hardy))
  862                         break;
  863                 delay(100);
  864         }
  865         if(inb(port+Rstatus) != (Inreq|Hardy)){
  866 buggery:
  867                 if(ctlr != nil)
  868                         free(ctlr);
  869                 if (sdev != nil)
  870                         free(sdev);
  871                 iofree(port);
  872                 return nil;
  873         }
  874 
  875         if((ctlr = malloc(sizeof(Ctlr))) == nil)
  876                 goto buggery;
  877         ctlr->port = port;
  878         ctlr->irq = irq;
  879         ctlr->bus = 24;
  880         ctlr->wide = 0;
  881 
  882         /*
  883          * Try to determine if this is a 32-bit MultiMaster controller
  884          * by attempting to obtain the extended inquiry information;
  885          * this command is not implemented on Adaptec 154xx
  886          * controllers. If successful, the first byte of the returned
  887          * data is the host adapter bus type, 'E' for 32-bit EISA,
  888          * PCI and VLB buses.
  889          */
  890         cmd[0] = Ciesi;
  891         cmd[1] = 14;
  892         clen = 2;
  893         dlen = 256;
  894         if(issue(ctlr, cmd, clen, data, dlen)){
  895                 if(data[0] == 'E')
  896                         ctlr->bus = 32;
  897                 ctlr->wide = data[0x0D] & 0x01;
  898                 /*
  899                  * devsd doesn't pass us the `spec' argument, so
  900                  * we'll assume that sd0 goes to the first scsi host
  901                  * adapter found, etc.
  902                  */
  903                 print("#S/sd%d: mylex SCSI: port 0x%ux: %d-bit, ",
  904                         count++, ctlr->port, ctlr->bus);
  905                 if (ctlr->wide)
  906                         print("wide\n");
  907                 else
  908                         print("narrow\n");
  909         }
  910         else{
  911                 /*
  912                  * Inconceivable though it may seem, a hard controller reset
  913                  * is necessary here to clear out the command queue. Every
  914                  * board seems to lock-up in a different way if you give an
  915                  * invalid command and then try to clear out the
  916                  * command/parameter and/or data-in register.
  917                  * Soft reset doesn't do the job either. Fortunately no
  918                  * serious initialisation has been done yet so there's nothing
  919                  * to tidy up.
  920                  */
  921                 outb(port+Rcontrol, Rhard);
  922                 for(timeo = 0; timeo < 100; timeo++){
  923                         if(inb(port+Rstatus) == (Inreq|Hardy))
  924                                 break;
  925                         delay(100);
  926                 }
  927                 if(inb(port+Rstatus) != (Inreq|Hardy))
  928                         goto buggery;
  929         }
  930 
  931         /*
  932          * If the BIOS is enabled on the AHA-1542C/CF and BIOS options for
  933          * support of drives > 1Gb, dynamic scanning of the SCSI bus or more
  934          * than 2 drives under DOS 5.0 are enabled, the BIOS disables
  935          * accepting Cmbinit to protect against running with drivers which
  936          * don't support those options. In order to unlock the interface it
  937          * is necessary to read a lock-code using Cextbios and write it back
  938          * using Cmbienable; the lock-code is non-zero.
  939          */
  940         cmd[0] = Cinquiry;
  941         clen = 1;
  942         dlen = 4;
  943         if(issue(ctlr, cmd, clen, data, dlen) == 0)
  944                 goto buggery;
  945         if(data[0] >= 0x43){
  946                 cmd[0] = Cextbios;
  947                 clen = 1;
  948                 dlen = 2;
  949                 if(issue(ctlr, cmd, clen, data, dlen) == 0)
  950                         goto buggery;
  951 
  952                 /*
  953                  * Lock-code returned in data[1]. If it's non-zero write
  954                  * it back along with bit 0 of byte 0 cleared to enable
  955                  * mailbox initialisation.
  956                  */
  957                 if(data[1]){
  958                         cmd[0] = Cmbienable;
  959                         cmd[1] = 0;
  960                         cmd[2] = data[1];
  961                         clen = 3;
  962                         if(issue(ctlr, cmd, clen, 0, 0) == 0)
  963                                 goto buggery;
  964                 }
  965         }
  966 
  967         /*
  968          * Get the id, DMA and IRQ info from the board. This will
  969          * cause an interrupt which will hopefully not cause any
  970          * trouble because the interrupt number isn't known yet.
  971          * This is necessary as the DMA won't be set up if the
  972          * board has the BIOS disabled.
  973          *
  974          * If the IRQ is already known, this must be a 32-bit PCI
  975          * or EISA card, in which case the returned DMA and IRQ can
  976          * be ignored.
  977          */
  978         cmd[0] = Cinquire;
  979         clen = 1;
  980         dlen = 3;
  981         if(issue(ctlr, cmd, clen, data, dlen) == 0)
  982                 goto buggery;
  983 
  984         ctlr->id = data[2] & 0x07;
  985         if(ctlr->irq < 0){
  986                 switch(data[0]){                /* DMA Arbitration Priority */
  987                 case 0x80:                      /* Channel 7 */
  988                         outb(0xD6, 0xC3);
  989                         outb(0xD4, 0x03);
  990                         break;
  991                 case 0x40:                      /* Channel 6 */
  992                         outb(0xD6, 0xC2);
  993                         outb(0xD4, 0x02);
  994                         break;
  995                 case 0x20:                      /* Channel 5 */
  996                         outb(0xD6, 0xC1);
  997                         outb(0xD4, 0x01);
  998                         break;
  999                 case 0x01:                      /* Channel 0 */
 1000                         outb(0x0B, 0xC0);
 1001                         outb(0x0A, 0x00);
 1002                         break;
 1003                 default:
 1004                         if(ctlr->bus == 24)
 1005                                 goto buggery;
 1006                         break;
 1007                 }
 1008         
 1009                 switch(data[1]){                /* Interrupt Channel */
 1010                 case 0x40:
 1011                         ctlr->irq = 15;
 1012                         break;
 1013                 case 0x20:
 1014                         ctlr->irq = 14;
 1015                         break;
 1016                 case 0x08:
 1017                         ctlr->irq = 12;
 1018                         break;
 1019                 case 0x04:
 1020                         ctlr->irq = 11;
 1021                         break;
 1022                 case 0x02:
 1023                         ctlr->irq = 10;
 1024                         break;
 1025                 case 0x01:
 1026                         ctlr->irq = 9;
 1027                         break;
 1028                 default:
 1029                         goto buggery;
 1030                 }
 1031         }
 1032 
 1033         if((sdev = malloc(sizeof(SDev))) == nil)
 1034                 goto buggery;
 1035         sdev->ifc = &sdmylexifc;
 1036         sdev->ctlr = ctlr;
 1037         sdev->idno = '';
 1038         ctlr->sdev = sdev;
 1039         if(!ctlr->wide)
 1040                 sdev->nunit = 8;
 1041         else
 1042                 sdev->nunit = 16;
 1043 
 1044         return sdev;
 1045 }
 1046 
 1047 static int mylexport[8] = {
 1048         0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0x000, 0x000,
 1049 };
 1050 
 1051 static SDev*
 1052 mylexpnp(void)
 1053 {
 1054         Pcidev *p;
 1055         Ctlr *ctlr;
 1056         ISAConf isa;
 1057         int cfg, ctlrno, i, x;
 1058         SDev *sdev, *head, *tail;
 1059 
 1060         p = nil;
 1061         head = tail = nil;
 1062         while(p = pcimatch(p, 0x104B, 0)){
 1063                 if((sdev = mylexprobe(p->mem[0].bar & ~0x01, p->intl)) == nil)
 1064                         continue;
 1065 
 1066                 ctlr = sdev->ctlr;
 1067                 ctlr->pcidev = p;
 1068 
 1069                 if(head != nil)
 1070                         tail->next = sdev;
 1071                 else
 1072                         head = sdev;
 1073                 tail = sdev;
 1074         }
 1075 
 1076         if(strncmp(KADDR(0xFFFD9), "EISA", 4) == 0){
 1077                 for(cfg = 0x1000; cfg < MaxEISA*0x1000; cfg += 0x1000){
 1078                         x = 0;
 1079                         for(i = 0; i < 4; i++)
 1080                                 x |= inb(cfg+CfgEISA+i)<<(i*8);
 1081                         if(x != 0x0142B30A && x != 0x0242B30A)
 1082                                 continue;
 1083         
 1084                         x = inb(cfg+0xC8C);
 1085                         if((sdev = mylexprobe(mylexport[x & 0x07], -1)) == nil)
 1086                                 continue;
 1087         
 1088                         if(head != nil)
 1089                                 tail->next = sdev;
 1090                         else
 1091                                 head = sdev;
 1092                         tail = sdev;
 1093                 }
 1094         }
 1095 
 1096         for(ctlrno = 0; ctlrno < 4; ctlrno++){
 1097                 memset(&isa, 0, sizeof(isa));
 1098                 if(!isaconfig("scsi", ctlrno, &isa))
 1099                         continue;
 1100                 if(strcmp(isa.type, "aha1542"))
 1101                         continue;
 1102                 if((sdev = mylexprobe(isa.port, -1)) == nil)
 1103                         continue;
 1104 
 1105                 if(head != nil)
 1106                         tail->next = sdev;
 1107                 else
 1108                         head = sdev;
 1109                 tail = sdev;
 1110         }
 1111 
 1112         return head;
 1113 }
 1114 
 1115 static int
 1116 mylex24enable(Ctlr* ctlr)
 1117 {
 1118         ulong p;
 1119         Ccb24 *ccb, *ccbp;
 1120         uchar cmd[6], *v;
 1121         int len;
 1122 
 1123         len = (sizeof(Mbox24)*NMbox*2)+(sizeof(Ccb24)*NCcb);
 1124         v = xspanalloc(len, 32, 0);
 1125 
 1126         if(!PADDR24(ctlr, sizeof(Ctlr)) || !PADDR24(v, len))
 1127                 return 0;
 1128 
 1129         ctlr->mb = v;
 1130         v += sizeof(Mbox24)*NMbox*2;
 1131 
 1132         ccb = (Ccb24*)v;
 1133         for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
 1134                 ccbp->ccb = ctlr->ccb;
 1135                 ctlr->ccb = (Ccb*)ccbp;
 1136         }
 1137 
 1138         /*
 1139          * Initialise the software controller and
 1140          * set the board scanning the mailboxes.
 1141          */
 1142         ctlr->mbix = NMbox;
 1143 
 1144         cmd[0] = Cinitialise;
 1145         cmd[1] = NMbox;
 1146         p = K2BPA(ctlr->mb, BUSUNKNOWN);
 1147         cmd[2] = p>>16;
 1148         cmd[3] = p>>8;
 1149         cmd[4] = p;
 1150 
 1151         return issue(ctlr, cmd, 5, 0, 0);
 1152 }
 1153 
 1154 static int
 1155 mylex32enable(Ctlr* ctlr)
 1156 {
 1157         ulong p;
 1158         Ccb32 *ccb, *ccbp;
 1159         uchar cmd[6], *v;
 1160 
 1161         v = xspanalloc((sizeof(Mbox32)*NMbox*2)+(sizeof(Ccb32)*NCcb), 32, 0);
 1162 
 1163         ctlr->mb = v;
 1164         v += sizeof(Mbox32)*NMbox*2;
 1165 
 1166         ccb = (Ccb32*)v;
 1167         for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
 1168                 /*
 1169                  * Fill in some stuff that doesn't change.
 1170                  */
 1171                 ccbp->senselen = sizeof(ccbp->sense);
 1172                 p = PADDR(ccbp->sense);
 1173                 ccbp->senseptr[0] = p;
 1174                 ccbp->senseptr[1] = p>>8;
 1175                 ccbp->senseptr[2] = p>>16;
 1176                 ccbp->senseptr[3] = p>>24;
 1177 
 1178                 ccbp->ccb = ctlr->ccb;
 1179                 ctlr->ccb = (Ccb*)ccbp;
 1180         }
 1181 
 1182         /*
 1183          * Attempt wide mode setup.
 1184          */
 1185         if(ctlr->wide){
 1186                 cmd[0] = Cwide;
 1187                 cmd[1] = 1;
 1188                 if(!issue(ctlr, cmd, 2, 0, 0)) {
 1189                         ctlr->wide = 0;
 1190                         print("mylex32enable: port 0x%ux: scsi wide-mode setup "
 1191                                 "failed on wide host adapter", ctlr->port);
 1192                 }
 1193         }
 1194 
 1195         /*
 1196          * Initialise the software controller and
 1197          * set the board scanning the mailboxes.
 1198          */
 1199         ctlr->mbix = NMbox;
 1200 
 1201         cmd[0] = Ciem;
 1202         cmd[1] = NMbox;
 1203         if(ctlr->pcidev)
 1204                 p = K2BPA(ctlr->mb, ctlr->tbdf);
 1205         else
 1206                 p = K2BPA(ctlr->mb, BUSUNKNOWN);
 1207         cmd[2] = p;
 1208         cmd[3] = p>>8;
 1209         cmd[4] = p>>16;
 1210         cmd[5] = p>>24;
 1211 
 1212         return issue(ctlr, cmd, 6, 0, 0);
 1213 }
 1214 
 1215 static int
 1216 mylexenable(SDev* sdev)
 1217 {
 1218         int tbdf;
 1219         Ctlr *ctlr;
 1220         void (*interrupt)(Ureg*, void*);
 1221         char name[32];
 1222 
 1223         ctlr = sdev->ctlr;
 1224         if(ctlr->cache == nil){
 1225                 if((ctlr->cache = malloc(sdev->nunit*sizeof(Ccb*))) == nil)
 1226                         return 0;
 1227         }
 1228 
 1229         tbdf = BUSUNKNOWN;
 1230         if(ctlr->bus == 32){
 1231                 if(ctlr->pcidev){
 1232                         tbdf = ctlr->pcidev->tbdf;
 1233                         pcisetbme(ctlr->pcidev);
 1234                 }
 1235                 if(!mylex32enable(ctlr))
 1236                         return 0;
 1237                 interrupt = mylex32interrupt;
 1238         }
 1239         else if(mylex24enable(ctlr))
 1240                 interrupt = mylex24interrupt;
 1241         else
 1242                 return 0;
 1243 
 1244         snprint(name, sizeof(name), "sd%c (%s)", sdev->idno, sdev->ifc->name);
 1245         intrenable(ctlr->irq, interrupt, ctlr, tbdf, name);
 1246 
 1247         return 1;
 1248 }
 1249 
 1250 SDifc sdmylexifc = {
 1251         "mylex",                        /* name */
 1252 
 1253         mylexpnp,                       /* pnp */
 1254         nil,                            /* legacy */
 1255         mylexenable,                    /* enable */
 1256         nil,                            /* disable */
 1257 
 1258         scsiverify,                     /* verify */
 1259         scsionline,                     /* online */
 1260         mylexrio,                       /* rio */
 1261         nil,                            /* rctl */
 1262         nil,                            /* wctl */
 1263 
 1264         scsibio,                        /* bio */
 1265         nil,                            /* probe */
 1266         nil,                            /* clear */
 1267         nil,                            /* rtopctl */
 1268         nil,                            /* wtopctl */
 1269 };

Cache object: 2597fea79070d98ab52d4f382b48e9b5


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