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/sqtzdc/zd.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  * Mach Operating System
    3  * Copyright (c) 1992-1 Carnegie Mellon University
    4  * Copyright (c) 1991 Sequent Computer Systems
    5  * All Rights Reserved.
    6  * 
    7  * Permission to use, copy, modify and distribute this software and its
    8  * documentation is hereby granted, provided that both the copyright
    9  * notice and this permission notice appear in all copies of the
   10  * software, derivative works or modified versions, and any portions
   11  * thereof, and that both notices appear in supporting documentation.
   12  * 
   13  * CARNEGIE MELLON AND SEQUENT COMPUTER SYSTEMS ALLOW FREE USE OF
   14  * THIS SOFTWARE IN ITS "AS IS" CONDITION.  CARNEGIE MELLON AND
   15  * SEQUENT COMPUTER SYSTEMS DISCLAIM ANY LIABILITY OF ANY KIND FOR
   16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  * 
   18  * Carnegie Mellon requests users of this software to return to
   19  * 
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  * 
   25  * any improvements or extensions that they make and grant Carnegie Mellon 
   26  * the rights to redistribute these changes.
   27  */
   28 
   29 /*
   30  * HISTORY
   31  * $Log:        zd.c,v $
   32  * Revision 2.7  93/03/11  14:05:45  danner
   33  *      u_long -> u_int
   34  *      [93/03/10            danner]
   35  * 
   36  * Revision 2.6  92/08/03  18:16:35  jfriedl
   37  *      Add "zd_devinfo" routine.
   38  *      [92/08/03  14:36:10  jms]
   39  * 
   40  * Revision 2.5  92/02/24  09:58:46  elf
   41  *      Removed gratuitous reference to undefined variable in zdgetstat.
   42  *      [92/02/24            elf]
   43  * 
   44  * Revision 2.4  92/02/23  22:45:21  elf
   45  *      Added zdgetstat().
   46  *      [92/02/22  19:52:59  af]
   47  * 
   48  * Revision 2.3  91/07/31  18:08:03  dbg
   49  *      Changed copyright.
   50  *      [91/07/31            dbg]
   51  * 
   52  * Revision 2.2  91/05/08  13:07:55  dbg
   53  *      Changes for new kmem_alloc interface.
   54  * 
   55  *      Adapted for pure Mach kernel.
   56  *      [91/03/22            dbg]
   57  * 
   58  */
   59 
   60 /*
   61  * zd.c
   62  *
   63  * ZDC SMD Disk Driver
   64  */
   65 
   66 #ifdef  MACH_KERNEL
   67 #include <vm/vm_kern.h>
   68 
   69 #include <sys/types.h>
   70 #include <sys/time.h>
   71 
   72 #include <device/buf.h>
   73 #include <device/errno.h>
   74 #include <device/param.h>
   75 
   76 #include <sqt/macros.h>
   77 #include <sqt/vm_defs.h>
   78 #include <sqt/slicreg.h>
   79 #include <sqt/clkarb.h>
   80 
   81 #include <sqt/mutex.h>
   82 #include <sqt/intctl.h>
   83 
   84 #include <sqtzdc/zdc.h>
   85 #include <sqtzdc/zdbad.h>
   86 #include <sqtzdc/ioconf.h>
   87 
   88 #define PZERO           (0)             /* unused */
   89 #define FWRITE          D_WRITE
   90 #define EACCES          D_ALREADY_OPEN
   91 
   92 #else   MACH_KERNEL
   93 #include "sys/param.h"
   94 #include "sys/file.h"
   95 #include "sys/user.h"
   96 #include "sys/buf.h"
   97 #include "sys/systm.h"
   98 #include "sys/uio.h"
   99 #include "sys/ioctl.h"
  100 #include "sys/proc.h"
  101 #include "sys/kernel.h"
  102 #include "sys/dk.h"
  103 #include "sys/vm.h"
  104 
  105 #include "sqt/slicreg.h"
  106 #include "sqt/clkarb.h"
  107 
  108 #include "sqt/mutex.h"
  109 #include "sqt/intctl.h"
  110 #include "sqt/pte.h"
  111 #include "sqt/mftpr.h"
  112 #include "sqt/plocal.h"
  113 
  114 #include "sqtzdc/zdc.h"
  115 #include "sqtzdc/zdbad.h"
  116 #include "sqtzdc/ioconf.h"
  117 #endif  MACH_KERNEL
  118 
  119 #define ZDUNIT(dev)     (minor(dev) >> 0x3)
  120 #define ZDPART(dev)     (minor(dev) & 0x7)
  121 #define PARTCHR(dev)    ('a' + ZDPART(dev))
  122 #define NUDGE_ZDC(ctlp, cbp, s) { \
  123         (s) = splhi(); \
  124         mIntr((ctlp)->zdc_slicaddr, CBBIN, (u_char)((cbp) - (ctlp)->zdc_cbp)); \
  125         splx((s)); \
  126         }
  127 #define PZOPEN          (PZERO - 1)             /* not signallable */
  128 #define b_diskaddr      b_resid
  129 #define b_psect         b_error
  130 #define B_IOCTL         B_MD1
  131 /*
  132  * PTECLOFF returns offset in cluster of memory pointed at by pte.
  133  */
  134 #define PTECLOFF(pte)   ((unsigned)((*(int*)(&(pte))) & ((~(NBPG-1))&CLOFSET)))
  135 
  136 extern  struct  zdc_ctlr *zdctrlr;      /* zdctrlr array */
  137 extern  struct  zd_unit  *zdunit;       /* zdunit array */
  138 extern  struct  zdsize   *zdparts[];    /* Partition tables */
  139 extern  int     zdntypes;               /* known drive types */
  140 extern  int     zdc_iovpercb;           /* no of iovecs per cb */
  141 extern  int     zdc_AB_throttle;        /* Channel A&B DMA throttle */
  142 extern  short   zdcretry;               /* retry count on errors */
  143 extern  u_char  zdctrl;                 /* additional icb_ctrl bits */
  144 extern  u_char  base_cb_intr;           /* base interrupt for zdc driver */
  145 extern  u_char  base_err_intr;          /* base controller interrupt */
  146 extern  simple_lock_data_t
  147                 zdcprlock;              /* coordinate error printfs */
  148 
  149 #define DEBUG 1
  150 
  151 #ifdef  DEBUG
  152 int     zddebug = 0;
  153 #endif  DEBUG
  154 
  155 caddr_t zd_compcodes[] = {
  156         "Command in progress",
  157         "Successful completion",
  158         "Write protect fault",
  159         "Drive Fault",
  160         "Seek error",
  161         "Seek timeout",
  162         "Channel timeout",
  163         "DMA timeout",
  164         "Header ECC error",
  165         "Soft ECC error",
  166         "Correctable ECC error",
  167         "Uncorrectable ECC error",
  168         "Sector not found",
  169         "Bad data sector",
  170         "Sector overrun",
  171         "No data synch",
  172         "Fifo data lost",
  173         "Illegal cb_cmd",
  174         "Illegal cb_mod",
  175         "Illegal disk address",
  176         "cb_addr not 16-byte aligned",
  177         "Illegal cb_count",
  178         "cb_iovec not 32-byte aligned",
  179         "Non-zero cb_iovec and page size invalid",
  180         "Illegal icb_pagesize",
  181         "icb_dumpaddr not 16-byte aligned",
  182         "Bad drive",
  183         "In-use CB reused",
  184         "Access error during DMA",
  185         "Channel not configured",
  186         "Channel was reset",
  187         "Unexpected status from DDC",
  188         "Unknown Completion code"
  189 };
  190 int     zdncompcodes = sizeof(zd_compcodes) / sizeof(zd_compcodes[0]);
  191 
  192 #ifdef  MACH
  193 static struct buf       zdbuf;          /* needed for physio */
  194 #endif
  195 
  196 /*
  197  * zdopen
  198  *
  199  * Return:
  200  *      0 - success.
  201  *      EACCES - open for write but drive write-protected.
  202  *      ENXIO - all other failures.
  203  */
  204 zdopen(dev, mode)
  205         dev_t   dev;
  206         int     mode;
  207 {
  208         register struct zd_unit *up;
  209         register struct zdcdd   *dd;            /* channel configuration */
  210         register struct zdc_dev *zdv;           /* config data */
  211         int     retval;                         /* return value */
  212         u_char  oldcfg;                         /* previous cfg state */
  213         struct  zdcdd   *zdget_chancfg();
  214 
  215         up = &zdunit[ZDUNIT(dev)];
  216 
  217 #ifdef  DEBUG
  218         if (zddebug)
  219                 printf("O");
  220 #endif  DEBUG
  221 
  222         /*
  223          * Fail open if the unit is bad or if the unit was not bound
  224          * to a drive during configuration.
  225          */
  226         if (ZDUNIT(dev) >= zdc_conf->zc_nent ||
  227             up->zu_state == ZU_NOTFOUND || up->zu_state == ZU_BAD)
  228                 return (ENXIO);
  229 
  230         /*
  231          * Now get serious
  232          */
  233         p_sema(&up->zu_ocsema, PZOPEN);
  234 
  235         (void)p_lock(&up->zu_lock, SPLZD);
  236         /*
  237          * check to see if still good drive.
  238          */
  239         if (up->zu_state == ZU_BAD) {
  240                 v_lock(&up->zu_lock, SPL0);
  241                 v_sema(&up->zu_ocsema);
  242                 return (ENXIO);
  243         }
  244         up->zu_nopen++;
  245         retval = 0;
  246         if (up->zu_nopen > 1) {
  247                 /*
  248                  * Already opened at least once.
  249                  */
  250                 if (up->zu_state == ZU_NO_RW) {
  251                         /*
  252                          * Only one formatter at a time please...
  253                          */
  254                         retval = EACCES;
  255                 } else if (zdparts[up->zu_drive_type][ZDPART(dev)].p_length == 0) {
  256                         /*
  257                          * Good drive but fail open if partition table is
  258                          * invalid.
  259                          */
  260                         retval = ENXIO;
  261                 } else if ((mode & FWRITE) && (up->zu_cfg & ZD_READONLY)) {
  262                         /*
  263                          * Fail open for write on a write-protected drive.
  264                          */
  265                         retval = EACCES;
  266                 }
  267                 v_lock(&up->zu_lock, SPL0);
  268                 if (retval != 0)
  269                         --up->zu_nopen;
  270                 v_sema(&up->zu_ocsema);
  271                 return (retval);
  272         }
  273 
  274         /*
  275          * First open!
  276          * Drop lock, we don't need as no other I/O can be in progress
  277          * on this drive.
  278          */
  279         v_lock(&up->zu_lock, SPL0);
  280 
  281         up->zu_state = ZU_GOOD;         /* assume good */
  282         oldcfg = up->zu_cfg;
  283         if ((retval = zdprobe_drive(dev, up)) != 0) {
  284                 /*
  285                  * Error whilst attempting probe!
  286                  */
  287                 goto out;
  288         }
  289         /*
  290          * Error if drive still not there or not online.
  291          */
  292         if (up->zu_cfg == ZD_NOTFOUND ||                /* Not there */
  293             (up->zu_cfg & ZD_ONLINE) != ZD_ONLINE) {    /* Offline */
  294                 if ((oldcfg & ZD_ONLINE) == ZD_ONLINE) {
  295                         /*
  296                          * It had been online.
  297                          */
  298                         disk_offline();
  299                 }
  300                 retval = ENXIO;
  301                 goto out;
  302         }
  303 
  304         if (oldcfg == ZD_NOTFOUND || ((oldcfg & ZD_ONLINE) != ZD_ONLINE)) {
  305                 /*
  306                  * It had been offline.
  307                  */
  308                 disk_online();
  309         }
  310 
  311         if ((mode & FWRITE) && (up->zu_cfg & ZD_READONLY)) {
  312                 /*
  313                  * Fail open for write on a write-protected drive.
  314                  */
  315                 retval = EACCES;
  316                 goto out;
  317         }
  318 
  319         dd = zdget_chancfg(dev, up);
  320         if (dd == NULL) {
  321                 retval = EIO;
  322                 goto out;
  323         }
  324         zdv = &zdc_conf->zc_dev[ZDUNIT(dev)];
  325         /*
  326          * Does channel configuration match the drive configuration.
  327          * If bound drive_type and mismatch, then drive is marked to
  328          * disallow normal read/write operations.
  329          */
  330         if (dd->zdd_sectors == 0 ||
  331             (zdv->zdv_drive_type != ANY &&
  332              zdv->zdv_drive_type != dd->zdd_drive_type)) {
  333                 up->zu_state = ZU_NO_RW;
  334                 printf("zd%d: drive type mismatch - check configuration.\n",
  335                         up - zdunit);
  336                 goto out;
  337         }
  338         /*
  339          * If the drive is not formatted or is formatted differently than
  340          * the other drives on the channel, then cannot read the bad block
  341          * list. In this case, only format operations via ioctl will be
  342          * allowed. Read and write operations will return error.
  343          */
  344         if ((up->zu_cfg & (ZD_FORMATTED|ZD_MATCH)) != (ZD_FORMATTED|ZD_MATCH)) {
  345                 up->zu_state = ZU_NO_RW;
  346                 printf("zd%d: warning: %s.\n", up - zdunit,
  347                         ((up->zu_cfg & ZD_FORMATTED) != ZD_FORMATTED)
  348                                 ? "drive unformatted"
  349                                 : "drive/channel mismatch");
  350                 goto out;
  351         }
  352         if (dd->zdd_drive_type >= zdntypes) {
  353                 /*
  354                  * Unknown drive type. Check zdparts[] in binary conf file.
  355                  */
  356                 up->zu_state = ZU_NO_RW;        /* allow reformat */
  357                 printf("zd%d: unknown drive type - check configuration.\n",
  358                         up - zdunit);
  359                 goto out;
  360         }
  361 
  362         up->zu_drive_type = dd->zdd_drive_type;
  363         if (zdparts[up->zu_drive_type][ZDPART(dev)].p_length == 0) {
  364                 /*
  365                  * Good drive but fail open if partition table is invalid.
  366                  */
  367                 retval = ENXIO;
  368                 goto out;
  369         }
  370 
  371         /*
  372          * Online and formatted drive - get bad block list.
  373          * If cannot correctly read bad block list - only allow ioctl
  374          * operations.
  375          */
  376         if (zdgetbad(dev, up) < 0) {
  377                 printf("zd%d: Cannot read bad block list.\n", up - zdunit);
  378                 up->zu_state = ZU_NO_RW;
  379         }
  380 
  381 out:
  382         if (retval != 0)
  383                 --up->zu_nopen;
  384         v_sema(&up->zu_ocsema);
  385         return (retval);
  386 }
  387 
  388 /*
  389  * zdclose
  390  *      Close the device.
  391  *      If last close, free memory holding bad block list.
  392  */
  393 /*ARGSUSED*/
  394 zdclose(dev, flag)
  395         dev_t dev;
  396         int flag;
  397 {
  398         register struct zd_unit *up;
  399         register int size;
  400 
  401         up = &zdunit[ZDUNIT(dev)];
  402 #ifdef  DEBUG
  403         if (zddebug)
  404                 printf("C");
  405 #endif  DEBUG
  406         p_sema(&up->zu_ocsema, PZOPEN);
  407         if (--up->zu_nopen == 0) {
  408                 /*
  409                  * Last close!
  410                  * Free memory allocated to hold bad block list.
  411                  * If drive has removable media, the next open may
  412                  * have different bad block list.
  413                  */
  414                 if (up->zu_zdbad != NULL) {
  415                         size = (up->zu_zdbad->bz_nsnf * sizeof(struct bz_bad))
  416                                 + sizeof(struct zdbad) - sizeof(struct bz_bad);
  417                         size = roundup(size, DEV_BSIZE);
  418                         kmem_free(kernel_map, (vm_offset_t)up->zu_zdbad, size);
  419                         up->zu_zdbad = NULL;
  420                 }
  421         }
  422         v_sema(&up->zu_ocsema);
  423 }
  424 
  425 /*
  426  * zdprobe_drive
  427  *      Probe for the status of a particular drive then update
  428  *      appropriate fields in controller and unit structures.
  429  */
  430 int
  431 zdprobe_drive(dev, up)
  432         dev_t   dev;
  433         register struct zd_unit *up;
  434 {
  435         register struct buf *bp;        /* ioctl buffer */
  436         register struct cb  *cbp;       /* cb argument */
  437         int     error;
  438 
  439         bp  = &up->zu_ioctl;
  440         cbp = &up->zu_ioctlcb;
  441 #ifndef MACH
  442         bufalloc(bp);                   /* will always get since 1st open */
  443 #endif  MACH
  444         bp->b_flags = B_IOCTL;
  445         bp->b_bcount = 0;               /* data in CB */
  446         bp->b_un.b_addr = NULL;
  447         bp->b_dev = dev;
  448         bp->b_blkno = 0;
  449         bp->b_error = 0;
  450 #ifndef MACH_KERNEL
  451         bp->b_proc = u.u_procp;
  452 #endif  MACH_KERNEL
  453 #ifndef MACH
  454         bp->b_iotype = B_FILIO;
  455         BIODONE(bp) = 0;
  456 #endif  MACH
  457         /* Fill out CB */
  458         cbp->cb_cmd = ZDC_PROBEDRIVE;
  459         /*
  460          * Insert at head of list and zdstart!
  461          */
  462         (void)p_lock(&up->zu_lock, SPLZD);
  463         bp->av_forw = NULL;
  464         up->zu_bhead.av_forw = bp;
  465         zdstart(up);
  466         v_lock(&up->zu_lock, SPL0);
  467         biowait(bp);
  468 #ifdef  MACH_KERNEL
  469         error = bp->b_error;
  470 #else   MACH_KERNEL
  471         error = geterror(bp);
  472 #endif  MACH_KERNEL
  473         if (error) {
  474 #ifndef MACH
  475                 buffree(bp);
  476 #endif  MACH
  477                 return (error);
  478         }
  479         /*
  480          * extract drive cfg data.
  481          */
  482         up->zu_cfg = ((struct probe_cb *)cbp)->pcb_drivecfg[up->zu_drive];
  483         zdctrlr[up->zu_ctrlr].zdc_drivecfg[up->zu_drive] = up->zu_cfg;
  484 #ifndef MACH
  485         buffree(bp);
  486 #endif  MACH
  487         return (0);
  488 }
  489 
  490 /*
  491  * zdget_chancfg
  492  *      Get the channel configuration for the channel on which this
  493  *      drive resides. Fills in channel configuration in controller structure.
  494  */
  495 struct zdcdd *
  496 zdget_chancfg(dev, up)
  497         dev_t   dev;
  498         register struct zd_unit *up;
  499 {
  500         register struct buf     *bp;    /* ioctl buffer */
  501         register struct cb      *cbp;   /* cb argument */
  502         struct zdcdd    *dd;            /* channel configuration data */
  503         int     chan;                   /* Channel A (0) or channel B (1) */
  504 
  505         bp  = &up->zu_ioctl;
  506         cbp = &up->zu_ioctlcb;
  507 #ifndef MACH
  508         bufalloc(bp);                   /* will always get since 1st open */
  509 #endif  MACH
  510         if (kmem_alloc(kernel_map,
  511                        (vm_offset_t *)&bp->b_un.b_addr,
  512                        sizeof(struct zdcdd)) != KERN_SUCCESS)
  513             panic("zdget_chancfg");
  514         bzero(bp->b_un.b_addr, sizeof(struct zdcdd));
  515         bp->b_flags = B_READ | B_IOCTL;
  516         bp->b_bcount = sizeof(struct zdcdd);
  517         bp->b_dev = dev;
  518         bp->b_blkno = 0;
  519         bp->b_error = 0;
  520 #ifndef MACH_KERNEL
  521         bp->b_proc = u.u_procp;
  522 #endif  MACH_KERNEL
  523 #ifndef MACH
  524         bp->b_iotype = B_FILIO;
  525         BIODONE(bp) = 0;
  526 #endif  MACH
  527         /* Fill out CB */
  528         cbp->cb_cmd = ZDC_GET_CHANCFG;
  529         cbp->cb_addr = KVTOPHYS(bp->b_un.b_addr, u_int);
  530         cbp->cb_count = sizeof(struct zdcdd);
  531         /*
  532          * Insert at head of list and zdstart!
  533          */
  534         (void)p_lock(&up->zu_lock, SPLZD);
  535         bp->av_forw = NULL;
  536         up->zu_bhead.av_forw = bp;
  537         zdstart(up);
  538         v_lock(&up->zu_lock, SPL0);
  539         biowait(bp);
  540         if (bp->b_flags & B_ERROR) {
  541                 kmem_free(kernel_map, bp->b_un.b_addr, sizeof(struct zdcdd));
  542 #ifndef MACH
  543                 buffree(bp);
  544 #endif  MACH
  545                 return (NULL);
  546         }
  547         /*
  548          * Extract Channel configuration data.
  549          */
  550         chan = up->zu_drive & 1;
  551         dd = (chan) ? &zdctrlr[up->zu_ctrlr].zdc_chanB
  552                     : &zdctrlr[up->zu_ctrlr].zdc_chanA;
  553         bcopy(bp->b_un.b_addr, (caddr_t)dd, sizeof(struct zdcdd));
  554         kmem_free(kernel_map, bp->b_un.b_addr, sizeof(struct zdcdd));
  555 #ifndef MACH
  556         buffree(bp);
  557 #endif  MACH
  558         /*
  559          * On the first get of the channel configuration set the
  560          * dma throttle for the channel. Make sure that the configuration
  561          * is valid.
  562          */
  563         if (dd->zdd_sectors != 0 &&
  564             (zdctrlr[up->zu_ctrlr].zdc_dma_throttle & (1 << chan)) == 0)
  565                 set_dma_throttle(&zdctrlr[up->zu_ctrlr], dd, chan);
  566         return (dd);
  567 }
  568 
  569 /*
  570  * set_dma_throttle
  571  *      If 1st open on channel, set the dma throttle
  572  */
  573 /*ARGSUSED*/
  574 set_dma_throttle(ctlrp, dd, chan)
  575         register struct zdc_ctlr *ctlrp;        /* controller */
  576         struct zdcdd    *dd;                    /* channel configuration data */
  577         int     chan;                           /* channel A (0) or B (1) */
  578 {
  579         register int    throttle;       /* throttle count */
  580         spl_t   s_ipl;
  581 
  582         s_ipl = p_lock(&ctlrp->zdc_ctlrlock, SPLHI);
  583         if ((ctlrp->zdc_dma_throttle & (1 << chan)) == 0) {
  584                 throttle = zdc_AB_throttle;
  585                 if (throttle > SLB_TVAL)
  586                         throttle = SLB_TVAL;
  587                 wrslave(ctlrp->zdc_slicaddr, (u_char)(SL_G_CHAN0 + chan),
  588                                         (u_char)(SLB_TH_ENB | throttle));
  589                 ctlrp->zdc_dma_throttle |= (1 << chan);
  590         }
  591         v_lock(&ctlrp->zdc_ctlrlock, s_ipl);
  592 }
  593 
  594 /*
  595  * getchksum
  596  *      Calculate bad block list checksum
  597  */
  598 static
  599 getchksum(lptr, nelem, seed)
  600         register long *lptr;
  601         register int nelem;
  602         long seed;
  603 {
  604         register long sum;
  605 
  606         sum = seed;
  607         while (nelem-- > 0) {
  608                 sum ^= *lptr;
  609                 ++lptr; 
  610         }
  611         return (sum);
  612 }
  613 
  614 /*
  615  * zdgetbad
  616  *      - get the bad block list for this unit.
  617  * Return:
  618  *       0 - success
  619  *      -1 - failure
  620  */
  621 int
  622 zdgetbad(dev, up)
  623         dev_t   dev;
  624         struct zd_unit *up;
  625 {
  626         register struct cb      *cbp;
  627         register struct bz_bad  *fbzp, *tbzp;
  628         register struct buf     *bp;            /* ioctl buffer */
  629         register int    size;
  630         struct  zdbad   *zdp;                   /* bad block list */
  631         struct  zdcdd   *dd;                    /* disk description */
  632         int     zdpsize;
  633         int     block;
  634         caddr_t addr;
  635         static struct   zdbad   null_bbl;       /* fake bad block list */
  636 
  637         /*
  638          * Initialize a fake bad block list in case we receive a
  639          * SNF failure whilst reading the bad block list!
  640          */
  641         null_bbl.bz_nelem = 0;
  642         null_bbl.bz_nsnf = 0;
  643         up->zu_zdbad = &null_bbl;
  644 
  645         dd = (up->zu_drive & 1) ? &zdctrlr[up->zu_ctrlr].zdc_chanB
  646                                 : &zdctrlr[up->zu_ctrlr].zdc_chanA;
  647         size = 1;                               /* get 1 for starters */
  648         if (kmem_alloc(kernel_map,
  649                        (vm_offset_t *)&zdp,
  650                        DEV_BSIZE) != KERN_SUCCESS)
  651             panic("zdgetbad");
  652 
  653         /*
  654          * Read bad block list.
  655          */
  656         bp = &up->zu_ioctl;
  657 #ifndef MACH
  658         bufalloc(bp);
  659 #endif  MACH
  660         bp->b_dev = dev;
  661         bp->b_blkno = 0;
  662 #ifndef MACH_KERNEL
  663         bp->b_proc = u.u_procp;
  664 #endif  MACH_KERNEL
  665 #ifndef MACH
  666         bp->b_iotype = B_FILIO;
  667 #endif  MACH
  668         cbp = &up->zu_ioctlcb;
  669         cbp->cb_mod = 0;
  670         cbp->cb_cmd = ZDC_READ;
  671         cbp->cb_cyl = ZDD_DDCYL;
  672         addr = (caddr_t)zdp;
  673         for (block = 0; block < size; block++) {
  674                 cbp->cb_head = 0;
  675                 cbp->cb_sect = ZDD_NDDSECTORS + block;
  676                 while (cbp->cb_head < MIN(dd->zdd_tracks, BZ_NBADCOPY)) {
  677                         bp->b_bcount = DEV_BSIZE;
  678                         bp->b_flags = B_READ | B_IOCTL;
  679                         bp->b_un.b_addr = addr;
  680                         bp->b_error = 0;
  681 #ifndef MACH
  682                         BIODONE(bp) = 0;
  683 #endif  MACH
  684                         cbp->cb_count = DEV_BSIZE;
  685                         cbp->cb_addr = KVTOPHYS(addr, u_int);
  686                         /*
  687                          * Queue and start I/O
  688                          */
  689                         (void)p_lock(&up->zu_lock, SPLZD);
  690                         bp->av_forw = NULL;
  691                         up->zu_bhead.av_forw = bp;
  692                         zdstart(up);
  693                         v_lock(&up->zu_lock, SPL0);
  694                         biowait(bp);
  695                         if ((bp->b_flags & B_ERROR) != B_ERROR)
  696                                 break;
  697                         /*
  698                          * If could not read - try next track.
  699                          */
  700                         cbp->cb_head++;
  701                         cbp->cb_sect = block;
  702                 }
  703 
  704                 /*
  705                  * If cannot read the first block of bad block list.
  706                  * give up and return.
  707                  */
  708                 if (bp->b_flags & B_ERROR) {
  709                         printf("zd%d: Cannot read block %d of bad block list.\n",
  710                                         up - zdunit, block);
  711                         if (block == 0)
  712                             kmem_free(kernel_map, (vm_offset_t)zdp, DEV_BSIZE);
  713                         else
  714                             kmem_free(kernel_map, (vm_offset_t)zdp,
  715                                                   dbtob(size));
  716 #ifndef MACH
  717                         buffree(bp);
  718 #endif  MACH
  719                         up->zu_zdbad = (struct zdbad *)NULL;
  720                         return (-1);
  721                 }
  722                 if (block == 0) {
  723                         size = (zdp->bz_nelem * sizeof(struct bz_bad))
  724                                 + sizeof(struct zdbad) - sizeof(struct bz_bad);
  725                         size = howmany(size, DEV_BSIZE);
  726                         if (size > ((dd->zdd_sectors - ZDD_NDDSECTORS) >> 1)) {
  727                                 printf("zd%d: Bad block list corrupted!\n",
  728                                         up - zdunit);
  729                                 kmem_free(kernel_map, (vm_offset_t)zdp,
  730                                                         DEV_BSIZE);
  731                                 up->zu_zdbad = (struct zdbad *)NULL;
  732                                 return (-1);
  733                         }
  734                         zdpsize = dbtob(size);
  735                         /*
  736                          * copy block 0 to new location in free memory, so
  737                          * that bad block list will be contiguous.
  738                          */
  739                         if (kmem_alloc(kernel_map,
  740                                        (vm_offset_t *)&addr,
  741                                        zdpsize) != KERN_SUCCESS)
  742                             panic("zdgetbad");
  743                         bcopy((caddr_t)zdp, addr, (unsigned)DEV_BSIZE);
  744                         kmem_free(kernel_map, (vm_offset_t)zdp, DEV_BSIZE);
  745                         zdp = (struct zdbad *)addr;
  746                 }
  747                 addr += DEV_BSIZE;
  748         } /* end of for */ 
  749 
  750 #ifndef MACH
  751         /*
  752          * done with I/O - free buf header.
  753          */
  754         buffree(bp);
  755 #endif  MACH
  756 
  757         /*
  758          * Confirm data integrity via checksum.
  759          */
  760         size = (zdp->bz_nelem * sizeof(struct bz_bad)) / sizeof(long);
  761         if (zdp->bz_csn != getchksum((long *)zdp->bz_bad, size,
  762                                 (long)(zdp->bz_nelem ^ zdp->bz_nsnf))) {
  763                 printf("zd%d: Checksum failed!\n", up - zdunit);
  764                 kmem_free(kernel_map, (vm_offset_t)zdp, zdpsize);
  765                 up->zu_zdbad = (struct zdbad *)NULL;
  766                 return (-1);
  767         }
  768 
  769         /*
  770          * Copy only BZ_SNF entries into unit's bad block list.
  771          * 
  772          * Calculate size of needed bad block list.
  773          * That is, only BZ_SNF entries are needed.
  774          */
  775         size = (zdp->bz_nsnf * sizeof(struct bz_bad))
  776                 + sizeof(struct zdbad) - sizeof(struct bz_bad);
  777         size = roundup(size, DEV_BSIZE);
  778         if (kmem_alloc(kernel_map,
  779                        (vm_offset_t *)&up->zu_zdbad,
  780                        size) != KERN_SUCCESS)
  781             panic("zdgetbad");
  782 #ifdef  DEBUG
  783         bzero((caddr_t)up->zu_zdbad, (u_int)size);
  784 #endif  DEBUG
  785         *up->zu_zdbad = *zdp;
  786         tbzp = up->zu_zdbad->bz_bad;
  787         for (fbzp = zdp->bz_bad; fbzp < &zdp->bz_bad[zdp->bz_nelem]; fbzp++) {
  788                 if (fbzp->bz_rtype == BZ_SNF)
  789                         *tbzp++ = *fbzp;
  790         }
  791         kmem_free(kernel_map, (vm_offset_t)zdp, zdpsize);
  792         return (0);
  793 }
  794 
  795 /*
  796  * zdstrat
  797  *      zd disk read/write routine.
  798  * Perform various checks and queue request and call start routine to
  799  * initiate I/O to the device.
  800  */
  801 zdstrat(bp)
  802         register struct buf *bp;
  803 {
  804         register struct zd_unit *up;
  805         register struct zdcdd   *dd;            /* channel configuration */
  806         register int sector;
  807         register int nspc;
  808         struct  zdsize  *part;
  809         struct  diskaddr diskaddress;
  810         spl_t s_ipl;
  811 
  812 #ifdef  DEBUG
  813         if (zddebug > 1)
  814                 printf("zdstrat(%c): bp=%x, dev=%x, cnt=%d, blk=%x, vaddr=%x\n",
  815                         (bp->b_flags & B_READ) ? 'R' : 'W',
  816                         bp, bp->b_dev, bp->b_bcount, bp->b_blkno,
  817                         bp->b_un.b_addr);
  818         else    if (zddebug)
  819                         printf("%c", (bp->b_flags & B_READ) ? 'R' : 'W');
  820 #endif  DEBUG
  821 
  822         up = &zdunit[ZDUNIT(bp->b_dev)];
  823         /*
  824          * Error if NO_RW operations are permitted.
  825          */
  826         if (up->zu_state == ZU_NO_RW) {
  827                 bp->b_flags |= B_ERROR;
  828                 bp->b_error = EIO;
  829                 bp->b_resid = bp->b_bcount;
  830                 biodone(bp);
  831                 return;
  832         }
  833 
  834         part = &zdparts[up->zu_drive_type][ZDPART(bp->b_dev)];
  835         /*
  836          * Size and partitioning check.
  837          *
  838          * Fail request if bogus byte count, if address not aligned to
  839          * ADDRALIGN boundary, or if transfer is not entirely within a
  840          * disk partition.
  841          */
  842         if (bp->b_bcount <= 0
  843         ||  ((bp->b_bcount & (DEV_BSIZE -1)) != 0)              /* size */
  844 #ifdef  MACH_KERNEL
  845         ||  (
  846 #else   MACH_KERNEL
  847 #ifndef MACH
  848         ||  ((bp->b_iotype == B_RAWIO) &&
  849 #else   MACH
  850         ||  ((bp->b_flags & B_PHYS) &&
  851 #endif  MACH
  852 #endif  MACH_KERNEL
  853              (((int)bp->b_un.b_addr & (ADDRALIGN - 1)) != 0))   /* alignment */
  854         ||  (bp->b_blkno < 0)                                   /* partition */
  855         ||  ((bp->b_blkno + btodb(bp->b_bcount)) > part->p_length)) {
  856                 bp->b_flags |= B_ERROR;
  857                 bp->b_error = EINVAL;
  858                 bp->b_resid = bp->b_bcount;
  859                 biodone(bp);
  860                 return;
  861         }
  862 
  863         dd = (up->zu_drive & 1) ? &zdctrlr[up->zu_ctrlr].zdc_chanB
  864                                 : &zdctrlr[up->zu_ctrlr].zdc_chanA;
  865         nspc = dd->zdd_sectors * dd->zdd_tracks;
  866         sector = bp->b_blkno;
  867 #if 1
  868         { /* gcc bug workaround */
  869             int temp;
  870             u_short temp2;
  871             temp = sector / nspc + part->p_cyloff;
  872             temp2 = temp & 0xFFFF;
  873             diskaddress.da_cyl = temp2;
  874         }
  875 #else
  876         diskaddress.da_cyl = sector / nspc + part->p_cyloff;
  877 #endif
  878         sector %= nspc;
  879         diskaddress.da_head = sector / dd->zdd_sectors;
  880         diskaddress.da_sect = sector % dd->zdd_sectors;
  881         bp->b_diskaddr = *(long *)&diskaddress;
  882         bp->b_psect = zdgetpsect(&diskaddress, dd);
  883 
  884         s_ipl = p_lock(&up->zu_lock, SPLZD);
  885         if (up->zu_state == ZU_BAD) {
  886                 v_lock(&up->zu_lock, s_ipl);
  887                 /*
  888                  * Controller/channel/Drive has gone bad!
  889                  */
  890                 bp->b_flags |= B_ERROR;
  891                 bp->b_error = EIO;
  892                 bp->b_resid = bp->b_bcount;
  893                 biodone(bp);
  894                 return;
  895         }
  896         disksort(&up->zu_bhead, bp);
  897         zdstart(up);
  898         v_lock(&up->zu_lock, s_ipl);
  899 }
  900 
  901 /*
  902  * zdgetpsect
  903  *      Determine physical sector in track where the I/O  transfer is to
  904  *      occur. Used by ZDC firmware for RPS optimization.
  905  */
  906 int
  907 zdgetpsect(dp, dd)
  908         register struct diskaddr *dp;
  909         register struct zdcdd    *dd;
  910 {
  911         if (dd->zdd_tskew == 1)
  912                 return (( ((dd->zdd_tracks - 1 + dd->zdd_cskew) * dp->da_cyl)
  913                                 + dp->da_head + dp->da_sect)
  914                                          % (dd->zdd_sectors + dd->zdd_spare));
  915         /*
  916          * track skew != 1
  917          */
  918         return (( (((dd->zdd_tskew*(dd->zdd_tracks-1)) + dd->zdd_cskew)
  919                                                                  * dp->da_cyl)
  920                   + (dd->zdd_tskew*dp->da_head) + dp->da_sect)
  921                                         % (dd->zdd_sectors + dd->zdd_spare));
  922 }
  923 
  924 /*
  925  * zdfill_iovec
  926  *      - fill out cb_iovec for the I/O request.
  927  *
  928  * B_RAWIO, B_PTEIO, B_PTBIO cases must flush TLB to avoid stale mappings
  929  * thru Usrptmap[], since this is callable from interrupt procedures (SGS only).
  930  *
  931  * Panics if bad pte found; "can't" happen.
  932  */
  933 
  934 #ifndef MACH
  935 
  936 static u_int
  937 zdfill_iovec(bp, iovstart)
  938 #ifndef i386
  939         register                                /* want optimial on 032's */
  940 #endif
  941         struct buf *bp;
  942         u_int *iovstart;
  943 {
  944         register struct pte *pte;
  945         register int    count;
  946         register u_int  *iovp;
  947         u_int   retval;
  948         unsigned offset;
  949         extern struct pte *vtopte();
  950 
  951         /*
  952          * Source/target pte's are found differently based on type
  953          * of IO operation.
  954          */
  955         switch(bp->b_iotype) {
  956 
  957         case B_RAWIO:                                   /* RAW IO */
  958                 /*
  959                  * In this case, must look into alignment of physical
  960                  * memory, since we can start on any ADDRALIGN boundary.
  961                  */
  962                 flush_tlb();
  963                 pte = vtopte(bp->b_proc, clbase(btop(bp->b_un.b_addr)));
  964                 count = (((int)bp->b_un.b_addr & CLOFSET) + bp->b_bcount
  965                                                          + CLOFSET) / CLBYTES;
  966                 retval = (u_int)bp->b_un.b_addr;
  967                 break;
  968 
  969         case B_FILIO:                                   /* file-sys IO */
  970                 /*
  971                  * Filesys/buffer-cache IO.  These are always cluster aligned
  972                  * both physically and virtually.
  973                  * Note: also used when to kernel memory acquired via wmemall().
  974                  * For example, channel configuration buffer in zdget_chancfg().
  975                  */
  976                 pte = &Sysmap[btop(bp->b_un.b_addr)];
  977                 count = (bp->b_bcount + CLOFSET) / CLBYTES;
  978                 retval = (u_int)bp->b_un.b_addr;
  979                 break;
  980 
  981         case B_PTEIO:                                   /* swap/page IO */
  982                 /*
  983                  * Pte-based IO -- already know pte of 1st page, which
  984                  * is cluster aligned, and b_count is a multiple of CLBYTES.
  985                  */
  986                 flush_tlb();
  987                 pte = bp->b_un.b_pte;
  988                 count = (bp->b_bcount + CLOFSET) / CLBYTES;
  989                 retval = PTETOPHYS(*pte);
  990                 break;
  991 
  992         case B_PTBIO:                                   /* Page-Table IO */
  993                 /*
  994                  * Page-Table IO: like B_PTEIO, but can start/end with
  995                  * non-cluster aligned memory (but is always HW page
  996                  * aligned). Count is multiple of NBPG.
  997                  *
  998                  * Separate case for greater efficiency in B_PTEIO.
  999                  */
 1000                 flush_tlb();
 1001                 pte = bp->b_un.b_pte;
 1002                 retval = PTETOPHYS(*pte);
 1003                 offset = PTECLOFF(*pte);
 1004                 pte -= btop(offset);
 1005                 count = (offset + bp->b_bcount + CLOFSET) / CLBYTES;
 1006                 break;
 1007 
 1008         default:
 1009                 panic("zdfill_iovec: bad b_iotype");
 1010                 /*NOTREACHED*/
 1011         }
 1012 
 1013         /*
 1014          * Now translate PTEs and fill-in iovectors.
 1015          */
 1016         iovp = iovstart;
 1017         while (count--) {
 1018                 *iovp++ = PTETOPHYS(*pte);
 1019                 pte += CLSIZE;
 1020         }
 1021         return (retval);
 1022 }
 1023 
 1024 #else   MACH
 1025 
 1026 #ifdef  MACH_KERNEL
 1027 /*
 1028  * pure Mach kernel version.
 1029  */
 1030 static u_int
 1031 zdfill_iovec(bp, iovp)
 1032         register struct buf *bp;
 1033         register u_int  *iovp;
 1034 {
 1035         register pt_entry_t *pte;
 1036         register int    count;
 1037         vm_offset_t     start, end;
 1038 
 1039         /*
 1040          * In this case, must look into alignment of physical
 1041          * memory, since we can start on any ADDRALIGN boundary.
 1042          *
 1043          * Since ptes mapping kernel address space are contiguous in
 1044          * kernel address space, can bump pte inside loop.
 1045          */
 1046 
 1047         start = i386_trunc_page((vm_offset_t)bp->b_un.b_addr);
 1048         end   = i386_round_page((vm_offset_t)bp->b_un.b_addr + bp->b_bcount);
 1049         pte   = pmap_pte(kernel_pmap, start);
 1050         count = i386_btop(end - start);
 1051         while (count--) {
 1052                 *iovp++ = pte_to_pa(*pte);
 1053                 pte++;
 1054         }
 1055         return((u_int)bp->b_un.b_addr);
 1056 }
 1057 #else   MACH_KERNEL
 1058 /*
 1059  * MACH version.
 1060  */
 1061 static u_int
 1062 zdfill_iovec(bp, iovp)
 1063         register struct buf *bp;
 1064         register u_int  *iovp;
 1065 {
 1066         register struct pte *pte;
 1067         register int    count;
 1068 
 1069         if (bp->b_flags & B_PHYS) {
 1070                 /*
 1071                  * In this case, must look into alignment of physical
 1072                  * memory, since we can start on any ADDRALIGN boundary.
 1073                  *
 1074                  * Since pte's mapping user task can be dis-contiguous in
 1075                  * kernel address space, need to re-compute pte inside loop.
 1076                  */
 1077                 vm_offset_t     addr;
 1078                 pmap_t          map;
 1079 
 1080                 addr = ((vm_offset_t)bp->b_un.b_addr & ~CLOFSET) | VA_USER;
 1081                 map = vm_map_pmap(bp->b_proc->task->map);
 1082                 count = (((int)bp->b_un.b_addr & CLOFSET) + bp->b_bcount
 1083                                                          + CLOFSET) / CLBYTES;
 1084                 while (count--) {
 1085                         pte = (struct pte *) pmap_pte(map, addr);
 1086                         *iovp++ = PTETOPHYS(*pte);
 1087                         addr += CLBYTES;
 1088                 }
 1089         } else {
 1090                 /*
 1091                  * Filesys/buffer-cache IO.  These are always cluster aligned
 1092                  * both physically and virtually.
 1093                  * Note: also used on kernel memory acquired via wmemall().
 1094                  * For example, channel configuration buffer in zdget_chancfg().
 1095                  *
 1096                  * Since pte's mapping kernel address space are contiguous
 1097                  * virtually, can bump pte inside loop.
 1098                  */
 1099                 pte = &Sysmap[btop(bp->b_un.b_addr)];
 1100                 count = (bp->b_bcount + CLOFSET) / CLBYTES;
 1101                 while (count--) {
 1102                         *iovp++ = PTETOPHYS(*pte);
 1103                         pte += CLSIZE;
 1104                 }
 1105         }
 1106         return((u_int)bp->b_un.b_addr);
 1107 }
 1108 #endif  MACH_KERNEL
 1109 #endif  MACH
 1110 
 1111 /*
 1112  * zdstart
 1113  *      - intitiate I/O request to controller.
 1114  * If controller is busy just return. Otherwise stuff appropriate CB
 1115  * with request and notify ZDC.
 1116  *
 1117  * Called with unit structure locked at SPLZD.
 1118  */
 1119 zdstart(up)
 1120         register struct zd_unit *up;
 1121 {
 1122         register struct cb      *cbp;
 1123         register struct buf     *bp;
 1124         register struct zdc_ctlr *ctlrp;
 1125         spl_t   s_ipl;
 1126 
 1127 #ifdef  DEBUG
 1128         if (zddebug)
 1129                 printf("S");
 1130 #endif  DEBUG
 1131         bp = up->zu_bhead.av_forw;
 1132         ctlrp = &zdctrlr[up->zu_ctrlr];
 1133         cbp = up->zu_cbptr;
 1134         if (cbp->cb_bp == NULL && cbp[1].cb_bp == NULL) {
 1135                 /*
 1136                  * Drive is idle.
 1137                  * If fp_lights - turn activity light on.
 1138                  * Get starting time.
 1139                  */
 1140                 if (fp_lights) {
 1141                         s_ipl = splhi();
 1142                         FP_IO_ACTIVE;
 1143                         splx(s_ipl);
 1144                 }
 1145                 up->zu_starttime = time;
 1146         }
 1147         if (cbp->cb_bp == NULL || cbp[1].cb_bp == NULL) {
 1148                 /*
 1149                  * Fill CB.
 1150                  */
 1151                 if (cbp->cb_bp)
 1152                         ++cbp;
 1153                 if (bp->b_flags & B_IOCTL) {
 1154                         /*
 1155                          * copy 1st half of cb (what fw will see)
 1156                          */
 1157                         bcopy((caddr_t)&up->zu_ioctlcb, (caddr_t)cbp, FWCBSIZE);
 1158                         if (cbp->cb_cmd != ZDC_READ_LRAM
 1159                         &&  cbp->cb_cmd != ZDC_WRITE_LRAM)
 1160                                 cbp->cb_addr = zdfill_iovec(bp, cbp->cb_iovstart);
 1161                 } else {
 1162                         *(long *)&cbp->cb_diskaddr = bp->b_diskaddr;
 1163                         cbp->cb_psect = (u_char)bp->b_psect;
 1164                         cbp->cb_count = bp->b_bcount;
 1165                         cbp->cb_mod = 0;
 1166                         cbp->cb_cmd = (bp->b_flags & B_READ) ? ZDC_READ : ZDC_WRITE;
 1167                         cbp->cb_addr = zdfill_iovec(bp, cbp->cb_iovstart);
 1168 #ifdef  MACH_KERNEL
 1169                         bp->b_error = 0;        /* was b_psect */
 1170 #endif  /* MACH_KERNEL */
 1171                 }
 1172                 bp->b_resid = bp->b_bcount;
 1173                 cbp->cb_transfrd = 0;
 1174                 cbp->cb_bp = bp;
 1175                 cbp->cb_errcnt = 0;
 1176                 cbp->cb_state = ZD_NORMAL;
 1177                 cbp->cb_iovec = KVTOPHYS(cbp->cb_iovstart, u_int *);
 1178                 /*
 1179                  * Notify ZDC of job request.
 1180                  */
 1181 #ifdef  DEBUG
 1182                 if (zddebug > 2)
 1183                         zddumpcb(cbp);
 1184 #endif  DEBUG
 1185                 NUDGE_ZDC(ctlrp, cbp, s_ipl);
 1186                 up->zu_bhead.av_forw = bp->av_forw;
 1187                 bp = bp->av_forw;
 1188                 cbp = up->zu_cbptr;
 1189         }
 1190 }
 1191 
 1192 /*
 1193  * zdintr
 1194  *      Normal request completion interrupt handler.
 1195  */
 1196 zdintr(vector)
 1197         u_char  vector;
 1198 {
 1199         register struct cb       *cbp;
 1200         register struct zd_unit  *up;
 1201         register struct buf      *donebp;
 1202         register struct zdc_ctlr *ctlrp;
 1203         struct  zdcdd *dd;
 1204         int     zdcvec;
 1205         daddr_t blkno;
 1206         int     i;
 1207         int     partition;
 1208         u_char  val;
 1209         spl_t   s_ipl;
 1210 
 1211 #ifdef  DEBUG
 1212         if (zddebug)
 1213                 printf("I");
 1214 #endif  DEBUG
 1215         zdcvec = vector - base_cb_intr;
 1216         ctlrp = &zdctrlr[zdcvec >> NCBZDCSHFT];
 1217         cbp = ctlrp->zdc_cbp + (zdcvec & (NCBPERZDC-1));
 1218         up = &zdunit[cbp->cb_unit];
 1219         if (cbp->cb_bp == NULL) {
 1220                 if (ctlrp->zdc_state == ZDC_DEAD) {
 1221                         printf("zdc%d drive %d: Spurious interrupt from dead controller.\n",
 1222                                 ctlrp - zdctrlr,
 1223                                 (cbp - ctlrp->zdc_cbp) / NCBPERDRIVE);
 1224                         return;
 1225                 }
 1226                 if (cbp->cb_unit < 0) {
 1227                         printf("zdc%d drive %d: Interrupt from unknown unit.\n",
 1228                                 ctlrp - zdctrlr,
 1229                                 (cbp - ctlrp->zdc_cbp) / NCBPERDRIVE);
 1230                         return;
 1231                 }
 1232                 printf("zd%d: Spurious interrupt.\n", cbp->cb_unit);
 1233                 return;
 1234         }
 1235 
 1236         /*
 1237          * Separate normal case from error cases for performance.
 1238          */
 1239         if (cbp->cb_compcode == ZDC_DONE) {
 1240                 if (cbp->cb_state == ZD_NORMAL) {
 1241                         donebp = cbp->cb_bp;
 1242                         donebp->b_resid = 0;
 1243                         goto donext;
 1244                 }
 1245                 if (cbp->cb_state & ZD_RESET) {
 1246                         /*
 1247                          * Reset completed.
 1248                          */
 1249                         cbp->cb_state &= ~ZD_RESET;
 1250                         if (cbp->cb_errcnt++ < zdcretry) {
 1251                                 zdretry(cbp, up, ctlrp);
 1252                                 return;
 1253                         }
 1254                         /*
 1255                          * Fail I/O request.
 1256                          */
 1257                         donebp = cbp->cb_bp;
 1258                         donebp->b_flags |= B_ERROR;
 1259                         donebp->b_error = EIO;
 1260                         goto donext;
 1261                 }
 1262                 if (cbp->cb_state & ZD_REVECTOR) {
 1263                         /*
 1264                          * Completed revector. Continue with rest of transfer.
 1265                          */
 1266                         zdcontinue(cbp, up, ctlrp);
 1267                         return;
 1268                 }
 1269         }
 1270 
 1271         /*
 1272          * E R R O R  O C C U R R E D !
 1273          */
 1274 
 1275         /*
 1276          * If not doing retry reset or revectoring, update b_resid.
 1277          */
 1278         if (cbp->cb_state == ZD_NORMAL)
 1279                 cbp->cb_bp->b_resid = cbp->cb_count;
 1280 
 1281         blkno = btodb(cbp->cb_bp->b_bcount - cbp->cb_bp->b_resid)
 1282                 + cbp->cb_bp->b_blkno;
 1283 
 1284         if (cbp->cb_state & ZD_RESET) {
 1285                 /*
 1286                  * Error occurred during attempted reset for previous
 1287                  * error. Give up and shutdown the drive.
 1288                  */
 1289                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1290                 printf("zd%d: Reset Failed.\n", cbp->cb_unit);
 1291                 if (cbp->cb_compcode >= zdncompcodes) {
 1292                         printf("zd%d: Bad cb_compcode 0x%x.\n",
 1293                                 cbp->cb_unit, cbp->cb_compcode);
 1294                         cbp->cb_compcode = zdncompcodes - 1;
 1295                 }
 1296                 zd_hard_error(cbp, blkno);
 1297                 zddumpstatus(cbp);
 1298                 v_lock(&zdcprlock, s_ipl);
 1299                 zdshutdrive(up);
 1300         } else switch (cbp->cb_compcode) {
 1301 
 1302         /*
 1303          * Command completed successfully but an ecc error occurred.
 1304          */
 1305         case ZDC_SOFTECC:
 1306         case ZDC_CORRECC:
 1307                 /*
 1308                  * Corrected or Soft ECC error.
 1309                  */
 1310                 dd = (up->zu_drive & 1) ? &ctlrp->zdc_chanB : &ctlrp->zdc_chanA;
 1311                 blkno = cbp->cb_cyl
 1312                         - zdparts[up->zu_drive_type][ZDPART(cbp->cb_bp->b_dev)].p_cyloff;
 1313                 blkno *= (dd->zdd_sectors * dd->zdd_tracks);
 1314                 blkno += (cbp->cb_head * dd->zdd_sectors);
 1315                 blkno += cbp->cb_sect;
 1316                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1317                 printf("zd%d%c: %s at (%d, %d, %d).\n",
 1318                         cbp->cb_unit, PARTCHR(cbp->cb_bp->b_dev),
 1319                         zd_compcodes[cbp->cb_compcode],
 1320                         cbp->cb_cyl, cbp->cb_head, cbp->cb_sect);
 1321                 printf("zd%d%c: Filesystem blkno = %d.\n", cbp->cb_unit,
 1322                         PARTCHR(cbp->cb_bp->b_dev), blkno);
 1323                 zddumpstatus(cbp);
 1324                 v_lock(&zdcprlock, s_ipl);
 1325                 if (cbp->cb_state & ZD_REVECTOR) {
 1326                         /*
 1327                          * Completed revector. Continue with rest of transfer.
 1328                          */
 1329                         zdcontinue(cbp, up, ctlrp);
 1330                         return;
 1331                 }
 1332                 donebp = cbp->cb_bp;
 1333                 goto donext;            /* Not fatal */
 1334 
 1335         /*
 1336          * Fail the job immediately - no retries.
 1337          */
 1338         case ZDC_DRVPROT:
 1339         case ZDC_ECC:
 1340                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1341                 zd_hard_error(cbp, blkno);
 1342                 zddumpstatus(cbp);
 1343                 v_lock(&zdcprlock, s_ipl);
 1344                 break;
 1345 
 1346         case ZDC_CH_RESET:              /* Shutdown drive */
 1347         case ZDC_BADDRV:
 1348         case ZDC_DDC_STAT:
 1349                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1350                 zd_hard_error(cbp, blkno);
 1351                 zddumpstatus(cbp);
 1352                 v_lock(&zdcprlock, s_ipl);
 1353                 zdshutdrive(up);
 1354                 break;
 1355 
 1356         case ZDC_DMA_TO:                /* Shutdown Channel */
 1357                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1358                 zd_hard_error(cbp, blkno);
 1359                 v_lock(&zdcprlock, s_ipl);
 1360                 zdshutchan(ctlrp, up->zu_drive & 1);
 1361                 break;
 1362 
 1363         case ZDC_NOCFG:
 1364                 if (cbp->cb_cmd == ZDC_GET_CHANCFG) {
 1365                         donebp = cbp->cb_bp;
 1366                         goto donext;            /* Not an error */
 1367                 }
 1368                 /*
 1369                  * FW assumed insane...
 1370                  */
 1371         case ZDC_REVECT:                /* FW hosed - shutdown controller */
 1372         case ZDC_ILLVECIO:
 1373         case ZDC_ILLPGSZ:
 1374         case ZDC_ILLDUMPADR:
 1375                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1376                 zd_hard_error(cbp, blkno);
 1377                 zddumpstatus(cbp);      /* for ZDC_REVECT */
 1378                 v_lock(&zdcprlock, s_ipl);
 1379                 zdshutctlr(ctlrp);
 1380                 break;
 1381 
 1382         default:
 1383                 /*
 1384                  * Unknown completion code - controller bad?
 1385                  */
 1386                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1387                 printf("zd%d: Bad cb_compcode 0x%x.\n",
 1388                         cbp->cb_unit, cbp->cb_compcode);
 1389                 cbp->cb_compcode = zdncompcodes - 1;    /* nice message */
 1390                 zd_hard_error(cbp, blkno);
 1391                 v_lock(&zdcprlock, s_ipl);
 1392                 zdshutctlr(ctlrp);
 1393                 break;
 1394 
 1395         case ZDC_ILLCMD:
 1396                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1397                 zd_hard_error(cbp, blkno);
 1398                 if (cbp->cb_cmd == 0 || cbp->cb_cmd > ZDC_MAXCMD) {
 1399                         printf("zd%d: cb_cmd 0x%x corrupted.\n",
 1400                                 cbp->cb_unit, cbp->cb_cmd);
 1401                         v_lock(&zdcprlock, s_ipl);
 1402                         panic("zdintr: cb corrupted");
 1403                 }
 1404                 v_lock(&zdcprlock, s_ipl);
 1405                 /*
 1406                  * Cb looks ok - assume controller unreliable
 1407                  */
 1408                 zdshutctlr(ctlrp);
 1409                 break;
 1410 
 1411         case ZDC_ILLMOD:
 1412                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1413                 zd_hard_error(cbp, blkno);
 1414                 switch(cbp->cb_cmd) {
 1415 
 1416                 case ZDC_READ:
 1417                 case ZDC_READ_SS:
 1418                 case ZDC_READ_HDRS:
 1419                 case ZDC_LONG_READ:
 1420                 case ZDC_REC_DATA:
 1421                         if (cbp->cb_mod != up->zu_ioctlcb.cb_mod) {
 1422                                 printf("zd%d: cb_mod 0x%x corrupted.\n",
 1423                                         cbp->cb_unit, cbp->cb_mod);
 1424                                 v_lock(&zdcprlock, s_ipl);
 1425                                 panic("zdintr: cb corrupted");
 1426                         }
 1427                 }
 1428                 v_lock(&zdcprlock, s_ipl);
 1429                 /*
 1430                  * Cb looks ok - assume controller unreliable
 1431                  */
 1432                 zdshutctlr(ctlrp);
 1433                 break;
 1434 
 1435         case ZDC_ILLALIGN:
 1436                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1437                 zd_hard_error(cbp, blkno);
 1438                 if ((cbp->cb_addr & (ADDRALIGN - 1)) != 0) {
 1439                         printf("zd%d: cb_addr 0x%x corrupted.\n",
 1440                                 cbp->cb_unit, cbp->cb_addr);
 1441                         v_lock(&zdcprlock, s_ipl);
 1442                         panic("zdintr: cb corrupted");
 1443                 }
 1444                 v_lock(&zdcprlock, s_ipl);
 1445                 /*
 1446                  * Cb looks ok - assume controller unreliable
 1447                  */
 1448                 zdshutctlr(ctlrp);
 1449                 break;
 1450 
 1451         case ZDC_ILLCNT:
 1452                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1453                 zd_hard_error(cbp, blkno);
 1454                 if (cbp->cb_count == 0 || (cbp->cb_count & (CNTMULT-1)) != 0) {
 1455                         printf("zd%d: cb_count 0x%x corrupted.\n",
 1456                                 cbp->cb_unit, cbp->cb_count);
 1457                         v_lock(&zdcprlock, s_ipl);
 1458                         panic("zdintr: cb corrupted");
 1459                 }
 1460                 v_lock(&zdcprlock, s_ipl);
 1461                 /*
 1462                  * Cb looks ok - assume controller unreliable
 1463                  */
 1464                 zdshutctlr(ctlrp);
 1465                 break;
 1466 
 1467         case ZDC_ILLIOV:
 1468                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1469                 zd_hard_error(cbp, blkno);
 1470                 if (((u_int)cbp->cb_iovec & (IOVALIGN - 1)) != 0) {
 1471                         printf("zd%d: cb_iovec 0x%x corrupted.\n",
 1472                                 cbp->cb_unit, cbp->cb_iovec);
 1473                         v_lock(&zdcprlock, s_ipl);
 1474                         panic("zdintr: cb corrupted");
 1475                 }
 1476                 v_lock(&zdcprlock, s_ipl);
 1477                 /*
 1478                  * Cb looks ok - assume controller unreliable
 1479                  */
 1480                 zdshutctlr(ctlrp);
 1481                 break;
 1482 
 1483         case ZDC_ILLCHS:
 1484                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1485                 zd_hard_error(cbp, blkno);
 1486                 dd = (up->zu_drive & 1) ? &ctlrp->zdc_chanB : &ctlrp->zdc_chanA;
 1487                 if (cbp->cb_cyl >= dd->zdd_cyls ||
 1488                     cbp->cb_head >= dd->zdd_tracks ||
 1489                     cbp->cb_sect >= dd->zdd_sectors + dd->zdd_spare) {
 1490                         printf("zd%d: cb_diskaddr (%d, %d, %d) corrupted.\n",
 1491                                 cbp->cb_unit,
 1492                                 cbp->cb_cyl, cbp->cb_head, cbp->cb_sect);
 1493                         v_lock(&zdcprlock, s_ipl);
 1494                         panic("zdintr: cb corrupted");
 1495                 }
 1496                 v_lock(&zdcprlock, s_ipl);
 1497                 /*
 1498                  * Cb looks ok - assume controller unreliable
 1499                  */
 1500                 zdshutctlr(ctlrp);
 1501                 break;
 1502 
 1503         case ZDC_CBREUSE:
 1504                 printf("zd%d: CBREUSE error cb = 0x%x\n", cbp->cb_unit, cbp);
 1505                 panic("zdc: ZDC_CBREUSE error");
 1506 
 1507         case ZDC_ACCERR:
 1508                 s_ipl = splhi();
 1509                 val = rdslave(ctlrp->zdc_slicaddr,
 1510                               (u_char)((up->zu_drive & 1) ? SL_G_ACCERR1
 1511                                                           : SL_G_ACCERR0));
 1512                 printf("zd%d: Access error on transfer starting at physical address 0x%x.\n",
 1513                                 cbp->cb_unit, cbp->cb_addr);
 1514                 access_error(val);
 1515                 val = ~val;
 1516                 if (((val & SLB_ATMSK) == SLB_AEFATAL) &&
 1517                     ((val & SLB_AEIO) != SLB_AEIO)) {
 1518                         /*
 1519                          * Uncorrectable memory error!
 1520                          * Clear access error to restart controller and
 1521                          * panic the system.
 1522                          */
 1523                         wrslave(ctlrp->zdc_slicaddr,
 1524                                 (u_char)((up->zu_drive & 1) ? SL_G_ACCERR1
 1525                                                             : SL_G_ACCERR0),
 1526                                 (u_char)0xbb);
 1527                         panic("zdc access error");
 1528                 }
 1529                 splx(s_ipl);
 1530 
 1531                 /*
 1532                  * Shutdown the channel and restart the controller.
 1533                  */
 1534                 zdshutchan(ctlrp, up->zu_drive & 1);
 1535                 s_ipl = splhi();
 1536                 wrslave(ctlrp->zdc_slicaddr,
 1537                         (u_char)((up->zu_drive & 1) ? SL_G_ACCERR1
 1538                                                     : SL_G_ACCERR0),
 1539                         (u_char)0xbb);
 1540                 splx(s_ipl);
 1541                 break;
 1542 
 1543         case ZDC_CH_TO:                 /* Retry without reset */
 1544         case ZDC_FDL:
 1545                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1546                 if (cbp->cb_errcnt++ < zdcretry) {
 1547 #ifdef  DEBUG
 1548                         zddumpcb(cbp);
 1549 #endif  DEBUG
 1550                         printf("zd%d%c: Error (%s); cmd 0x%x at (%d, %d, %d).\n",
 1551                                 cbp->cb_unit, PARTCHR(cbp->cb_bp->b_dev),
 1552                                 zd_compcodes[cbp->cb_compcode],
 1553                                 cbp->cb_cmd, cbp->cb_cyl, cbp->cb_head,
 1554                                 cbp->cb_sect);
 1555                         printf("zd%d%c: Filesystem blkno = %d.\n", cbp->cb_unit,
 1556                                 PARTCHR(cbp->cb_bp->b_dev), blkno);
 1557                         zddumpstatus(cbp);
 1558                         v_lock(&zdcprlock, s_ipl);
 1559                         zdretry(cbp, up, ctlrp);
 1560                         return;
 1561                 }
 1562                 /*
 1563                  * Exceeded retry count.
 1564                  * Shutdown the channel.
 1565                  */
 1566                 zd_hard_error(cbp, blkno);
 1567                 zddumpstatus(cbp);
 1568                 v_lock(&zdcprlock, s_ipl);
 1569                 zdshutchan(ctlrp, up->zu_drive & 1);
 1570                 break;
 1571 
 1572         case ZDC_DRVFLT:
 1573                 /*
 1574                  * cb_count and cb_diskaddr are unreliable on drive fault
 1575                  * so retry entire request.
 1576                  */
 1577                 cbp->cb_bp->b_resid = cbp->cb_bp->b_bcount - cbp->cb_transfrd;
 1578                 blkno = btodb(cbp->cb_bp->b_bcount - cbp->cb_bp->b_resid)
 1579                                 + cbp->cb_bp->b_blkno;
 1580                 dd = (up->zu_drive & 1) ? &ctlrp->zdc_chanB : &ctlrp->zdc_chanA;
 1581                 i = blkno;
 1582                 partition = ZDPART(cbp->cb_bp->b_dev);
 1583 #if 1
 1584                 { /* gcc bug workaround */
 1585                     int temp;
 1586                     short temp2;
 1587                     temp =
 1588                         i / (dd->zdd_sectors * dd->zdd_tracks) +
 1589                         zdparts[up->zu_drive_type][partition].p_cyloff;
 1590                     temp2 = temp;
 1591                     cbp->cb_diskaddr.da_cyl = temp2;
 1592                 }
 1593 #else
 1594                 cbp->cb_diskaddr.da_cyl = 
 1595                         i / (dd->zdd_sectors * dd->zdd_tracks) +
 1596                         zdparts[up->zu_drive_type][partition].p_cyloff;
 1597 #endif
 1598                 i %= (dd->zdd_sectors * dd->zdd_tracks);
 1599                 cbp->cb_diskaddr.da_head = i / dd->zdd_sectors;
 1600                 cbp->cb_diskaddr.da_sect = i % dd->zdd_sectors;
 1601                 /* Fall into */
 1602         case ZDC_SEEKERR:       /* reset and retry */
 1603         case ZDC_SEEK_TO:
 1604                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1605                 if (cbp->cb_errcnt < zdcretry) {
 1606 #ifdef  DEBUG
 1607                         zddumpcb(cbp);
 1608 #endif  DEBUG
 1609                         printf("zd%d%c: Error (%s); cmd 0x%x at (%d, %d, %d).\n",
 1610                                 cbp->cb_unit, PARTCHR(cbp->cb_bp->b_dev),
 1611                                 zd_compcodes[cbp->cb_compcode],
 1612                                 cbp->cb_cmd, cbp->cb_cyl, cbp->cb_head,
 1613                                 cbp->cb_sect);
 1614                         printf("zd%d%c: Filesystem blkno = %d.\n", cbp->cb_unit,
 1615                                 PARTCHR(cbp->cb_bp->b_dev), blkno);
 1616                         zddumpstatus(cbp);
 1617                         v_lock(&zdcprlock, s_ipl);
 1618                         /*
 1619                          * reset drive
 1620                          */
 1621                         cbp->cb_state |= ZD_RESET;
 1622                         cbp->cb_cmd = ZDC_RESET;
 1623                         NUDGE_ZDC(ctlrp, cbp, s_ipl);
 1624                         return;
 1625                 }
 1626 
 1627                 /*
 1628                  * Exceeded retry count.
 1629                  * Shutdown the drive.
 1630                  */
 1631                 zd_hard_error(cbp, blkno);
 1632                 zddumpstatus(cbp);
 1633                 v_lock(&zdcprlock, s_ipl);
 1634                 zdshutdrive(up);
 1635                 break;
 1636 
 1637         case ZDC_SNF:                   /* Revector request */
 1638                 if (zdrevector(cbp, up, ctlrp))
 1639                         return;
 1640                 /* else fall into... */
 1641         case ZDC_HDR_ECC:               /* Reset and retry */
 1642         case ZDC_SO:
 1643         case ZDC_NDS:
 1644                 s_ipl = p_lock(&zdcprlock, SPLZD);
 1645                 if (cbp->cb_errcnt == zdcretry)
 1646                         zd_hard_error(cbp, blkno);
 1647                 else {
 1648 #ifdef  DEBUG
 1649                         zddumpcb(cbp);
 1650 #endif  DEBUG
 1651                         printf("zd%d%c: Error (%s); cmd 0x%x at (%d, %d, %d).\n",
 1652                                 cbp->cb_unit, PARTCHR(cbp->cb_bp->b_dev),
 1653                                 zd_compcodes[cbp->cb_compcode],
 1654                                 cbp->cb_cmd, cbp->cb_cyl, cbp->cb_head,
 1655                                 cbp->cb_sect);
 1656                         printf("zd%d%c: Filesystem blkno = %d.\n", cbp->cb_unit,
 1657                                 PARTCHR(cbp->cb_bp->b_dev), blkno);
 1658                 }
 1659                 zddumpstatus(cbp);
 1660                 v_lock(&zdcprlock, s_ipl);
 1661                 cbp->cb_state |= ZD_RESET;
 1662                 cbp->cb_cmd = ZDC_RESET;
 1663                 NUDGE_ZDC(ctlrp, cbp, s_ipl);
 1664                 return;
 1665 
 1666         } /* end of switch */
 1667 
 1668         /*
 1669          * Fail this I/O request
 1670          */
 1671         donebp = cbp->cb_bp;
 1672         donebp->b_flags |= B_ERROR;
 1673         donebp->b_error = EIO;
 1674 
 1675 donext:
 1676 #ifdef  DEBUG
 1677         if (zddebug > 2)
 1678                 zddumpcb(cbp);
 1679 #endif  DEBUG
 1680         if (donebp->b_flags & B_IOCTL) {
 1681                 bcopy((caddr_t)cbp, (caddr_t)&up->zu_ioctlcb, FWCBSIZE);
 1682         }
 1683         /*
 1684          * If more requests - start them.
 1685          */
 1686         s_ipl = p_lock(&up->zu_lock, SPLZD);
 1687         cbp->cb_bp = NULL;
 1688         if (up->zu_bhead.av_forw != NULL) {
 1689                 zdstart(up);
 1690         } else {
 1691                 if (up->zu_cbptr->cb_bp == NULL
 1692                 &&  up->zu_cbptr[1].cb_bp == NULL) {
 1693                         /*
 1694                          * Going idle.
 1695                          * Get elapsed time and decrement I/O activity.
 1696                          */
 1697 #ifndef MACH
 1698                         if (up->zu_dkstats) {
 1699                                 struct timeval elapsed;
 1700 
 1701                                 elapsed = time;
 1702                                 timevalsub(&elapsed, &up->zu_starttime);
 1703                                 timevaladd(&up->zu_dkstats->dk_time, &elapsed);
 1704                         }
 1705 #endif  MACH
 1706                         if (fp_lights) {
 1707                                 s_ipl = splhi();
 1708                                 FP_IO_INACTIVE;
 1709                                 splx(s_ipl);
 1710                         }
 1711                 }
 1712         }
 1713         v_lock(&up->zu_lock, s_ipl);
 1714 
 1715         /*
 1716          * Gather stats
 1717          * Note: no attempt to mutex...
 1718          */
 1719 #ifndef MACH
 1720         if (up->zu_dkstats) {
 1721                 up->zu_dkstats->dk_xfer++;
 1722                 up->zu_dkstats->dk_blks +=
 1723                         btodb(donebp->b_bcount - donebp->b_resid);
 1724         }
 1725 #endif  MACH
 1726         biodone(donebp);
 1727 }
 1728 
 1729 /*
 1730  * zd_hard_error
 1731  *      report hard error
 1732  */
 1733 zd_hard_error(cbp, blkno)
 1734         register struct cb *cbp;
 1735         daddr_t blkno;
 1736 {
 1737 #ifdef  DEBUG
 1738         zddumpcb(cbp);
 1739 #endif  DEBUG
 1740         printf("zd%d%c: Hard Error (%s); cmd 0x%x at (%d, %d, %d).\n",
 1741                 cbp->cb_unit, PARTCHR(cbp->cb_bp->b_dev),
 1742                 zd_compcodes[cbp->cb_compcode], cbp->cb_cmd,
 1743                 cbp->cb_cyl, cbp->cb_head, cbp->cb_sect);
 1744         printf("zd%d%c: Filesystem blkno = %d.\n", cbp->cb_unit,
 1745                 PARTCHR(cbp->cb_bp->b_dev), blkno);
 1746 }
 1747 
 1748 /*
 1749  * zdgetrpl()
 1750  *      Search bad block list for replacement sector for bad sector (SNF).
 1751  *
 1752  * Return:
 1753  *      pointer to replacement sector
 1754  *      otherwise NULL pointer if no replacement sector found.
 1755  *      
 1756  */
 1757 static struct diskaddr *
 1758 zdgetrpl(badsect, zdp)
 1759         register struct diskaddr *badsect;
 1760         register struct zdbad    *zdp;
 1761 {
 1762         register struct bz_bad   *bb;
 1763 
 1764         bb = zdp->bz_bad;
 1765         for (bb = zdp->bz_bad; bb < &zdp->bz_bad[zdp->bz_nsnf]; bb++) {
 1766                 if (bb->bz_cyl < badsect->da_cyl)
 1767                         continue;
 1768                 if (bb->bz_cyl > badsect->da_cyl)
 1769                         break;
 1770                 /* cylinder matched */
 1771                 if (bb->bz_head < badsect->da_head)
 1772                         continue;
 1773                 if (bb->bz_head > badsect->da_head)
 1774                         break;
 1775                 /* head matched */
 1776                 if (bb->bz_sect == badsect->da_sect)
 1777                         return (&bb->bz_rpladdr);
 1778         }
 1779         return (NULL);
 1780 }
 1781 
 1782 /*
 1783  * zdrevector
 1784  *      Attempt to revector the sector-not-found.
 1785  * If the sector-not-found is in the bad block list perform the I/O on
 1786  * its replacement sector. Then continue with the following sector if
 1787  * necessary.
 1788  * 
 1789  * Return values:
 1790  *       0 - No replacement sector in bad block list.
 1791  *       1 - Replacement sector found in bad block list.
 1792  */
 1793 int
 1794 zdrevector(cbp, up, ctlrp)
 1795         register struct cb *cbp;
 1796         struct  zd_unit *up;
 1797         struct zdc_ctlr *ctlrp;
 1798 {
 1799         register struct zdcdd    *dd;           /* disk description */
 1800         register struct diskaddr *replcmnt;     /* replacement address */
 1801         register int    count;                  /* # bytes of iovecs */
 1802         int     transfrd;                       /* bytes already transferred */
 1803         int     cbcount;
 1804         u_int   *from;
 1805         spl_t   s_ipl;
 1806 
 1807 #ifdef  DEBUG
 1808         if (zddebug)
 1809                 printf("zd%d: revectoring (%d, %d, %d)", cbp->cb_unit,
 1810                         cbp->cb_cyl, cbp->cb_head, cbp->cb_sect);
 1811 #endif  DEBUG
 1812         /*
 1813          * Determine if bad block is in bad block list.
 1814          */
 1815         replcmnt = zdgetrpl(&cbp->cb_diskaddr, up->zu_zdbad);
 1816         if (replcmnt == NULL) {
 1817                 /*
 1818                  * Not in bad block list. Caller should retry
 1819                  * bad block.
 1820                  */
 1821 #ifdef  DEBUG
 1822                 if (zddebug)
 1823                         printf(": not in table.\n");
 1824 #endif  DEBUG
 1825                 return (0);
 1826         }
 1827 
 1828         /*
 1829          * Save state of current request, do new request for replacement.
 1830          */
 1831         transfrd = cbp->cb_bp->b_bcount - cbp->cb_bp->b_resid;
 1832         /* adjust for previously transferred sectors */
 1833         transfrd -= cbp->cb_transfrd;
 1834         from = cbp->cb_iovstart
 1835                 + i386_btop((cbp->cb_addr & (I386_PGBYTES-1)) + transfrd);
 1836         cbp->cb_transfrd += transfrd;
 1837         cbp->cb_addr += transfrd;
 1838 
 1839         /*
 1840          * figure number of iovecs to copy down.
 1841          */
 1842         count = 0;
 1843         cbcount = cbp->cb_count;
 1844         if (cbp->cb_addr & (I386_PGBYTES-1)) {
 1845                 ++count;
 1846                 cbcount -= I386_PGBYTES - (cbp->cb_addr & (I386_PGBYTES-1));
 1847         }
 1848         count += i386_btop(cbcount + (I386_PGBYTES-1));
 1849         count *= sizeof(u_int *);
 1850         cbp->cb_iovec = KVTOPHYS(cbp->cb_iovstart, u_int *);
 1851         bcopy((caddr_t)from, (caddr_t)cbp->cb_iovstart, (unsigned)count);
 1852 
 1853         dd = (up->zu_drive & 1) ? &ctlrp->zdc_chanB : &ctlrp->zdc_chanA;
 1854         if (cbp->cb_count != DEV_BSIZE) {
 1855                 cbp->cb_state |= ZD_REVECTOR;
 1856                 if (++cbp->cb_sect == dd->zdd_sectors) {
 1857                         cbp->cb_sect = 0;
 1858                         if (++cbp->cb_head == dd->zdd_tracks) {
 1859                                 cbp->cb_head = 0;
 1860                                 cbp->cb_cyl++;
 1861                         }
 1862                 }
 1863                 *(int *)&cbp->cb_contaddr = *(int *)&cbp->cb_diskaddr;
 1864                 cbp->cb_contiovsz = count;
 1865         }
 1866         cbp->cb_count = DEV_BSIZE;
 1867         cbp->cb_diskaddr = *replcmnt;
 1868         cbp->cb_psect = zdgetpsect(&cbp->cb_diskaddr, dd);
 1869 #ifdef  DEBUG
 1870         if (zddebug)
 1871                 printf(" to (%d, %d, %d).\n",
 1872                         cbp->cb_cyl, cbp->cb_head, cbp->cb_sect);
 1873 #endif  DEBUG
 1874 
 1875         /*
 1876          * Nudge controller.
 1877          */
 1878         NUDGE_ZDC(ctlrp, cbp, s_ipl);
 1879         return (1);
 1880 }
 1881 
 1882 /*
 1883  * zdcontinue
 1884  *      Continue rest of I/O request after the revectored sector.
 1885  */
 1886 zdcontinue(cbp, up, ctlrp)
 1887         register struct cb       *cbp;
 1888         struct zd_unit *up;
 1889         register struct zdc_ctlr *ctlrp;
 1890 {
 1891         u_int   *from;
 1892         spl_t   s_ipl;
 1893 
 1894         /*
 1895          * Revectoring completed successfully.
 1896          * Restart rest of I/O request.
 1897          */
 1898         cbp->cb_state &= ~ZD_REVECTOR;
 1899         cbp->cb_bp->b_resid -= DEV_BSIZE;
 1900         cbp->cb_transfrd += DEV_BSIZE;
 1901         cbp->cb_errcnt = 0;
 1902         cbp->cb_count = cbp->cb_bp->b_resid;
 1903         cbp->cb_iovec = KVTOPHYS(cbp->cb_iovstart, u_int *);
 1904         from = cbp->cb_iovstart
 1905                 + i386_btop((cbp->cb_addr & (I386_PGBYTES-1)) + DEV_BSIZE);
 1906         cbp->cb_addr += DEV_BSIZE;
 1907         if (from != cbp->cb_iovstart) {
 1908                 /*
 1909                  * Must start with next iovector.
 1910                  */
 1911                 bcopy((caddr_t)from, (caddr_t)cbp->cb_iovstart,
 1912                         (unsigned)(cbp->cb_contiovsz - sizeof(u_int *)));
 1913         }
 1914         *(int *)&cbp->cb_diskaddr = *(int *)&cbp->cb_contaddr;
 1915         cbp->cb_psect = zdgetpsect(&cbp->cb_diskaddr,
 1916                                         (up->zu_drive & 1) ? &ctlrp->zdc_chanB
 1917                                                            : &ctlrp->zdc_chanA);
 1918         /*
 1919          * Nudge controller.
 1920          */
 1921         NUDGE_ZDC(ctlrp, cbp, s_ipl);
 1922 }
 1923 
 1924 /*
 1925  * zdretry
 1926  *      Retry the request.
 1927  * If the request is a normal read/write request then retry the command
 1928  * from where the error occurred. If B_IOCTL request, retry from the
 1929  * initial CB.
 1930  */
 1931 zdretry(cbp, up, ctlrp)
 1932         register struct cb *cbp;
 1933         struct  zd_unit  *up;
 1934         struct  zdc_ctlr *ctlrp;
 1935 {
 1936         register int count;             /* # iovecs remaining */
 1937         register int transfrd;          /* # bytes transferred */
 1938         register int cbcount;
 1939         u_int   *from;                  /* 1st retry iovec */
 1940         spl_t   s_ipl;
 1941 
 1942         /*
 1943          * Retry job
 1944          */
 1945         if (cbp->cb_bp->b_flags & B_IOCTL) {
 1946                 /*
 1947                  * copy 1st half of cb (what fw will see)
 1948                  */
 1949                 bcopy((caddr_t)&up->zu_ioctlcb, (caddr_t)cbp, FWCBSIZE);
 1950         } else {
 1951                 cbp->cb_count = cbp->cb_bp->b_resid;
 1952                 cbp->cb_cmd = (cbp->cb_bp->b_flags & B_READ) ? ZDC_READ : ZDC_WRITE;
 1953                 cbp->cb_sect &= ~ZD_AUTOBIT;     /* drop Auto-revetor bit */
 1954                 cbp->cb_psect = zdgetpsect(&cbp->cb_diskaddr,
 1955                                         (up->zu_drive & 1) ? &ctlrp->zdc_chanB
 1956                                                            : &ctlrp->zdc_chanA);
 1957                 transfrd = cbp->cb_bp->b_bcount - cbp->cb_count;
 1958                 transfrd -= cbp->cb_transfrd;
 1959                 from = cbp->cb_iovstart
 1960                         + i386_btop((cbp->cb_addr & (I386_PGBYTES-1)) + transfrd);
 1961                 cbp->cb_transfrd += transfrd;
 1962                 cbp->cb_addr += transfrd;
 1963 
 1964                 /*
 1965                  * determine number of iovecs remaining.
 1966                  */
 1967                 count = 0;
 1968                 cbcount = cbp->cb_count;
 1969                 if (cbp->cb_addr & (I386_PGBYTES-1)) {
 1970                         ++count;
 1971                         cbcount -= I386_PGBYTES - (cbp->cb_addr & (I386_PGBYTES-1));
 1972                 }
 1973                 count += i386_btop(cbcount + (I386_PGBYTES-1));
 1974 
 1975                 /*
 1976                  * Copy down iovecs to 32 byte aligned boundary.
 1977                  * That is, cb_iovstart.
 1978                  */
 1979                 bcopy((caddr_t)from, (caddr_t)cbp->cb_iovstart,
 1980                         (unsigned)(count * sizeof(u_int *)));
 1981         }
 1982         cbp->cb_iovec = KVTOPHYS(cbp->cb_iovstart, u_int *);
 1983 
 1984         /*
 1985          * Nudge controller.
 1986          */
 1987         NUDGE_ZDC(ctlrp, cbp, s_ipl);
 1988 }
 1989 
 1990 /*
 1991  * zdc_cb_cleanup
 1992  *      Cleanup (cancel) jobs active on disabled controller.
 1993  * Called as timeout routine to allow completed CB's to drain.
 1994  * That is, those for which a completion interrupt was sent just
 1995  * before the error interrupt occurred.
 1996  */
 1997 zdc_cb_cleanup(ctlrp)
 1998         register struct zdc_ctlr *ctlrp;
 1999 {
 2000         register struct cb       *cbp;
 2001         register struct buf      *bp;
 2002         spl_t   s_ipl;
 2003 
 2004         /*
 2005          * Controller dead. Fail all active I/O requests.
 2006          */
 2007         cbp = ctlrp->zdc_cbp;
 2008         for (; cbp < &ctlrp->zdc_cbp[NCBPERZDC]; cbp++) {
 2009                 if (cbp->cb_bp != NULL) {
 2010                         bp = cbp->cb_bp;
 2011                         bp->b_flags |= B_ERROR;
 2012                         bp->b_error = EIO;
 2013                         bp->b_resid = bp->b_bcount;
 2014                         biodone(bp);
 2015                         bp = NULL;
 2016                         /*
 2017                          * Decrement I/O activity
 2018                          */
 2019                         if (fp_lights) {
 2020                                 s_ipl = splhi();
 2021                                 FP_IO_INACTIVE;
 2022                                 splx(s_ipl);
 2023                         }
 2024                 }
 2025         }
 2026 }
 2027 
 2028 /*
 2029  * zdc_error
 2030  *      Controller error interrupt.
 2031  */
 2032 zdc_error(vector)
 2033         u_char  vector;
 2034 {
 2035         register int    val;
 2036         register struct zdc_ctlr *ctlrp;
 2037         spl_t   s_ipl;
 2038 
 2039         ctlrp = &zdctrlr[vector - base_err_intr];
 2040         s_ipl = splhi();        /* In case zdc_err_bin not splhi() */
 2041         val = rdslave(ctlrp->zdc_slicaddr, SL_Z_STATUS);
 2042         splx(s_ipl);
 2043         if (((val & SLB_ZPARERR) != SLB_ZPARERR) &&
 2044             ((val & ZDC_READY) == ZDC_READY)) {
 2045                 printf("zdc%d - stray error interrupt!\n", ctlrp - zdctrlr);
 2046                 return;
 2047         }
 2048         printf("zdc%d: controller interrupt - SL_Z_STATUS == 0x%x.\n",
 2049                 ctlrp - zdctrlr, val);
 2050         if ((val & ZDC_ERRMASK) == ZDC_OBCB) {
 2051                 /*
 2052                  * Assume stray interrupt happened and tell fw to continue.
 2053                  */
 2054                 s_ipl = splhi();        /* in case zdc_err_bin not splhi() */
 2055                 mIntr(ctlrp->zdc_slicaddr, CLRERRBIN, 0xbb);
 2056                 splx(s_ipl);
 2057                 return;
 2058         }
 2059 
 2060         splx(SPLZD);            /* Do the rest at SPLZD */
 2061 
 2062         /*
 2063          * Fail all queued I/O requests.
 2064          */
 2065         zdshutctlr(ctlrp);
 2066 
 2067         /*
 2068          * Allow completed CBs to drain then
 2069          * fail all other "active" I/O requests.
 2070          */
 2071         timeout(zdc_cb_cleanup, (caddr_t)ctlrp, 5 * hz);
 2072 }
 2073 
 2074 /*
 2075  * zdshutctlr
 2076  *      Fail all I/O requests queued to the drives on this controller.
 2077  *      Currently active I/O requests will finish asyncronously.
 2078  *      The controller is marked as ZDC_DEAD and all units on the
 2079  *      controller are marked as ZU_BAD.
 2080  */
 2081 zdshutctlr(ctlrp)
 2082         register struct zdc_ctlr *ctlrp;
 2083 {
 2084         register struct cb *cbp;
 2085 
 2086         printf("zdc%d: Controller disabled.\n", ctlrp - zdctrlr);
 2087 
 2088         cbp = ctlrp->zdc_cbp;
 2089         for (; cbp < &ctlrp->zdc_cbp[NCBPERZDC]; cbp += NCBPERDRIVE) {
 2090                 if (cbp->cb_unit >= 0)
 2091                         zdshutdrive(&zdunit[cbp->cb_unit]);
 2092         }
 2093         ctlrp->zdc_state = ZDC_DEAD;
 2094 }
 2095 
 2096 /*
 2097  * zdshutchan
 2098  *      Fail all I/O requests queued to the drives on this channel.
 2099  *      Currently active I/O requests will finish asyncronously.
 2100  *      All units on the channel are marked as ZU_BAD.
 2101  */
 2102 zdshutchan(ctlrp, channel)
 2103         register struct zdc_ctlr *ctlrp;
 2104         int     channel;                /* 0 == Channel A, 1 == channel B */
 2105 {
 2106         register struct cb *cbp;
 2107 
 2108         printf("zdc%d: Channel %c disabled.\n", ctlrp - zdctrlr,
 2109                         (channel == 0) ? 'A' : 'B');
 2110 
 2111         cbp = &ctlrp->zdc_cbp[channel * NCBPERDRIVE];
 2112         for (; cbp < &ctlrp->zdc_cbp[NCBPERZDC]; cbp += 2 * NCBPERDRIVE) {
 2113                 if (cbp->cb_unit >= 0)
 2114                         zdshutdrive(&zdunit[cbp->cb_unit]);
 2115         }
 2116 }
 2117 
 2118 /*
 2119  * zdshutdrive
 2120  *      Fail all I/O requests queued to the drive.
 2121  *      Currently active I/O requests will finish asyncronously.
 2122  *      The drive is marked as ZU_BAD.
 2123  */
 2124 zdshutdrive(up)
 2125         register struct zd_unit *up;
 2126 {
 2127         register struct buf     *bp, *nextbp;
 2128         spl_t   s_ipl;
 2129 
 2130         /*
 2131          * Lock the device and fail all jobs currently queued.
 2132          */
 2133         s_ipl = p_lock(&up->zu_lock, SPLZD);
 2134         if (up->zu_state == ZU_BAD) {
 2135                 v_lock(&up->zu_lock, s_ipl);
 2136                 return;
 2137         }
 2138         printf("zd%d: Drive disabled.\n", up - zdunit);
 2139         bp = up->zu_bhead.av_forw;
 2140         while (bp != NULL) {
 2141                 bp->b_flags |= B_ERROR;
 2142                 bp->b_error = EIO;
 2143                 bp->b_resid = bp->b_bcount;
 2144                 nextbp = bp->av_forw;
 2145                 biodone(bp);
 2146                 bp = nextbp;
 2147         }
 2148         up->zu_bhead.av_forw = NULL;
 2149         up->zu_state = ZU_BAD;
 2150         v_lock(&up->zu_lock, s_ipl);
 2151         /*
 2152          * Turn on error light on front panel.
 2153          */
 2154         if (fp_lights) {
 2155                 s_ipl = splhi();
 2156                 FP_IO_ERROR;
 2157                 splx(s_ipl);
 2158         }
 2159         /*
 2160          * It had been online and usable.
 2161          */
 2162         disk_offline();
 2163 }
 2164 
 2165 /*
 2166  * zdminphys - correct for too large a request.
 2167  *
 2168  * Note correction for non-cluster-aligned transfers.
 2169  */
 2170 zdminphys(bp)
 2171         struct buf *bp;
 2172 {
 2173         if (bp->b_bcount > ((zdc_iovpercb - 1) * I386_PGBYTES))
 2174                 bp->b_bcount = (zdc_iovpercb - 1) * I386_PGBYTES;
 2175 }
 2176 
 2177 zdread(dev, uio)
 2178         dev_t   dev;
 2179         struct uio *uio;
 2180 {
 2181 #ifndef MACH
 2182         int err, diff;
 2183         off_t lim;
 2184 
 2185         lim = zdparts[zdunit[ZDUNIT(dev)].zu_drive_type][ZDPART(dev)].p_length;
 2186         lim = dbtob(lim);
 2187         err = physck(lim, uio, B_READ, &diff);
 2188         if (err != 0) {
 2189                 if (err == -1)  /* not an error, but request of 0 bytes */
 2190                         err = 0;
 2191                 return (err);
 2192         }
 2193         err = physio(zdstrat, (struct buf *)0, dev, B_READ, zdminphys, uio);
 2194         uio->uio_resid += diff;
 2195         return (err);
 2196 #else   MACH
 2197         return physio(zdstrat, &zdbuf, dev, B_READ, zdminphys, uio);
 2198 #endif  MACH
 2199 }
 2200 
 2201 zdwrite(dev, uio)
 2202         dev_t   dev;
 2203         struct uio *uio;
 2204 {
 2205 #ifndef MACH
 2206         int err, diff;
 2207         off_t lim;
 2208 
 2209         lim = zdparts[zdunit[ZDUNIT(dev)].zu_drive_type][ZDPART(dev)].p_length;
 2210         lim = dbtob(lim);
 2211         err = physck(lim, uio, B_WRITE, &diff);
 2212         if (err != 0) {
 2213                 if (err == -1)  /* not an error, but request of 0 bytes */
 2214                         err = 0;
 2215                 return (err);
 2216         }
 2217         err = physio(zdstrat, (struct buf *)0, dev, B_WRITE, zdminphys, uio);
 2218         uio->uio_resid += diff;
 2219         return (err);
 2220 #else   MACH
 2221         return physio(zdstrat, &zdbuf, dev, B_WRITE, zdminphys, uio);
 2222 #endif  MACH
 2223 }
 2224 
 2225 /*
 2226  * zdioctl
 2227  *      Currently the only ZIOCBCMDs that are supported are ZDC_READ_LRAM and
 2228  *      ZDC_WRITE_LRAM. The ioctl mechanism could be used to support
 2229  *      more functions to facilitate online formatting.
 2230  */
 2231 /*ARGSUSED*/
 2232 zdioctl(dev, cmd, data, flag)
 2233         dev_t   dev;
 2234         int     cmd;
 2235         caddr_t data;
 2236         int     flag;
 2237 {
 2238 #ifndef MACH
 2239         register struct cb *cbp;        /* cb argument */
 2240         register struct buf *bp;        /* ioctl buffer */
 2241         register struct zd_unit *up;    /* unit structure */
 2242         int     error;
 2243         spl_t   s_ipl;
 2244 
 2245         up = &zdunit[ZDUNIT(dev)];
 2246         bp = &up->zu_ioctl;
 2247 
 2248         switch(cmd) {
 2249 
 2250         case ZIOCBCMD:
 2251                 cbp = (struct cb *)data;
 2252                 switch(cbp->cb_cmd) {
 2253 
 2254                 case ZDC_GET_CHANCFG:
 2255                         if (cbp->cb_count != sizeof(struct zdcdd) ||
 2256                             (cbp->cb_addr & (ADDRALIGN-1)) != 0)
 2257                                 return (EINVAL);
 2258                         if (!useracc((char *)cbp->cb_addr,
 2259                                                 (u_int)cbp->cb_count, B_WRITE))
 2260                                 return (EFAULT);
 2261                         bufalloc(bp);
 2262                         bp->b_flags = B_READ;
 2263                         bp->b_bcount = cbp->cb_count;
 2264                         bp->b_un.b_addr = (caddr_t)cbp->cb_addr;
 2265                         break;
 2266 
 2267                 case ZDC_READ_SS:
 2268                         if (cbp->cb_count != ZDD_SS_SIZE ||
 2269                             (cbp->cb_addr & (ADDRALIGN-1)) != 0 ||
 2270                             cbp->cb_diskaddr.da_cyl != 0 ||
 2271                             cbp->cb_diskaddr.da_head != 0 ||
 2272                             cbp->cb_diskaddr.da_sect >= ZDD_NDDSECTORS)
 2273                                 return (EINVAL);
 2274                         if (!useracc((char *)cbp->cb_addr,
 2275                                                 (u_int)cbp->cb_count, B_WRITE))
 2276                                 return (EFAULT);
 2277                         bufalloc(bp);
 2278                         bp->b_flags = B_READ;
 2279                         bp->b_bcount = cbp->cb_count;
 2280                         bp->b_un.b_addr = (caddr_t)cbp->cb_addr;
 2281                         break;
 2282 
 2283                 case ZDC_WRITE_LRAM:
 2284                         if (!suser())
 2285                                 return (EPERM);
 2286                         /* Fall into */
 2287                 case ZDC_READ_LRAM:
 2288                         /*
 2289                          * Check if LRAM address reasonable.
 2290                          */
 2291                         if (cbp->cb_addr >= (ZDC_LRAMSZ / sizeof(int)))
 2292                                 return (EINVAL);
 2293                         bufalloc(bp);
 2294                         bp->b_flags = (cbp->cb_cmd == ZDC_READ_LRAM) ? B_READ
 2295                                                                      : B_WRITE;
 2296                         bp->b_bcount = 0;               /* data in CB */
 2297                         bp->b_un.b_addr = NULL;
 2298                         break;
 2299 
 2300                 default:
 2301                         return (EINVAL);
 2302                 }
 2303 
 2304                 /*
 2305                  * Do ioctl.
 2306                  */
 2307                 bcopy((caddr_t)cbp, (caddr_t)&up->zu_ioctlcb, FWCBSIZE);
 2308                 bp->b_flags |= B_IOCTL;
 2309                 bp->b_dev = dev;
 2310                 bp->b_blkno = 0;
 2311                 bp->b_error = 0;
 2312                 bp->b_proc = u.u_procp;
 2313                 bp->b_iotype = B_RAWIO;
 2314                 BIODONE(bp) = 0;
 2315                 ++u.u_procp->p_noswap;
 2316                 if (bp->b_bcount > 0) {
 2317                         /*
 2318                          * lock down pages
 2319                          */
 2320                         vslock(bp->b_un.b_addr, (int)bp->b_bcount,
 2321                                 (bool_t)(bp->b_flags & B_READ));
 2322                 }
 2323                 s_ipl = p_lock(&up->zu_lock, SPLZD);
 2324                 if (up->zu_state == ZU_BAD) {
 2325                         v_lock(&up->zu_lock, s_ipl);
 2326                         /*
 2327                          * Controller/channel/Drive has gone bad!
 2328                          */
 2329                         buffree(bp);
 2330                         --u.u_procp->p_noswap;
 2331                         return (EIO);
 2332                 }
 2333                 /*
 2334                  * Insert at head of list and zdstart!
 2335                  */
 2336                 bp->av_forw = up->zu_bhead.av_forw;
 2337                 up->zu_bhead.av_forw = bp;
 2338                 zdstart(up);
 2339                 v_lock(&up->zu_lock, s_ipl);
 2340                 biowait(bp);
 2341                 --u.u_procp->p_noswap;                  /* re-swappable */
 2342                 error = geterror(bp);
 2343                 bcopy((caddr_t)&up->zu_ioctlcb, (caddr_t)cbp, FWCBSIZE);
 2344                 buffree(bp);
 2345                 return (error);
 2346 
 2347         default:
 2348                 return (EINVAL);
 2349         }
 2350 #else   MACH
 2351         return EINVAL;
 2352 #endif  MACH
 2353 }
 2354 
 2355 #ifdef  MACH_KERNEL
 2356 /*
 2357  * Get status routine
 2358  */
 2359 zdgetstat(dev, flavor, status, count)
 2360         dev_t   dev;
 2361         int     *status, *count;
 2362 {
 2363         if (flavor == DEV_GET_SIZE) {
 2364                 unsigned int    length;
 2365 
 2366                 length = zdparts[
 2367                            zdunit[ ZDUNIT(dev) ].zu_drive_type
 2368                          ] [ ZDPART(dev) ].p_length;
 2369                 status[DEV_GET_SIZE_DEVICE_SIZE] = length * DEV_BSIZE;
 2370                 status[DEV_GET_SIZE_RECORD_SIZE] = DEV_BSIZE;
 2371                 *count = DEV_GET_SIZE_COUNT;
 2372                 
 2373                 return D_SUCCESS;
 2374         } else return D_INVALID_OPERATION;
 2375 }
 2376 #endif  /*MACH_KERNEL*/
 2377 
 2378 /*
 2379  *      Routine to return information to kernel.
 2380  */
 2381 int
 2382 zd_devinfo(dev, flavor, info)
 2383         int     dev;
 2384         int     flavor;
 2385         char    *info;
 2386 {
 2387         register int    result;
 2388 
 2389         result = D_SUCCESS;
 2390 
 2391         switch (flavor) {
 2392         case D_INFO_BLOCK_SIZE:
 2393                 *((int *) info) = DEV_BSIZE;
 2394                 break;
 2395         default:
 2396                 result = D_INVALID_OPERATION;
 2397         }
 2398 
 2399         return(result);
 2400 }
 2401 
 2402 /*
 2403  * zdsize()
 2404  *      Used for swap-space partition calculation.
 2405  */
 2406 zdsize(dev)
 2407         register dev_t dev;
 2408 {
 2409         register struct zd_unit *up;
 2410 
 2411         up = &zdunit[ZDUNIT(dev)];
 2412 
 2413         if (ZDUNIT(dev) >= zdc_conf->zc_nent
 2414         ||  up->zu_state != ZU_GOOD
 2415         ||  ((up->zu_cfg & (ZD_FORMATTED|ZD_MATCH)) != (ZD_FORMATTED|ZD_MATCH))
 2416         ||  zdparts[up->zu_drive_type][ZDPART(dev)].p_length == 0)
 2417                         return (-1);
 2418         return (zdparts[up->zu_drive_type][ZDPART(dev)].p_length);
 2419 }
 2420 
 2421 /*
 2422  * Print out status bytes when appropriate.
 2423  */
 2424 zddumpstatus(cbp)
 2425         register struct cb *cbp;
 2426 {
 2427         register int i;
 2428 
 2429         if (cbp->cb_cmd == ZDC_INIT || cbp->cb_cmd == ZDC_PROBE ||
 2430             cbp->cb_cmd == ZDC_PROBEDRIVE)
 2431                 return;
 2432 
 2433         switch(cbp->cb_compcode) {
 2434 
 2435         case ZDC_DRVPROT:
 2436         case ZDC_DRVFLT:
 2437         case ZDC_SEEKERR:
 2438         case ZDC_HDR_ECC:
 2439         case ZDC_SOFTECC:
 2440         case ZDC_CORRECC:
 2441         case ZDC_ECC:
 2442         case ZDC_SNF:
 2443         case ZDC_REVECT:
 2444         case ZDC_SO:
 2445         case ZDC_NDS:
 2446         case ZDC_FDL:
 2447         case ZDC_DDC_STAT:
 2448                 break;
 2449 
 2450         default:
 2451                 if (cbp->cb_cmd == ZDC_READ_LRAM || cbp->cb_cmd == ZDC_WRITE_LRAM)
 2452                         break;
 2453                 return;
 2454         }
 2455         if (cbp->cb_bp != NULL)
 2456                 printf("zd%d%c: cb_status:", cbp->cb_unit,
 2457                         PARTCHR(cbp->cb_bp->b_dev));
 2458         else
 2459                 printf("zd%d: cbstatus:", cbp->cb_unit);
 2460         for (i=0; i < NSTATBYTES; i++)
 2461                 printf(" 0x%x", cbp->cb_status[i]);
 2462         printf("\n");
 2463 }
 2464 
 2465 #ifdef  DEBUG
 2466 /*
 2467  * Print out the contents of a cb.
 2468  */
 2469 zddumpcb(cbp)
 2470         register struct cb *cbp;
 2471 {
 2472         register struct init_cb *icbp;
 2473         register int i;
 2474         register int count;
 2475         int     cbcount;
 2476 
 2477         printf("zd%d: cb at 0x%x, cb_cmd 0x%x, cb_compcode 0x%x\n",
 2478                 cbp->cb_unit, cbp, cbp->cb_cmd, cbp->cb_compcode);
 2479         if (cbp->cb_cmd == ZDC_INIT) {
 2480                 icbp = (struct init_cb *)cbp;
 2481                 printf("icb_ctrl 0x%x, icb_pagesize 0x%x, icb_dumpaddr 0x%x\n",
 2482                         icbp->icb_ctrl, icbp->icb_pagesize, icbp->icb_dumpaddr);
 2483                 printf("icb_dest 0x%x, icb_bin 0x%x, icb_vecbase 0x%x\n",
 2484                         icbp->icb_dest, icbp->icb_bin, icbp->icb_vecbase);
 2485                 printf("icb_errdest 0x%x, icb_errbin 0x%x, icb_errvector 0x%x\n\n",
 2486                         icbp->icb_errdest, icbp->icb_errbin,
 2487                         icbp->icb_errvector);
 2488                 return;
 2489         }
 2490         if (cbp->cb_cmd == ZDC_PROBE || cbp->cb_cmd == ZDC_PROBEDRIVE) {
 2491                 printf("pcb_drivecfg:");
 2492                 for (i = 0; i < ZDC_MAXDRIVES; i++)
 2493                         printf(" 0x%x",
 2494                                  ((struct probe_cb *)cbp)->pcb_drivecfg[i]);
 2495                 printf("\n\n");
 2496                 return;
 2497         }
 2498         printf("cb_mod 0x%x, cb_diskaddr (%d, %d, %d), cb_psect 0x%x\n",
 2499                 cbp->cb_mod, cbp->cb_cyl, cbp->cb_head, cbp->cb_sect,
 2500                 cbp->cb_psect);
 2501         printf("cb_addr 0x%x, cb_count 0x%x, cb_iovec 0x%x, cb_reqstat 0x%x\n",
 2502                 cbp->cb_addr, cbp->cb_count, cbp->cb_iovec, cbp->cb_reqstat);
 2503         zddumpstatus(cbp);
 2504         printf("cb_bp 0x%x, cb_errcnt 0x%x, cb_iovstart 0x%x, cb_state 0x%x\n",
 2505                 cbp->cb_bp, cbp->cb_errcnt, cbp->cb_iovstart, cbp->cb_state);
 2506         printf("cb_contaddr 0x%x, cb_contiovsz 0x%x, cb_transfrd 0x%x\n",
 2507                 cbp->cb_contaddr, cbp->cb_contiovsz, cbp->cb_transfrd);
 2508         if (cbp->cb_iovec != NULL) {
 2509                 count = 0;
 2510                 cbcount = cbp->cb_count;
 2511 #ifdef  MACH_KERNEL
 2512                 if (cbp->cb_addr != trunc_page(cbp->cb_addr)) {
 2513                         ++count;
 2514                         cbcount -= PAGE_SIZE -
 2515                                    (cbp->cb_addr - trunc_page(cbp->cb_addr));
 2516                 }
 2517                 count += atop(round_page(cbcount));
 2518 #else   /* MACH_KERNEL */
 2519                 if (cbp->cb_addr & CLOFSET) {
 2520                         ++count;
 2521                         cbcount -= CLBYTES - (cbp->cb_addr & CLOFSET);
 2522                 }
 2523                 count += (cbcount + CLOFSET) >> CLSHIFT;
 2524 #endif  /* MACH_KERNEL */
 2525                 printf("iovecs:");
 2526                 for (i = 0; i < count; i++) {
 2527                         printf(" 0x%x", cbp->cb_iovstart[i]);
 2528                         if ((i % 8) == 7)
 2529                                 printf("\n\t");
 2530                 }
 2531                 printf("\n");
 2532         }
 2533         printf("\n");
 2534 }
 2535 #endif  DEBUG

Cache object: ca78b3c2a0bb68b3329056ee180d3f80


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