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/wd7000.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  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
    3  * All rights reserved.
    4  *
    5  * Written by Olof Johansson (offe@ludd.luth.se) 1995.
    6  * Based on code written by Theo de Raadt (deraadt@fsa.ca).
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *     This product includes software developed at Ludd, University of Lule}.
   19  * 4. The name of the author may not be used to endorse or promote products
   20  *    derived from this software without specific prior written permission
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34  /* All bugs are subject to removal without further notice */
   35 
   36 /*
   37  * offe 01/07/95
   38  *
   39  * This version of the driver _still_ doesn't implement scatter/gather for the
   40  * WD7000-FASST2. This is due to the fact that my controller doesn't seem to
   41  * support it. That, and the lack of documentation makes it impossible for
   42  * me to implement it.
   43  * What I've done instead is allocated a local buffer, contiguous buffer big
   44  * enough to handle the requests. I haven't seen any read/write bigger than 64k,
   45  * so I allocate a buffer of 64+16k. The data that needs to be DMA'd to/from
   46  * the controller is copied to/from that buffer before/after the command is
   47  * sent to the card.
   48  */
   49 
   50 #include "wds.h"
   51 #if NWDS > 0
   52 
   53 #include <sys/types.h>
   54 #include <sys/param.h>
   55 #include <sys/systm.h>
   56 #include <sys/errno.h>
   57 #include <sys/ioctl.h>
   58 #include <sys/buf.h>
   59 #include <sys/proc.h>
   60 #include <sys/dkbad.h>
   61 #include <sys/disklabel.h>
   62 
   63 #include <scsi/scsi_all.h>
   64 #include <scsi/scsiconf.h>
   65 
   66 #include <machine/clock.h>
   67 
   68 #include <vm/vm.h>
   69 #include <vm/vm_param.h>
   70 #include <vm/pmap.h>
   71 
   72 #include <i386/isa/isa_device.h>
   73 
   74 static struct scsi_device wds_dev =
   75 {
   76         NULL,
   77         NULL,
   78         NULL,
   79         NULL,
   80         "wds",
   81         0,
   82         { 0, 0 }
   83 };
   84 
   85 /*
   86   XXX   THIS SHOULD BE FIXED!
   87   I haven't got the KERNBASE-version to work, but on my system the kernel
   88   is at virtual address 0xFxxxxxxx, responding to physical address
   89   0x0xxxxxxx.
   90 #define PHYSTOKV(x)     ((x) + KERNBASE)
   91 */
   92 #define PHYSTOKV(x)     ((x) | 0xf0000000)
   93 #define KVTOPHYS(x)     vtophys(x)
   94 /* 0x10000 (64k) should be enough. But just to be sure... */
   95 #define BUFSIZ          0x12000
   96 
   97 
   98 /* WD7000 registers */
   99 #define WDS_STAT                0       /* read */
  100 #define WDS_IRQSTAT             1       /* read */
  101 
  102 #define WDS_CMD                 0       /* write */
  103 #define WDS_IRQACK              1       /* write */
  104 #define WDS_HCR                 2       /* write */
  105 
  106 /* WDS_STAT (read) defs */
  107 #define WDS_IRQ                 0x80
  108 #define WDS_RDY                 0x40
  109 #define WDS_REJ                 0x20
  110 #define WDS_INIT                0x10
  111 
  112 /* WDS_IRQSTAT (read) defs */
  113 #define WDSI_MASK               0xc0
  114 #define WDSI_ERR                0x00
  115 #define WDSI_MFREE              0x80
  116 #define WDSI_MSVC               0xc0
  117 
  118 /* WDS_CMD (write) defs */
  119 #define WDSC_NOOP               0x00
  120 #define WDSC_INIT               0x01
  121 #define WDSC_DISUNSOL           0x02
  122 #define WDSC_ENAUNSOL           0x03
  123 #define WDSC_IRQMFREE           0x04
  124 #define WDSC_SCSIRESETSOFT      0x05
  125 #define WDSC_SCSIRESETHARD      0x06
  126 #define WDSC_MSTART(m)          (0x80 + (m))
  127 #define WDSC_MMSTART(m)         (0xc0 + (m))
  128 
  129 /* WDS_HCR (write) defs */
  130 #define WDSH_IRQEN              0x08
  131 #define WDSH_DRQEN              0x04
  132 #define WDSH_SCSIRESET          0x02
  133 #define WDSH_ASCRESET           0x01
  134 
  135 struct wds_cmd {
  136   u_char cmd;
  137   u_char targ;
  138   u_char scb[12];       /*u_char scb[12];*/
  139   u_char stat;
  140   u_char venderr;
  141   u_char len[3];
  142   u_char data[3];
  143   u_char next[3];
  144   u_char write;
  145   u_char xx[6];
  146 };
  147 
  148 struct wds_req {
  149   struct wds_cmd cmd;
  150   struct wds_cmd sense;
  151   struct scsi_xfer *sxp;
  152   int busy, polled;
  153   int done, ret, ombn;
  154 };
  155 
  156 #define WDSX_SCSICMD            0x00
  157 #define WDSX_OPEN_RCVBUF        0x80
  158 #define WDSX_RCV_CMD            0x81
  159 #define WDSX_RCV_DATA           0x82
  160 #define WDSX_RCV_DATASTAT       0x83
  161 #define WDSX_SND_DATA           0x84
  162 #define WDSX_SND_DATASTAT       0x85
  163 #define WDSX_SND_CMDSTAT        0x86
  164 #define WDSX_READINIT           0x88
  165 #define WDSX_READSCSIID         0x89
  166 #define WDSX_SETUNSOLIRQMASK    0x8a
  167 #define WDSX_GETUNSOLIRQMASK    0x8b
  168 #define WDSX_GETFIRMREV         0x8c
  169 #define WDSX_EXECDIAG           0x8d
  170 #define WDSX_SETEXECPARM        0x8e
  171 #define WDSX_GETEXECPARM        0x8f
  172 
  173 struct wds_mb {
  174   u_char stat;
  175   u_char addr[3];
  176 };
  177 /* ICMB status value */
  178 #define ICMB_OK                 0x01
  179 #define ICMB_OKERR              0x02
  180 #define ICMB_ETIME              0x04
  181 #define ICMB_ERESET             0x05
  182 #define ICMB_ETARCMD            0x06
  183 #define ICMB_ERESEL             0x80
  184 #define ICMB_ESEL               0x81
  185 #define ICMB_EABORT             0x82
  186 #define ICMB_ESRESET            0x83
  187 #define ICMB_EHRESET            0x84
  188 
  189 struct wds_setup {
  190   u_char cmd;
  191   u_char scsi_id;
  192   u_char buson_t;
  193   u_char busoff_t;
  194   u_char xx;
  195   u_char mbaddr[3];
  196   u_char nomb;
  197   u_char nimb;
  198 };
  199 
  200 #define WDS_NOMB        8
  201 #define WDS_NIMB        8
  202 #define MAXSIMUL        8
  203 
  204 static int wdsunit=0;
  205 
  206 static u_char wds_data[NWDS][BUFSIZ];
  207 static u_char wds_data_in_use[NWDS];
  208 
  209 static struct wds {
  210   int addr;
  211   struct wds_req wdsr[MAXSIMUL];
  212   struct wds_mb ombs[WDS_NOMB], imbs[WDS_NIMB];
  213   struct scsi_link sc_link;
  214 } wds[NWDS];
  215 
  216 static int wdsprobe(struct isa_device *);
  217 static void wds_minphys(struct buf *);
  218 static struct wds_req *wdsr_alloc(int);
  219 static int32_t wds_scsi_cmd(struct scsi_xfer *);
  220 static u_int32_t wds_adapter_info(int);
  221 static int wds_done(int, struct wds_cmd *, u_char);
  222 static int wdsattach(struct isa_device *);
  223 static int wds_init(struct isa_device *);
  224 static int wds_cmd(int, u_char *, int);
  225 static void wds_wait(int, int, int);
  226 
  227 struct isa_driver wdsdriver =
  228 {
  229   wdsprobe,
  230   wdsattach,
  231   "wds"
  232 };
  233 
  234 static struct scsi_adapter wds_switch =
  235 {
  236         wds_scsi_cmd,
  237         wds_minphys,
  238         0,
  239         0,
  240         wds_adapter_info,
  241         "wds",
  242         {0,0}
  243 };
  244 
  245 int
  246 wdsprobe(struct isa_device *dev)
  247 {
  248   if(wdsunit > NWDS)
  249     return 0;
  250 
  251   dev->id_unit = wdsunit;       /* XXX WRONG! */
  252   wds[wdsunit].addr = dev->id_iobase;
  253 
  254   if(wds_init(dev) != 0)
  255     return 0;
  256   wdsunit++;
  257   return 8;
  258 }
  259 
  260 void
  261 wds_minphys(struct buf *bp)
  262 {
  263   if(bp->b_bcount > BUFSIZ)
  264     bp->b_bcount = BUFSIZ;
  265 }
  266 
  267 struct wds_req *
  268 wdsr_alloc(int unit)
  269 {
  270   struct wds_req *r;
  271   int x;
  272   int i;
  273 
  274   r = NULL;
  275   x = splbio();
  276   for(i=0; i<MAXSIMUL; i++)
  277     if(!wds[unit].wdsr[i].busy)
  278     {
  279       r = &wds[unit].wdsr[i];
  280       r->busy = 1;
  281       break;
  282     }
  283   if(!r)
  284   {
  285     splx(x);
  286     return NULL;
  287   }
  288 
  289   r->ombn = -1;
  290   for(i=0; i<WDS_NOMB; i++)
  291     if(!wds[unit].ombs[i].stat)
  292     {
  293       wds[unit].ombs[i].stat = 1;
  294       r->ombn = i;
  295       break;
  296     }
  297   if(r->ombn == -1 )
  298   {
  299     r->busy = 0;
  300     splx(x);
  301     return NULL;
  302   }
  303   splx(x);
  304   return r;
  305 }
  306 
  307 int32_t
  308 wds_scsi_cmd(struct scsi_xfer *sxp)
  309 {
  310   struct wds_req *r;
  311   int unit = sxp->sc_link->adapter_unit;
  312   int base;
  313   u_char c;
  314   int i;
  315 
  316   base = wds[unit].addr;
  317 
  318   if( sxp->flags & SCSI_RESET)
  319   {
  320     printf("reset!\n");
  321     return COMPLETE;
  322   }
  323 
  324   r = wdsr_alloc(unit);
  325   if(r==NULL)
  326   {
  327     printf("no request slot available!\n");
  328     sxp->error = XS_DRIVER_STUFFUP;
  329     return TRY_AGAIN_LATER;
  330   }
  331   r->done = 0;
  332   r->sxp = sxp;
  333 
  334   if(sxp->flags & SCSI_DATA_UIO)
  335   {
  336     printf("UIO!\n");
  337     sxp->error = XS_DRIVER_STUFFUP;
  338     return TRY_AGAIN_LATER;
  339   }
  340 
  341   scsi_uto3b(KVTOPHYS(&r->cmd),wds[unit].ombs[r->ombn].addr);
  342 
  343   bzero(&r->cmd, sizeof r->cmd);
  344   r->cmd.cmd = WDSX_SCSICMD;
  345   r->cmd.targ = (sxp->sc_link->target << 5) | sxp->sc_link->lun;
  346   bcopy(sxp->cmd, &r->cmd.scb, sxp->cmdlen<12 ? sxp->cmdlen : 12);
  347   scsi_uto3b(sxp->datalen, r->cmd.len);
  348 
  349   if(wds_data_in_use[unit])
  350   {
  351     sxp->error = XS_DRIVER_STUFFUP;
  352     return TRY_AGAIN_LATER;
  353   }
  354   else
  355     wds_data_in_use[unit] = 1;
  356 
  357   if(sxp->datalen && !(sxp->flags&SCSI_DATA_IN))
  358     bcopy(sxp->data, wds_data[unit], sxp->datalen);
  359 
  360   scsi_uto3b(sxp->datalen ? KVTOPHYS(wds_data[unit]) : 0, r->cmd.data);
  361 
  362   r->cmd.write = (sxp->flags&SCSI_DATA_IN)? 0x80 : 0x00;
  363 
  364   scsi_uto3b(KVTOPHYS(&r->sense),r->cmd.next);
  365 
  366   bzero(&r->sense, sizeof r->sense);
  367   r->sense.cmd = r->cmd.cmd;
  368   r->sense.targ = r->cmd.targ;
  369   r->sense.scb[0] = REQUEST_SENSE;
  370   scsi_uto3b(KVTOPHYS(&sxp->sense),r->sense.data);
  371   scsi_uto3b(sizeof(sxp->sense), r->sense.len);
  372   r->sense.write = 0x80;
  373 
  374   if(sxp->flags & SCSI_NOMASK)
  375   {
  376     outb(base+WDS_HCR, WDSH_DRQEN);
  377     r->polled = 1;
  378   } else
  379   {
  380     outb(base+WDS_HCR, WDSH_IRQEN|WDSH_DRQEN);
  381     r->polled = 0;
  382   }
  383 
  384   c = WDSC_MSTART(r->ombn);
  385 
  386   if( wds_cmd(base, &c, sizeof c) != 0)
  387   {
  388     printf("wds%d: unable to start outgoing mbox\n", unit);
  389     r->busy = 0;
  390     wds[unit].ombs[r->ombn].stat = 0;
  391 
  392     return TRY_AGAIN_LATER;
  393   }
  394 
  395   if(sxp->flags & SCSI_NOMASK)
  396   {
  397   repoll:
  398 
  399     i = 0;
  400     while(!(inb(base+WDS_STAT) & WDS_IRQ))
  401     {
  402 
  403       DELAY(20000);
  404       if(++i == 20)
  405       {
  406         outb(base + WDS_IRQACK, 0);
  407         /*r->busy = 0;*/
  408         sxp->error = XS_TIMEOUT;
  409         return HAD_ERROR;
  410       }
  411     }
  412     wdsintr(unit);
  413     if(r->done)
  414     {
  415       r->sxp->flags |= ITSDONE;
  416       r->busy = 0;
  417       return r->ret;
  418     }
  419     goto repoll;
  420   }
  421 
  422   return SUCCESSFULLY_QUEUED;
  423 }
  424 
  425 u_int32_t
  426 wds_adapter_info(int unit)
  427 {
  428   return 1;
  429 }
  430 
  431 void
  432 wdsintr(int unit)
  433 {
  434   struct wds_cmd *pc, *vc;
  435   struct wds_mb *in;
  436   u_char stat;
  437   u_char c;
  438 
  439   if(!inb(wds[unit].addr+WDS_STAT) & WDS_IRQ)
  440   {
  441     outb(wds[unit].addr + WDS_IRQACK, 0);
  442     return;
  443   }
  444 
  445   c = inb(wds[unit].addr + WDS_IRQSTAT);
  446   if( (c&WDSI_MASK) == WDSI_MSVC)
  447   {
  448     c = c & ~WDSI_MASK;
  449     in = &wds[unit].imbs[c];
  450 
  451     pc = (struct wds_cmd *)scsi_3btou(in->addr);
  452     vc = (struct wds_cmd *)PHYSTOKV((long)pc);
  453     stat = in->stat;
  454 
  455     wds_done(unit, vc, stat);
  456     in->stat = 0;
  457 
  458     outb(wds[unit].addr + WDS_IRQACK, 0);
  459   }
  460 }
  461 
  462 int
  463 wds_done(int unit, struct wds_cmd *c, u_char stat)
  464 {
  465   struct wds_req *r;
  466   int i;
  467 
  468   r = (struct wds_req *)NULL;
  469 
  470   for(i=0; i<MAXSIMUL; i++)
  471     if( c == &wds[unit].wdsr[i].cmd && !wds[unit].wdsr[i].done)
  472     {
  473       r = &wds[unit].wdsr[i];
  474       break;
  475     }
  476   if(r == (struct wds_req *)NULL)
  477   {
  478     /* failed to find request! */
  479     return 1;
  480   }
  481 
  482   r->done = 1;
  483   wds[unit].ombs[r->ombn].stat = 0;
  484   r->ret = HAD_ERROR;
  485   switch(stat)
  486   {
  487   case ICMB_OK:
  488     r->ret = COMPLETE;
  489     if(r->sxp)
  490       r->sxp->resid = 0;
  491     break;
  492   case ICMB_OKERR:
  493     if(!(r->sxp->flags & SCSI_ERR_OK) && c->stat)
  494     {
  495       r->sxp->sense.error_code = c->venderr;
  496       r->sxp->error=XS_SENSE;
  497     }
  498     else
  499       r->sxp->error=XS_NOERROR;
  500     r->ret = COMPLETE;
  501     break;
  502   case ICMB_ETIME:
  503     r->sxp->error = XS_TIMEOUT;
  504     r->ret = HAD_ERROR;
  505     break;
  506   case ICMB_ERESET:
  507   case ICMB_ETARCMD:
  508   case ICMB_ERESEL:
  509   case ICMB_ESEL:
  510   case ICMB_EABORT:
  511   case ICMB_ESRESET:
  512   case ICMB_EHRESET:
  513     r->sxp->error = XS_DRIVER_STUFFUP;
  514     r->ret = HAD_ERROR;
  515     break;
  516   }
  517 
  518   if(r->sxp)
  519     if(r->sxp->datalen && (r->sxp->flags&SCSI_DATA_IN))
  520       bcopy(wds_data[unit],r->sxp->data,r->sxp->datalen);
  521 
  522   wds_data_in_use[unit] = 0;
  523 
  524   if(!r->polled)
  525   {
  526     r->sxp->flags |= ITSDONE;
  527     scsi_done(r->sxp);
  528   }
  529 
  530   r->busy = 0;
  531 
  532   return 0;
  533 }
  534 
  535 static int
  536 wds_getvers(int unit)
  537 {
  538   struct wds_req *r;
  539   int base;
  540   u_char c;
  541   int i;
  542 
  543   base = wds[unit].addr;
  544 
  545   r = wdsr_alloc(unit);
  546   if(!r)
  547   {
  548     printf("wds%d: no request slot available!\n", unit);
  549     return -1;
  550   }
  551 
  552   r->done = 0;
  553   r->sxp = NULL;
  554 
  555   scsi_uto3b(KVTOPHYS(&r->cmd), wds[unit].ombs[r->ombn].addr);
  556 
  557   bzero(&r->cmd, sizeof r->cmd);
  558   r->cmd.cmd = WDSX_GETFIRMREV;
  559 
  560   outb(base+WDS_HCR, WDSH_DRQEN);
  561   r->polled = 1;
  562 
  563   c = WDSC_MSTART(r->ombn);
  564   if(wds_cmd(base, (u_char *)&c, sizeof c))
  565   {
  566     printf("wds%d: version request failed\n", unit);
  567     r->busy = 0;
  568     wds[unit].ombs[r->ombn].stat = 0;
  569     return -1;
  570   }
  571 
  572   while(1)
  573   {
  574     i = 0;
  575     while( (inb(base+WDS_STAT) & WDS_IRQ) == 0)
  576     {
  577       DELAY(9000);
  578       if(++i == 20)
  579         return -1;
  580     }
  581     wdsintr(unit);
  582     if(r->done)
  583     {
  584       printf("wds%d: firmware version %d.%02d\n", unit,
  585              r->cmd.targ, r->cmd.scb[0]);
  586       r->busy = 0;
  587       return 0;
  588     }
  589   }
  590 }
  591 
  592 int
  593 wdsattach(struct isa_device *dev)
  594 {
  595   int masunit;
  596   static u_long versprobe=0;    /* max 32 controllers */
  597   int unit = dev->id_unit;
  598   struct scsibus_data *scbus;
  599 
  600   masunit = dev->id_unit;
  601 
  602   if( !(versprobe & (1<<masunit)))
  603   {
  604     versprobe |= (1<<masunit);
  605     if(wds_getvers(masunit)==-1)
  606       printf("wds%d: getvers failed\n", masunit);
  607   }
  608 
  609   printf("wds%d: using %d bytes for dma buffer\n",unit,BUFSIZ);
  610 
  611   wds[unit].sc_link.adapter_unit = unit;
  612   wds[unit].sc_link.adapter_targ = 7;
  613   wds[unit].sc_link.adapter = &wds_switch;
  614   wds[unit].sc_link.device = &wds_dev;
  615   wds[unit].sc_link.flags = SDEV_BOUNCE;
  616 
  617   /*
  618    * Prepare the scsibus_data area for the upperlevel
  619    * scsi code.
  620    */
  621   scbus = scsi_alloc_bus();
  622   if(!scbus)
  623     return 0;
  624   scbus->adapter_link = &wds[unit].sc_link;
  625 
  626   scsi_attachdevs(scbus);
  627 
  628   return 1;
  629 }
  630 
  631 int
  632 wds_init(struct isa_device *dev)
  633 {
  634   struct wds_setup init;
  635   int base;
  636   int unit, i;
  637   struct wds_cmd wc;
  638 
  639   unit = dev->id_unit;
  640   base = wds[unit].addr;
  641 
  642   /*
  643    * Sending a command causes the CMDRDY bit to clear.
  644    */
  645 
  646   outb(base+WDS_CMD, WDSC_NOOP);
  647   if( inb(base+WDS_STAT) & WDS_RDY)
  648     return 1;
  649 
  650   /*
  651    * the controller exists. reset and init.
  652    */
  653   outb(base+WDS_HCR, WDSH_ASCRESET|WDSH_SCSIRESET);
  654   DELAY(30);
  655   outb(base+WDS_HCR, 0);
  656 
  657   outb(base+WDS_HCR, WDSH_DRQEN);
  658 
  659   isa_dmacascade(dev->id_drq);
  660 
  661   if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY)
  662   {
  663     for(i=0; i<10; i++)
  664     {
  665       if( (inb(base+WDS_STAT) & (WDS_RDY)) == WDS_RDY)
  666         break;
  667       DELAY(40000);
  668     }
  669     if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY) /* probe timeout */
  670       return 1;
  671   }
  672 
  673   bzero(&init, sizeof init);
  674   init.cmd = WDSC_INIT;
  675   init.scsi_id = 7;
  676   init.buson_t = 24;
  677   init.busoff_t = 48;
  678   scsi_uto3b(KVTOPHYS(wds[unit].ombs), init.mbaddr);
  679   init.xx = 0;
  680   init.nomb = WDS_NOMB;
  681   init.nimb = WDS_NIMB;
  682 
  683   wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY);
  684   if( wds_cmd(base, (u_char *)&init, sizeof init) != 0)
  685   {
  686     printf("wds%d: wds_cmd failed\n", unit);
  687     return 1;
  688   }
  689 
  690   wds_wait(base+WDS_STAT, WDS_INIT, WDS_INIT);
  691 
  692   wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY);
  693 
  694   bzero(&wc,sizeof wc);
  695   wc.cmd = WDSC_DISUNSOL;
  696   if( wds_cmd(base, (char *)&wc, sizeof wc) != 0)
  697   {
  698     printf("wds%d: wds_cmd failed\n", unit);
  699     return 1;
  700   }
  701 
  702   return 0;
  703 }
  704 
  705 int
  706 wds_cmd(int base, u_char *p, int l)
  707 {
  708   int s=splbio();
  709 
  710   while(l--)
  711   {
  712     do
  713     {
  714       outb(base+WDS_CMD,*p);
  715       wds_wait(base+WDS_STAT,WDS_RDY,WDS_RDY);
  716     } while (inb(base+WDS_STAT) & WDS_REJ);
  717     p++;
  718   }
  719 
  720   wds_wait(base+WDS_STAT,WDS_RDY,WDS_RDY);
  721 
  722   splx(s);
  723 
  724   return 0;
  725 }
  726 
  727 void
  728 wds_wait(int reg, int mask, int val)
  729 {
  730   while((inb(reg) & mask) != val);
  731 }
  732 
  733 #endif

Cache object: 84d9e62ba94fff98db0701c7be3b3cce


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