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/i386at/hd.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) 1993,1991,1990,1989 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        hd.c,v $
   29  * Revision 2.23  93/08/10  15:57:25  mrt
   30  *      We now use bsd labels internally and convert from "local labels"
   31  *      if we find them on the disk. 
   32  *      [93/08/03  20:36:05  rvb]
   33  * 
   34  *      Fix DIOCxxx ioctls to deal with MAXPARTITION or MAXPARTITION+1
   35  *      parititions.  We'll do this better next release.        
   36  * 
   37  * Revision 2.22  93/05/10  20:03:39  rvb
   38  *      Types.
   39  *      [93/05/08  11:17:48  af]
   40  * 
   41  * Revision 2.21  93/03/11  13:58:01  danner
   42  *      u_long -> u_int.
   43  *      [93/03/09            danner]
   44  * 
   45  * Revision 2.20  93/01/24  13:15:53  danner
   46  *      Deal with DPT WD1003 emulation that clears BUSY before READY is
   47  *      set.
   48  *      [92/10/01            rvb]
   49  * 
   50  * Revision 2.19  93/01/14  17:30:21  danner
   51  *      Proper spl typing.
   52  *      [92/11/30            af]
   53  * 
   54  * Revision 2.18  92/07/09  22:54:06  rvb
   55  *      Transcription error missed a line.
   56  *      [92/06/23  11:16:20  rvb]
   57  * 
   58  *      Setcontroller should be called synchronously with hd_start().  So
   59  *      that the controller is idle.
   60  *      [92/06/20            rvb]
   61  * 
   62  *      Defer setcontroller(unit) to getvtoc();  So we only setcontroller()
   63  *      what we open, not what we probe.  ESDI+SCSI messes up the device
   64  *      count.
   65  *      [92/06/18            rvb]
   66  * 
   67  * Revision 2.17  92/03/01  00:39:53  rpd
   68  *      Cleaned up syntactically incorrect ifdefs.
   69  *      [92/02/29            rpd]
   70  * 
   71  * Revision 2.16  92/02/23  22:43:07  elf
   72  *      Added (mandatory) DEV_GET_SIZE flavor of get_status.
   73  *      [92/02/22            af]
   74  * 
   75  * Revision 2.15  92/02/19  16:29:51  elf
   76  *      On 25-Jan, did not consider NO ACTIVE mach parition.
   77  *      Add "BIOS" support -- always boot mach partition NOT active one.
   78  *      [92/01/31            rvb]
   79  * 
   80  * Revision 2.14  92/01/27  16:43:06  rpd
   81  *      Fixed hdgetstat and hdsetstat to return D_INVALID_OPERATION
   82  *      for unsupported flavors.
   83  *      [92/01/26            rpd]
   84  * 
   85  * Revision 2.13  92/01/14  16:43:51  rpd
   86  *      Error in badblock_mapping code in the case there was sector replacement.
   87  *      For all the sectors in the disk block before the bad sector, you
   88  *      badblock_mapping should give the identity map and it was not.
   89  *      [92/01/08            rvb]
   90  * 
   91  * Revision 2.12  91/11/18  17:34:19  rvb
   92  *      For now, back out the hdprobe(), hdslave() probes and use
   93  *      the old simple test and believe BIOS.
   94  * 
   95  * Revision 2.11  91/11/12  11:09:32  rvb
   96  *      Amazing how hard getting the probe to work for all machines is.
   97  *      V_REMOUNT must clear gotvtoc[].
   98  *      [91/10/16            rvb]
   99  * 
  100  * Revision 2.10  91/10/07  17:25:35  af
  101  *      Now works with 2 disk drives, new probe/slave routines, misc cleanup
  102  *      [91/08/07            mg32]
  103  * 
  104  *      From 2.5:
  105  *      Rationalize p_flag
  106  *      Kill nuisance print out.
  107  *      Removed "hdioctl(): do not recognize ioctl ..." printf().
  108  *      [91/08/07            rvb]
  109  * 
  110  * Revision 2.9  91/08/28  11:11:42  jsb
  111  *      Replace hdbsize with hddevinfo.
  112  *      [91/08/12  17:33:59  dlb]
  113  * 
  114  *      Add block size routine.
  115  *      [91/08/05  17:39:16  dlb]
  116  * 
  117  * Revision 2.8  91/08/24  11:57:46  af
  118  *      New MI autoconf.
  119  *      [91/08/02  02:52:47  af]
  120  * 
  121  * Revision 2.7  91/05/14  16:23:24  mrt
  122  *      Correcting copyright
  123  * 
  124  * Revision 2.6  91/02/05  17:17:01  mrt
  125  *      Changed to new Mach copyright
  126  *      [91/02/01  17:43:01  mrt]
  127  * 
  128  * Revision 2.5  91/01/08  17:32:51  rpd
  129  *      Allow ioctl's
  130  *      [90/12/19            rvb]
  131  * 
  132  * Revision 2.4  90/11/26  14:49:37  rvb
  133  *      jsb bet me to XMK34, sigh ...
  134  *      [90/11/26            rvb]
  135  *      Synched 2.5 & 3.0 at I386q (r1.8.1.15) & XMK35 (r2.4)
  136  *      [90/11/15            rvb]
  137  * 
  138  * Revision 1.8.1.14  90/09/18  08:38:49  rvb
  139  *      Typo & vs && at line 592.               [contrib]
  140  *      Make Status printout on error only conditional on hd_print_error.
  141  *      So we can get printout during clobber_my_disk.
  142  *      [90/09/08            rvb]
  143  * 
  144  * Revision 1.8.1.13  90/08/25  15:44:38  rvb
  145  *      Use take_<>_irq() vs direct manipulations of ivect and friends.
  146  *      [90/08/20            rvb]
  147  * 
  148  * Revision 1.8.1.12  90/07/27  11:25:30  rvb
  149  *      Fix Intel Copyright as per B. Davies authorization.
  150  *      Let anyone who as opened the disk do absolute io.
  151  *      [90/07/27            rvb]
  152  * 
  153  * Revision 1.8.1.11  90/07/10  11:43:22  rvb
  154  *      Unbelievable bug in setcontroller.
  155  *      New style probe/slave/attach.
  156  *      [90/06/15            rvb]
  157  * 
  158  * Revision 1.8.1.10  90/03/29  19:00:00  rvb
  159  *      Conditionally, print out state info for "state error".
  160  *      [90/03/26            rvb]
  161  * 
  162  * Revision 1.8.1.8  90/03/10  00:27:20  rvb
  163  *      Fence post error iff (bp->b_blkno + hh.blocktotal ) > partition_p->p_size)
  164  *      [90/03/10            rvb]
  165  * 
  166  * Revision 1.8.1.7  90/02/28  15:49:35  rvb
  167  *      Fix numerous typo's in Olivetti disclaimer.
  168  *      [90/02/28            rvb]
  169  * 
  170  * Revision 1.8.1.6  90/01/16  15:54:14  rvb
  171  *      FLush pdinfo/vtoc -> evtoc
  172  *      [90/01/16            rvb]
  173  * 
  174  *      Must be able to return "dos{cyl,head,sector}"
  175  *      [90/01/12            rvb]
  176  * 
  177  *      Be careful about p_size bound's checks if B_MD1 is true.
  178  *      [90/01/12            rvb]
  179  * 
  180  * Revision 1.8.1.5  90/01/08  13:29:29  rvb
  181  *      Add Intel copyright.
  182  *      Add Olivetti copyright.
  183  *      [90/01/08            rvb]
  184  * 
  185  *      It is no longer possible to set the start and size of disk
  186  *      partition "PART_DISK" -- it is always loaded from the DOS
  187  *      partition data.
  188  *      [90/01/08            rvb]
  189  * 
  190  * Revision 1.8.1.4  90/01/02  13:54:58  rvb
  191  *      Temporarily regress driver to one that is known to work with Vectra's.
  192  * 
  193  */
  194  
  195  
  196 /*
  197   Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
  198 
  199                 All Rights Reserved
  200 
  201 Permission to use, copy, modify, and distribute this software and
  202 its documentation for any purpose and without fee is hereby
  203 granted, provided that the above copyright notice appears in all
  204 copies and that both the copyright notice and this permission notice
  205 appear in supporting documentation, and that the name of Intel
  206 not be used in advertising or publicity pertaining to distribution
  207 of the software without specific, written prior permission.
  208 
  209 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
  210 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  211 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
  212 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  213 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
  214 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  215 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  216 */
  217 
  218 /*
  219  *  AT Hard Disk Driver
  220  *  Copyright Ing. C. Olivetti & S.p.A. 1989
  221  *  All rights reserved.
  222  *
  223  */
  224 /*
  225   Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
  226 Cupertino, California.
  227 
  228                 All Rights Reserved
  229 
  230   Permission to use, copy, modify, and distribute this software and
  231 its documentation for any purpose and without fee is hereby
  232 granted, provided that the above copyright notice appears in all
  233 copies and that both the copyright notice and this permission notice
  234 appear in supporting documentation, and that the name of Olivetti
  235 not be used in advertising or publicity pertaining to distribution
  236 of the software without specific, written prior permission.
  237 
  238   OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
  239 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  240 IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
  241 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  242 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
  243 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
  244 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  245 */
  246 
  247 #include <hd.h>
  248 
  249 #include <sys/types.h>
  250 #ifdef  MACH_KERNEL
  251 #define PRIBIO 20
  252 #include <device/buf.h>
  253 #include <device/errno.h>
  254 #include <device/device_types.h>
  255 #include <device/disk_status.h>
  256 #else   MACH_KERNEL
  257 #include <sys/buf.h>
  258 #include <sys/user.h> 
  259 #endif  MACH_KERNEL
  260 #include <sys/ioctl.h>
  261 #include <i386/pio.h>
  262 #include <i386/ipl.h>
  263 #include <i386at/disk.h>
  264 #include <chips/busses.h>
  265 #include <i386at/hdreg.h>
  266 
  267 #define LABEL_DEBUG(x,y) if (label_flag&x) y
  268 
  269 /* From sys/systm.h */
  270 struct buf *geteblk();
  271 
  272 #define b_cylin         b_resid
  273 #define PAGESIZ 4096
  274 
  275 int devaddr[NHD/2];
  276 int hdalive[NHD];
  277 int hdgotvtoc[NHD];
  278 struct hh hh[NHD/2];
  279 struct alt_info alt_info[NHD];
  280 struct buf hdbuf[NHD], hdunit[NHD];
  281 
  282 int need_set_controller[NHD/2];
  283 
  284 struct disklabel label[NHD];
  285 int        labeloffset[NHD];
  286 int        labelsector[NHD];
  287 
  288 struct hd_param {
  289         unsigned short  ncyl;
  290         unsigned short  nheads;
  291         unsigned short  precomp;
  292         unsigned short  nsec;
  293 }               dosparm[NHD];
  294 
  295 int hdstrategy(), hdminphys(), hdprobe(), hdslave(), hdintr();
  296 void hdattach();
  297 struct bus_device *hdinfo[NHD];
  298 
  299 vm_offset_t     hd_std[NHD] = { 0 };
  300 struct  bus_device *hd_dinfo[NHD*NDRIVES];
  301 struct  bus_ctlr *hd_minfo[NHD];
  302 struct  bus_driver      hddriver = {
  303         hdprobe, hdslave, hdattach, 0, hd_std, "hd", hd_dinfo, "hdc", hd_minfo, 0};
  304 
  305 
  306 hdprobe(port, ctlr)
  307 struct bus_ctlr *ctlr;
  308 {
  309         int     i,
  310                 ctrl = ctlr->unit;
  311         int     addr = devaddr[ctrl] = (int)ctlr->address;
  312 
  313         outb(PORT_DRIVE_HEADREGISTER(addr),0);
  314         outb(PORT_COMMAND(addr),CMD_RESTORE);
  315         for (i=500000; i && inb(PORT_STATUS(addr))&STAT_BUSY; i--);
  316         for (; i; i--) {
  317                 if (inb(PORT_STATUS(addr))&STAT_READY) {
  318                         take_ctlr_irq(ctlr);
  319                         hh[ctrl].curdrive = ctrl<<1;
  320                         printf("%s%d: port = %x, spl = %d, pic = %d.\n", ctlr->name,
  321                                 ctlr->unit, ctlr->address, ctlr->sysdep, ctlr->sysdep1);
  322 #if     0
  323                         /* may be necesary for two controllers */
  324                         outb(FIXED_DISK_REG(ctrl), 4);
  325                         for(i = 0; i < 10000; i++);
  326                         outb(FIXED_DISK_REG(ctrl), 0);
  327 #endif
  328                         return(1);
  329                 }
  330         }
  331         return(0);
  332 }
  333 
  334 /*
  335  * hdslave:
  336  *
  337  *      Actually should be thought of as a slave probe.
  338  *
  339  */
  340 
  341 hdslave(dev, xxx)
  342 struct bus_device *dev;
  343 {
  344         int     i, j,
  345                 addr = devaddr[dev->ctlr];
  346         u_char  *bios_magic = (u_char *)(0xc0000475);
  347 
  348         if (dev->ctlr == 0)                             /* for now: believe DOS */
  349                 if (*bios_magic >= 1 + dev->slave)
  350                         return 1;
  351                 else
  352                         return 0;
  353         else
  354                 return 1;
  355                 
  356 #if     0
  357         /* it is working on all types of PCs */
  358         outb(PORT_DRIVE_HEADREGISTER(addr),dev->slave<<4);
  359         outb(PORT_COMMAND(addr),CMD_RESTORE);
  360 
  361         for (i=350000; i && (j = inb(PORT_STATUS(addr)))&STAT_BUSY; i--);
  362         for (j = 0; i && !(j & STAT_READY); i--)
  363                 j = inb(PORT_STATUS(addr));
  364         if (i == 0) {
  365                 outb(FIXED_DISK_REG(dev->ctlr), 4);
  366                 for(i = 0; i < 10000; i++);
  367                 outb(FIXED_DISK_REG(dev->ctlr), 0);
  368                 setcontroller(dev->slave);
  369                 return 0;
  370         }
  371         return(j&STAT_READY);
  372 #endif
  373 }
  374 
  375 /*
  376  * hdattach:
  377  *
  378  *      Attach the drive unit that has been successfully probed.  For the
  379  *      AT ESDI drives we will initialize all driver specific structures
  380  *      and complete the controller attach of the drive.
  381  *
  382  */
  383 
  384 void hdattach(dev)
  385 struct bus_device *dev;
  386 {
  387         int                     unit = dev->unit;
  388         struct disklabel        *lp = &label[unit];
  389         u_int                   n;
  390         u_char                  *tbl;
  391 
  392         hdalive[unit] = 1;
  393         n = *(unsigned long *)phystokv(dev->address);
  394         tbl = (unsigned char *)phystokv((n&0xffff) + ((n>>12)&0xffff0));
  395         dosparm[unit].ncyl      = *(unsigned short *)tbl;
  396         dosparm[unit].nheads    = *(unsigned char  *)(tbl+2);
  397         dosparm[unit].precomp   = *(unsigned short *)(tbl+5);
  398         dosparm[unit].nsec      = *(unsigned char  *)(tbl+14);
  399         printf(", stat = %x, spl = %d, pic = %d\n",
  400                 dev->address, dev->sysdep, dev->sysdep1);
  401 
  402         /*
  403          * copy initial parameters into label
  404          */
  405         fudge_bsd_label(lp, DTYPE_ESDI, dosparm[unit].ncyl, dosparm[unit].nheads,
  406                         dosparm[unit].nsec, 2);
  407 
  408         if (unit<2)
  409                 printf(" hd%d:   %dMeg, cyls %d, heads %d, secs %d, precomp %d",
  410                         unit, lp->d_secperunit * 512/1000000,
  411                         lp->d_ncylinders, lp->d_ntracks, lp->d_nsectors,
  412                         dosparm[unit].precomp);
  413         else
  414                 printf("hd%d:   Capacity not available through bios\n",unit);
  415 }
  416 
  417 hdopen(dev, flags)
  418 {
  419         u_char  unit = UNIT(dev),
  420                 part = PARTITION(dev);
  421 
  422         if (!hdalive[unit] || part >= MAXPARTITIONS)
  423                 return(ENXIO);
  424         getvtoc(unit);
  425         if (!(label[unit].d_partitions[part].p_offset) &&
  426             !(label[unit].d_partitions[part].p_size))
  427                 return(ENXIO);
  428         return(0);
  429 }
  430 
  431 hdclose(dev)
  432 {
  433         return D_SUCCESS;
  434 }
  435 
  436 #ifdef  MACH_KERNEL
  437 /*
  438  *      No need to limit IO size to 4096 bytes.
  439  */
  440 int hdread(dev, ior)
  441 dev_t dev;
  442 io_req_t ior;
  443 {
  444         return (block_io(hdstrategy, minphys, ior));
  445 }
  446 
  447 int hdwrite(dev, ior)
  448 dev_t dev;
  449 io_req_t ior;
  450 {
  451         return (block_io(hdstrategy, minphys, ior));
  452 }
  453 #else   MACH_KERNEL
  454 hdminphys(bp)
  455 struct buf *bp;
  456 {
  457         if (bp->b_bcount > PAGESIZ)
  458                 bp->b_bcount = PAGESIZ;
  459 }
  460 
  461 hdread(dev,uio)
  462 dev_t dev;
  463 struct uio *uio;
  464 {
  465         return(physio(hdstrategy,&hdbuf[UNIT(dev)],dev,B_READ,hdminphys,uio));
  466 }
  467 
  468 hdwrite(dev,uio)
  469 dev_t dev;
  470 struct uio *uio;
  471 {
  472         return(physio(hdstrategy,&hdbuf[UNIT(dev)],dev,B_WRITE,hdminphys,uio));
  473 }
  474 #endif  MACH_KERNEL
  475 
  476 #ifdef  MACH_KERNEL
  477 int abs_sec   = -1;
  478 int abs_count = -1;
  479 /* IOC_OUT only and not IOC_INOUT */
  480 io_return_t hdgetstat(dev, flavor, data, count)
  481         dev_t dev;
  482         int flavor;
  483         int *data;              /* pointer to OUT array */
  484         unsigned int *count;    /* OUT */
  485 {
  486         int                     unit = UNIT(dev);
  487         struct disklabel        *lp = &label[unit];
  488         struct buf              *bp1;
  489         int                     i;
  490 
  491         switch (flavor) {
  492 
  493         /* Mandatory flavors */
  494 
  495         case DEV_GET_SIZE: {
  496                 int part = PARTITION(dev);
  497                 data[DEV_GET_SIZE_DEVICE_SIZE] = lp->d_partitions[part].p_size * lp->d_secsize;
  498                 data[DEV_GET_SIZE_RECORD_SIZE] = lp->d_secsize;
  499                 *count = DEV_GET_SIZE_COUNT;
  500                 break;
  501         }
  502 
  503         /* BsdLabel flavors */
  504         case DIOCGDINFO:
  505         case DIOCGDINFO - (0x10<<16):
  506                 dkgetlabel(lp, flavor, data, count);
  507                 break;
  508 
  509         /* Extra flavors */
  510         case V_GETPARMS: {
  511                 struct disk_parms *dp;
  512                 int part = PARTITION(dev);
  513                 if (*count < sizeof (struct disk_parms)/sizeof(int))
  514                         return (D_INVALID_OPERATION);
  515                 dp = (struct disk_parms *) data;
  516                 dp->dp_type = DPT_WINI;
  517                 dp->dp_heads =  lp->d_ntracks;
  518                 dp->dp_cyls =   lp->d_ncylinders;
  519                 dp->dp_sectors  = lp->d_nsectors;
  520                 dp->dp_dosheads = dosparm[unit].nheads;
  521                 dp->dp_doscyls = dosparm[unit].ncyl;
  522                 dp->dp_dossectors  = dosparm[unit].nsec;
  523                 dp->dp_secsiz = lp->d_secsize;
  524                 dp->dp_ptag = 0;
  525                 dp->dp_pflag = 0;
  526                 dp->dp_pstartsec = lp->d_partitions[part].p_offset;
  527                 dp->dp_pnumsec = lp->d_partitions[part].p_size;
  528                 *count = sizeof(struct disk_parms)/sizeof(int);
  529                 break;
  530         }
  531         case V_RDABS: {
  532                 /* V_RDABS is relative to head 0, sector 0, cylinder 0 */
  533                 if (*count < SECSIZE/sizeof (int)) {
  534                         printf("hd%d: RDABS bad size %x", unit, count);
  535                         return (D_INVALID_OPERATION);
  536                 }
  537                 bp1 = geteblk(SECSIZE);
  538                 bp1->b_flags = B_READ | B_MD1;  /* MD1 is be absolute */
  539                 bp1->b_blkno = abs_sec;
  540                 bp1->b_dev = WHOLE_DISK(unit);  /* C partition */
  541                 bp1->b_bcount = SECSIZE;
  542                 hdstrategy(bp1);
  543                 biowait(bp1);
  544                 if (bp1->b_flags & B_ERROR) {
  545                         printf("hd%d hdsetstat(): read failure RDABS\n", unit);
  546                         brelse(bp1);
  547                         return (ENXIO);
  548                 }
  549                 bcopy(bp1->b_un.b_addr, (caddr_t)data, SECSIZE);
  550                 brelse(bp1);
  551                 *count = SECSIZE/sizeof(int);
  552                 break;
  553         }
  554         case V_VERIFY: {
  555                 unsigned int snum;
  556                 int xcount;
  557                 int code = 0;
  558                 bp1 = geteblk(PAGESIZ);
  559                 bp1->b_flags = B_READ;
  560                 bp1->b_blkno = abs_sec;
  561                 bp1->b_dev = WHOLE_DISK(unit);  /* C partition */
  562                 xcount = abs_count;
  563                 snum = PAGESIZ >> 9;
  564                 while (xcount > 0) {
  565                         i = (xcount > snum) ? snum : xcount;
  566                         bp1->b_bcount = i << 9;
  567                         bp1->b_flags |= B_MD1;
  568                         hdstrategy(bp1);
  569                         biowait(bp1);
  570                         if (bp1->b_flags & B_ERROR) {
  571                                 code = BAD_BLK;
  572                                 break;
  573                         }
  574                         xcount -= i;
  575                         bp1->b_blkno += i;
  576                         bp1->b_flags &= ~B_DONE;
  577                 }
  578                 brelse(bp1);
  579                 data[0] = code;
  580                 *count = 1;
  581                 break;
  582         }
  583         default:
  584                 return (D_INVALID_OPERATION);
  585         }
  586         return (D_SUCCESS);
  587 }
  588 
  589 /* IOC_VOID or IOC_IN or IOC_INOUT */
  590 io_return_t hdsetstat(dev, flavor, data, count)
  591 dev_t dev;
  592 int flavor;
  593 int * data;
  594 unsigned int count;
  595 {
  596         struct buf              *bp1;
  597         io_return_t             errcode = D_SUCCESS;
  598         int                     unit = UNIT(dev);
  599         struct disklabel        *lp = &label[unit];
  600 
  601         switch (flavor) {
  602         /* BsdLabel flavors */
  603         case DIOCWLABEL:
  604         case DIOCWLABEL - (0x10<<16):
  605                 if (*(int*)data)
  606 /*
  607                         tgt->flags |= TGT_WRITE_LABEL;
  608                 else
  609                         tgt->flags &= ~TGT_WRITE_LABEL;
  610 */              break;
  611         case DIOCSDINFO:
  612         case DIOCSDINFO - (0x10<<16):
  613         case DIOCWDINFO:
  614         case DIOCWDINFO - (0x10<<16):
  615                 if (count != sizeof(struct disklabel) / sizeof(int))
  616                         return D_INVALID_SIZE;
  617                 /*
  618                  * setdisklabel is in scsi/rz_disk.c; but is generic
  619                  */
  620                 errcode = setdisklabel(lp, (struct disklabel*) data);
  621                 if (errcode || (flavor == DIOCSDINFO) || (flavor == DIOCSDINFO - (0x10<<16)))
  622                         return errcode;
  623                 errcode = hdwritelabel(unit);
  624                 break;
  625         /* LocalLabel flavors */
  626         case V_REMOUNT:
  627                 hdgotvtoc[unit] = 0;
  628                 getvtoc(unit);
  629                 break;
  630         case V_ABS:
  631                 abs_sec = *(int *)data;
  632                 if (count == 2)
  633                         abs_count = data[1];
  634                 break;
  635         case V_WRABS:
  636                 /* V_WRABS is relative to head 0, sector 0, cylinder 0 */
  637                 if (count < SECSIZE/sizeof (int)) {
  638                         printf("hd%d: WRABS bad size %x", unit, count);
  639                         return (D_INVALID_OPERATION);
  640                 }
  641                 bp1 = geteblk(SECSIZE);
  642                 bcopy((caddr_t)data, bp1->b_un.b_addr, SECSIZE);
  643                 bp1->b_flags = B_WRITE | B_MD1; /* MD1 is be absolute */
  644                 bp1->b_blkno = abs_sec;
  645                 bp1->b_dev = WHOLE_DISK(unit);  /* C partition */
  646                 bp1->b_bcount = SECSIZE;
  647                 hdstrategy(bp1);
  648                 biowait(bp1);
  649                 if (bp1->b_flags & B_ERROR) {
  650                         printf("hd%d: hdsetstat() read failure WRABS\n", unit);
  651                         errcode = ENXIO;
  652                 }
  653                 brelse(bp1);
  654                 break;
  655         default:
  656                 return (D_INVALID_OPERATION);
  657         }
  658         return (errcode);
  659 }
  660 
  661 #else   MACH_KERNEL
  662 hdioctl(dev, cmd, arg, mode)
  663 dev_t dev;
  664 int cmd;
  665 caddr_t arg;
  666 {
  667         u_char                  unit = UNIT(dev),
  668                                 ctrl = unit>>1;
  669         struct disklabel        *lp = &label[unit];
  670         union io_arg            *arg_kernel;
  671         int                     snum, xcount, i;
  672         struct buf              *bp1;
  673 
  674         switch (cmd) {
  675         case V_CONFIG:
  676                 arg_kernel = (union io_arg *)arg;
  677                 if (arg_kernel->ia_cd.secsiz != SECSIZE)
  678                         /* changing sector size NOT allowed */
  679                         return(EINVAL);
  680                 lp->d_ncylinders=(unsigned short)arg_kernel->ia_cd.ncyl;
  681                 lp->d_ntracks=(unsigned short)arg_kernel->ia_cd.nhead;
  682                 lp->d_nsectors=(unsigned short)arg_kernel->ia_cd.nsec;
  683                 fudge_bsd_label(lp, lp->d_type,
  684                                 lp->d_ncylinders, lp->d_ntracks,
  685                                 lp->d_nsectors, lp->d_npartitions);
  686                 setcontroller(unit);
  687                 break;
  688         case V_REMOUNT:
  689                 hdgotvtoc[unit] = 0;
  690                 getvtoc(unit);  
  691                 break;
  692         case V_ADDBAD:
  693                 /* this adds a bad block to IN CORE alts table ONLY */
  694                 alt_info[unit].alt_sec.alt_used++;
  695                 alt_info[unit].alt_sec.alt_bad[alt_info[unit].alt_sec.alt_used]
  696                         = ((union io_arg *)arg)->ia_abs.bad_sector;
  697                 break;
  698         case V_GETPARMS:
  699                 {
  700                 unsigned char part = PARTITION(dev);
  701                 struct disk_parms *disk_parms = (struct disk_parms *)arg;
  702                 disk_parms->dp_type = DPT_WINI;
  703                 disk_parms->dp_heads = lp->d_ntracks;
  704                 disk_parms->dp_cyls = lp->d_ncylinders;
  705                 disk_parms->dp_sectors  = lp->d_nsectors
  706                 disk_parms->dp_dosheads = dosparm[unit].nheads;
  707                 disk_parms->dp_doscyls = dosparm[unit].ncyl;
  708                 disk_parms->dp_dossectors  = dosparm[unit].nsec;
  709                 disk_parms->dp_secsiz = SECSIZE;
  710                 disk_parms->dp_ptag = 0;
  711                 disk_parms->dp_pflag = 0;
  712                 disk_parms->dp_pstartsec =lp->d_partitions[part].p_offset;
  713                 disk_parms->dp_pnumsec =lp->d_partitions[part].p_size;
  714                 break;
  715                 }
  716         case V_RDABS:
  717                 /* V_RDABS is relative to head 0, sector 0, cylinder 0 */
  718                 bp1 = geteblk(SECSIZE);
  719                 bp1->b_flags = B_READ | B_MD1;  /* MD1 is be absolute */
  720                 bp1->b_blkno = ((struct absio *)arg)->abs_sec;
  721                 bp1->b_dev = WHOLE_DISK(unit);  /* C partition for RDABS */
  722                 bp1->b_bcount = SECSIZE;
  723                 hdstrategy(bp1);
  724                 biowait(bp1);
  725                 if (bp1->b_flags & B_ERROR) {
  726                         printf("hd: read failure on ioctl\n");
  727                         brelse(bp1);
  728                         return(ENXIO);
  729                 }
  730                 if(copyout(bp1->b_un.b_addr,((struct absio *)arg)->abs_buf,
  731                            SECSIZE)){
  732                         brelse(bp1);
  733                         return(ENXIO);
  734                 }
  735                 brelse(bp1);
  736                 break;
  737         case V_WRABS:
  738                 /* V_WRABS is relative to head 0, sector 0, cylinder 0 */
  739                 bp1 = geteblk(SECSIZE);
  740                 if (copyin(((struct absio *)arg)->abs_buf,bp1->b_un.b_addr,
  741                            SECSIZE)){
  742                         brelse(bp1);
  743                         return(ENXIO);
  744                 }
  745                 bp1->b_flags = B_WRITE | B_MD1; /* MD1 is be absolute */
  746                 bp1->b_blkno = ((struct absio *)arg)->abs_sec;
  747                 bp1->b_dev = WHOLE_DISK(unit);  /* C partition for RDABS */
  748                 bp1->b_bcount = SECSIZE;
  749                 hdstrategy(bp1);
  750                 biowait(bp1);
  751                 if (bp1->b_flags & B_ERROR) {
  752                         printf("hd: write failure on ioctl\n");
  753                         brelse(bp1);
  754                         return(ENXIO);
  755                 }
  756                 brelse(bp1);
  757                 break;
  758         case V_VERIFY:
  759                 if (u.u_uid)
  760                         return(ENXIO);
  761                 bp1 = geteblk(PAGESIZ);
  762                 bp1->b_flags = B_READ | B_MD1;
  763                 bp1->b_blkno = ((union vfy_io *)arg)->vfy_in.abs_sec;
  764                 bp1->b_dev = WHOLE_DISK(unit);  /* C partition for RDABS */
  765                 xcount = ((union vfy_io *)arg)->vfy_in.num_sec;
  766                 ((union vfy_io *)arg)->vfy_out.err_code = 0;
  767                 snum = PAGESIZ >> 9;
  768                 while (xcount > 0) {
  769                         i = (xcount > snum) ? snum : xcount;
  770                         bp1->b_bcount = i << 9;
  771                         hdstrategy(bp1);
  772                         biowait(bp1);
  773                         if (bp1->b_flags & B_ERROR) {
  774                                ((union vfy_io *)arg)->vfy_out.err_code=BAD_BLK;
  775                                break;
  776                         }
  777                         xcount -= i;
  778                         bp1->b_blkno += i;
  779                         bp1->b_flags &= ~B_DONE;
  780                 }
  781                 brelse(bp1);
  782                 break;
  783         default:
  784                 return(EINVAL);
  785         }
  786         return(0);
  787 }
  788 #endif  MACH_KERNEL
  789 
  790 hdstrategy(bp)
  791 struct buf *bp;
  792 {
  793         u_char                  unit = UNIT(bp->b_dev),
  794                                 ctrl = unit>>1;
  795         struct disklabel        *lp = &label[unit];
  796         struct partition        *part_p = &lp->d_partitions[PARTITION(bp->b_dev)];
  797         spl_t                   opri;
  798 
  799         if (!bp->b_bcount)
  800                 goto done;
  801         /* if request is off the end or trying to write last block on out */
  802         if (bp->b_flags & B_MD1) {
  803                 if (bp->b_blkno > lp->d_partitions[PART_DISK].p_offset +
  804                     lp->d_partitions[PART_DISK].p_size - 1) {
  805                         bp->b_error = ENXIO;
  806                         goto bad;
  807                 }
  808         } else {
  809                 if ((bp->b_blkno > part_p->p_size) ||
  810                     (bp->b_blkno==part_p->p_size && !(bp->b_flags & B_READ))) {
  811                         bp->b_error = ENXIO;
  812                         goto bad;
  813                 }
  814                 if (bp->b_blkno == part_p->p_size) {
  815                         /* indicate (read) EOF by setting b_resid to b_bcount on last block */ 
  816                         bp->b_resid = bp->b_bcount;
  817                         goto done;
  818                 }
  819         }
  820         bp->b_cylin = ((bp->b_flags&B_MD1 ? 0 : part_p->p_offset) + bp->b_blkno)
  821                 / (lp->d_nsectors * lp->d_ntracks);
  822         opri = spl5();
  823         disksort(&hdunit[unit], bp);
  824         if (!hh[ctrl].controller_busy)
  825                 hdstart(ctrl);
  826         splx(opri);
  827         return;
  828 bad:
  829         bp->b_flags |= B_ERROR;
  830 done:
  831         iodone(bp);
  832         return;
  833 }
  834 
  835 /* hdstart() is called at spl5 */
  836 hdstart(ctrl)
  837 int ctrl;
  838 {
  839         struct partition        *part_p;
  840         register struct buf     *bp;
  841         int                     i;
  842 
  843         /* things should be quiet */
  844         if (i = need_set_controller[ctrl]) {
  845                 if (i&1) set_controller(ctrl<<1);
  846                 if (i&2) set_controller((ctrl<<1)||1);
  847                 need_set_controller[ctrl] = 0;
  848         }
  849         if (bp = hdunit[hh[ctrl].curdrive^1].b_actf)
  850                 hh[ctrl].curdrive^=1;
  851         else if (!(bp = hdunit[hh[ctrl].curdrive].b_actf))
  852                 return;
  853         hh[ctrl].controller_busy = 1;
  854         hh[ctrl].blocktotal = (bp->b_bcount + 511) >> 9;
  855         part_p = &label[UNIT(bp->b_dev)].d_partitions[PARTITION(bp->b_dev)];
  856         /* see V_RDABS and V_WRABS in hdioctl() */
  857         if (bp->b_flags & B_MD1) {
  858                 struct disklabel *lp = &label[hh[ctrl].curdrive];
  859                 int end = lp->d_partitions[PART_DISK].p_offset +
  860                         lp->d_partitions[PART_DISK].p_size - 1;
  861                 hh[ctrl].physblock = bp->b_blkno;
  862                 if ((bp->b_blkno + hh[ctrl].blocktotal) > end)
  863                         hh[ctrl].blocktotal = end - bp->b_blkno + 1;
  864         } else {
  865                 hh[ctrl].physblock = part_p->p_offset + bp->b_blkno;
  866                 if ((bp->b_blkno + hh[ctrl].blocktotal) > part_p->p_size)
  867                         hh[ctrl].blocktotal = part_p->p_size - bp->b_blkno + 1;
  868         }
  869         hh[ctrl].blockcount = 0;
  870         hh[ctrl].rw_addr = (int)bp->b_un.b_addr;
  871         hh[ctrl].retry_count = 0;
  872         start_rw(bp->b_flags & B_READ, ctrl);
  873 }
  874 
  875 int hd_print_error = 0;
  876 hdintr(ctrl)
  877 int ctrl;
  878 {
  879         register struct buf     *bp;
  880         int                     addr = devaddr[ctrl],
  881                                 unit = hh[ctrl].curdrive;
  882         u_char status;
  883 
  884         if (!hh[ctrl].controller_busy)
  885                 return;
  886         waitcontroller(ctrl);
  887         status = inb(PORT_STATUS(addr));
  888         bp = hdunit[unit].b_actf;
  889         if (hh[ctrl].restore_request) { /* Restore command has completed */
  890                 hh[ctrl].restore_request = 0;
  891                 if (status & STAT_ERROR)
  892                         hderror(bp,ctrl);
  893                 else if (bp)
  894                         start_rw(bp->b_flags & B_READ,ctrl);
  895                 return;
  896         }
  897         if (status & STAT_WRITEFAULT) {
  898                 if (hd_print_error) {
  899                          printf("hdintr: write fault. block %d, count %d, total %d\n",
  900                                 hh[ctrl].physblock, hh[ctrl].blockcount,
  901                                 hh[ctrl].blocktotal);
  902                          printf("hdintr: write fault. cyl %d, head %d, sector %d\n",
  903                                 hh[ctrl].cylinder, hh[ctrl].head,
  904                                 hh[ctrl].sector);
  905 
  906                 }
  907                 panic("hd: write fault\n");
  908         }
  909         if (status & STAT_ERROR) {
  910                 if (hd_print_error) {
  911                          printf("hdintr: state error %x, error = %x\n",
  912                                 status, inb(PORT_ERROR(addr)));
  913                          printf("hdintr: state error. block %d, count %d, total %d\n",
  914                                 hh[ctrl].physblock, hh[ctrl].blockcount,
  915                                 hh[ctrl].blocktotal);
  916                          printf("hdintr: state error. cyl %d, head %d, sector %d\n",
  917                                 hh[ctrl].cylinder, hh[ctrl].head,
  918                                 hh[ctrl].sector);
  919 
  920                 }
  921                 hderror(bp,ctrl);
  922                 return;
  923         }
  924         if (status & STAT_ECC) 
  925                 printf("hd: ECC soft error fixed, unit %d, partition %d, physical block %d \n",
  926                         unit, PARTITION(bp->b_dev), hh[ctrl].physblock);
  927         if (!bp) {
  928                 /* there should be a read/write buffer queued at this point */
  929                 printf("hd%d: no bp buffer to read or write\n",unit);
  930                 return;
  931         }
  932         if (bp->b_flags & B_READ) {
  933                 while (!(inb(PORT_STATUS(addr)) & STAT_DATAREQUEST));
  934                 linw(PORT_DATA(addr), hh[ctrl].rw_addr, SECSIZE/2); 
  935         }
  936         if (++hh[ctrl].blockcount == hh[ctrl].blocktotal) {
  937                 hdunit[unit].b_actf = bp->av_forw;
  938                 bp->b_resid = 0;
  939                 iodone(bp);
  940                 hh[ctrl].controller_busy = 0;
  941                 hdstart(ctrl);
  942         } else {
  943                 hh[ctrl].rw_addr += SECSIZE;
  944                 hh[ctrl].physblock++;
  945                 if (hh[ctrl].single_mode)
  946                         start_rw(bp->b_flags & B_READ,ctrl);
  947                 else if (!(bp->b_flags & B_READ)) {
  948                         /* Load sector into controller for next write */
  949                         while (!(inb(PORT_STATUS(addr)) & STAT_DATAREQUEST));
  950                         loutw(PORT_DATA(addr), hh[ctrl].rw_addr, SECSIZE/2);
  951                 }
  952         }
  953 }
  954 
  955 hderror(bp,ctrl)
  956 struct buf *bp;
  957 int ctrl;
  958 {
  959         int     addr = devaddr[ctrl],
  960                 unit = hh[ctrl].curdrive;
  961 
  962         if(++hh[ctrl].retry_count > 3) {
  963                 if(bp) {
  964                         int i;
  965                         /****************************************************
  966                         * We have a problem with this block, set the error  *
  967                         * flag, terminate the operation and move on to the  *
  968                         * next request.  With every hard disk transaction   *
  969                         * error we set the reset requested flag so that the *
  970                         * controller is reset before the next operation is  *
  971                         * started.                                          *
  972                         ****************************************************/
  973                         hdunit[unit].b_actf = bp->av_forw;
  974                         bp->b_flags |= B_ERROR;
  975                         bp->b_resid = 0;
  976                         iodone(bp);
  977                         outb(FIXED_DISK_REG(ctrl), 4);
  978                         for(i = 0; i < 10000; i++);
  979                         outb(FIXED_DISK_REG(ctrl), 0);
  980                         setcontroller(unit);
  981                         hh[ctrl].controller_busy = 0;
  982                         hdstart(ctrl);
  983                 }
  984         }
  985         else {
  986                 /* lets do a recalibration */
  987                 waitcontroller(ctrl);
  988                 hh[ctrl].restore_request = 1;
  989                 outb(PORT_PRECOMP(addr), dosparm[unit].precomp>>2);
  990                 outb(PORT_NSECTOR(addr), label[unit].d_nsectors);
  991                 outb(PORT_SECTOR(addr), hh[ctrl].sector);
  992                 outb(PORT_CYLINDERLOWBYTE(addr), hh[ctrl].cylinder & 0xff);
  993                 outb(PORT_CYLINDERHIBYTE(addr), (hh[ctrl].cylinder>>8) & 0xff);
  994                 outb(PORT_DRIVE_HEADREGISTER(addr), (unit&1)<<4);
  995                 outb(PORT_COMMAND(addr), CMD_RESTORE);
  996         }
  997 }
  998 
  999 getvtoc(unit)
 1000 {
 1001         hdreadlabel(unit, 1);
 1002 }
 1003 
 1004 setcontroller(unit)
 1005 {
 1006         need_set_controller[unit>>1] |= (1<<(unit&1));
 1007 }
 1008 
 1009 set_controller(unit)
 1010 {
 1011         int                     ctrl = unit >> 1;
 1012         int                     addr = devaddr[ctrl];
 1013         struct disklabel        *lp = &label[unit];
 1014 
 1015         waitcontroller(ctrl);
 1016         outb(PORT_DRIVE_HEADREGISTER(addr), (lp->d_ntracks - 1) |
 1017              ((unit&1) << 4) | FIXEDBITS);
 1018         outb(PORT_NSECTOR(addr), lp->d_nsectors);
 1019         outb(PORT_COMMAND(addr), CMD_SETPARAMETERS);
 1020         waitcontroller(ctrl);
 1021 }
 1022 
 1023 waitcontroller(ctrl)
 1024 {
 1025         u_int   n = PATIENCE;
 1026 
 1027         while (--n && inb(PORT_STATUS(devaddr[ctrl])) & STAT_BUSY);
 1028         if (n)
 1029                 return;
 1030         panic("hd%d: waitcontroller() timed out",ctrl);
 1031 }
 1032 
 1033 start_rw(read, ctrl)
 1034      int read, ctrl;
 1035 {
 1036         int                     addr = devaddr[ctrl],
 1037                                 unit = hh[ctrl].curdrive;
 1038         struct disklabel        *lp = &label[unit];
 1039         u_int                   track, disk_block, xblk;
 1040 
 1041         disk_block = hh[ctrl].physblock;
 1042         xblk=hh[ctrl].blocktotal - hh[ctrl].blockcount; /*# blks to transfer*/
 1043         if (!(hdunit[unit].b_actf->b_flags & B_MD1) &&
 1044             (hh[ctrl].single_mode = xfermode(ctrl))) {
 1045                 xblk = 1;
 1046                 if (PARTITION(hdunit[unit].b_actf->b_dev) != PART_DISK)
 1047                         disk_block = badblock_mapping(ctrl);
 1048         }
 1049         /* disk is formatted starting sector 1, not sector 0 */
 1050         hh[ctrl].sector = (disk_block % lp->d_nsectors) + 1;
 1051         track = disk_block / lp->d_nsectors;
 1052         hh[ctrl].head = track % lp->d_ntracks | 
 1053                 (unit&1) << 4 | FIXEDBITS;
 1054         hh[ctrl].cylinder = track / lp->d_ntracks;
 1055         waitcontroller(ctrl);
 1056         outb(PORT_PRECOMP(addr), dosparm[unit].precomp >>2);
 1057         outb(PORT_NSECTOR(addr), xblk);
 1058         outb(PORT_SECTOR(addr), hh[ctrl].sector);
 1059         outb(PORT_CYLINDERLOWBYTE(addr), hh[ctrl].cylinder & 0xff );
 1060         outb(PORT_CYLINDERHIBYTE(addr),  (hh[ctrl].cylinder >> 8) & 0xff );
 1061         outb(PORT_DRIVE_HEADREGISTER(addr), hh[ctrl].head);
 1062         if(read) {
 1063                 outb(PORT_COMMAND(addr), CMD_READ);
 1064         } else {
 1065                 outb(PORT_COMMAND(addr), CMD_WRITE);
 1066                 waitcontroller(ctrl);
 1067                 while (!(inb(PORT_STATUS(addr)) & STAT_DATAREQUEST));
 1068                 loutw(PORT_DATA(addr), hh[ctrl].rw_addr, SECSIZE/2);
 1069         }
 1070 }
 1071 
 1072 int badblock_mapping(ctrl)
 1073 int ctrl;
 1074 {
 1075         u_short n;
 1076         u_int   track,
 1077                 unit = hh[ctrl].curdrive,
 1078                 block = hh[ctrl].physblock,
 1079                 nsec = label[unit].d_nsectors;
 1080 
 1081         track = block / nsec;
 1082         for (n = 0; n < alt_info[unit].alt_trk.alt_used; n++)
 1083                 if (track == alt_info[unit].alt_trk.alt_bad[n])
 1084                         return alt_info[unit].alt_trk.alt_base +
 1085                                nsec * n + (block % nsec);
 1086         /* BAD BLOCK MAPPING */
 1087         for (n = 0; n < alt_info[unit].alt_sec.alt_used; n++)
 1088                 if (block == alt_info[unit].alt_sec.alt_bad[n])
 1089                         return alt_info[unit].alt_sec.alt_base + n;
 1090         return block;
 1091 }
 1092 
 1093 /*
 1094  *  determine single block or multiple blocks transfer mode
 1095  */
 1096 int xfermode(ctrl)
 1097 int ctrl;
 1098 {
 1099         int     n, bblk, eblk, btrk, etrk;
 1100         int     unit = hh[ctrl].curdrive;
 1101 
 1102         bblk = hh[ctrl].physblock;
 1103         eblk = bblk + hh[ctrl].blocktotal - 1;
 1104         btrk = bblk / label[unit].d_nsectors;
 1105         etrk = eblk / label[unit].d_nsectors;
 1106         
 1107         for (n = 0; n < alt_info[unit].alt_trk.alt_used; n++)
 1108                 if ((btrk <= alt_info[unit].alt_trk.alt_bad[n]) &&
 1109                     (etrk >= alt_info[unit].alt_trk.alt_bad[n]))
 1110                         return 1;
 1111         for (n = 0; n < alt_info[unit].alt_sec.alt_used; n++)
 1112                 if ((bblk <= alt_info[unit].alt_sec.alt_bad[n]) &&
 1113                     (eblk >= alt_info[unit].alt_sec.alt_bad[n]))
 1114                         return 1;
 1115         return 0;
 1116 }
 1117 
 1118 hdsize()
 1119 {
 1120         printf("hdsize()                -- not implemented\n");
 1121 }
 1122 
 1123 hddump()
 1124 {
 1125         printf("hddump()                -- not implemented\n");
 1126 }
 1127 
 1128 #ifdef  MACH_KERNEL
 1129 /*
 1130  *      Routine to return information to kernel.
 1131  */
 1132 int
 1133 hddevinfo(dev, flavor, info)
 1134 dev_t   dev;
 1135 int     flavor;
 1136 char    *info;
 1137 {
 1138         register int    result;
 1139 
 1140         result = D_SUCCESS;
 1141 
 1142         switch (flavor) {
 1143         case D_INFO_BLOCK_SIZE:
 1144                 *((int *) info) = SECSIZE;
 1145                 break;
 1146         default:
 1147                 result = D_INVALID_OPERATION;
 1148         }
 1149 
 1150         return(result);
 1151 }
 1152 #endif  MACH_KERNEL

Cache object: 807367d4b01cc5ae9e5030c7319bd92a


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