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/i386ps2/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) 1991,1989 Carnegie Mellon University
    4  * Copyright (c) 1991 IBM Corporation 
    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  * and that the name IBM not be used in advertising or publicity 
   13  * pertaining to distribution of the software without specific, written
   14  * prior permission.
   15  * 
   16  * CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   17  * CONDITION.  CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
   18  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   19  * 
   20  * Carnegie Mellon requests users of this software to return to
   21  * 
   22  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   23  *  School of Computer Science
   24  *  Carnegie Mellon University
   25  *  Pittsburgh PA 15213-3890
   26  * 
   27  * any improvements or extensions that they make and grant Carnegie Mellon
   28  * the rights to redistribute these changes.
   29  */
   30 
   31 static char sccsid[] = "@(#)66  1.1  mk/src/latest/kernel/i386ps2/hd.c, root 4/4/91 10:22:11";
   32 /* 
   33  * HISTORY
   34  * $Log:        hd.c,v $
   35  * Revision 2.5  93/08/10  16:00:26  mrt
   36  *      changed partition -> localpartition for type declaration so not
   37  *      to conflict with partition struct introduced in disklabel.h
   38  *      [93/08/09            rvb]
   39  * 
   40  * Revision 2.4  93/05/28  21:22:25  rvb
   41  *      In the getstat and setstat routines, return failure
   42  *      if the flavor isn't one we know about.
   43  *      [93/05/28  15:07:28  chs]
   44  * 
   45  * Revision 2.3  93/03/11  14:09:19  danner
   46  *      u_long -> u_int
   47  *      [93/03/09            danner]
   48  * 
   49  * Revision 2.2  93/02/04  07:59:55  danner
   50  *      Using i386at/disk.h rather than i386ps2/disk.h == They are
   51  *      identical. 
   52  *      [93/01/25            rvb]
   53  * 
   54  *      Changed to new partition scheme.
   55  *      Pick up recent bugfixes from i386at/hd.c.
   56  *      [93/01/18            zon]
   57  * 
   58  *      Integrate PS2 code from IBM.
   59  *      [93/01/18            prithvi]
   60  * 
   61  * Revision 1.17  90/11/02  11:15:42  webb
   62  * 1. move code out of hdinit into hdprobe and hdslave routines 
   63  * 2. make other appropriate changes to work fully with autoconfig.
   64  * 
   65  * Revision 1.16  90/11/01  10:44:52  webb
   66  * changes for new version of config 
   67  * 
   68  * Revision 1.15  90/10/23  15:36:13  webb
   69  * remove dead code and make changes so that multiple LIDS (and multiple 
   70  * interrupt vectors) are supported.
   71  * 
   72  * Revision 1.7  90/09/12  11:10:09  webb
   73  * 1. clean up code and debugging printf's
   74  * 2. improve error message output's 
   75  * 3. delete code not needed for this driver 
   76  * 4. put in error retrying
   77  * 
   78  * Revision 1.6  90/09/05  10:00:47  webb
   79  * 1. add error decoding 
   80  * 2. use write-verify instead of write for now 
   81  * 3. allow driver to return an error instead of just panicing.
   82  * 
   83  * Revision 1.4  90/08/16  15:51:32  relyea
   84  * rci.rsc nps2 hdreg.h
   85  * fix problems which blew GCC out of the water.
   86  * 
   87  * Revision 1.3  90/08/08  11:20:18  webb
   88  * changes to make gcc happy.
   89  * 
   90  * Revision 1.1  90/02/23  00:27:20  devrcs
   91  *      Latest version for osc.5
   92  *      [90/02/20  11:57:26  kevins]
   93  * 
   94  * Revision 1.6  89/10/24  20:20:52  lance
   95  * Trying to fix the random hang bug.
   96  * 
   97  * Revision 1.5  89/09/26  11:56:47  lance
   98  * X109 checkin
   99  * 
  100  * Revision 1.8  89/09/25  12:26:48  rvb
  101  *      i386at/alttbl.h, i386/vtoc.h, i386/iobuf.h, i386/elog.h -> disk.h
  102  *      [89/09/23            rvb]
  103  * 
  104  * Revision 1.7  89/09/20  17:28:21  rvb
  105  *      Revision 1.3  89/08/01  16:54:04  kupfer
  106  *      Debugging hacks for when driver gets wedged.
  107  * 
  108  * Revision 1.2  89/07/12  11:13:41  lance
  109  * New paths to disk (both through buffer cache & physio).
  110  * 
  111  * Revision 1.4  89/03/09  20:05:37  rpd
  112  *      More cleanup.
  113  * 
  114  * Revision 1.3  89/02/26  12:36:37  gm0w
  115  *      Changes for cleanup.
  116  * 
  117  */
  118  
  119 /*
  120  *         INTEL CORPORATION PROPRIETARY INFORMATION
  121  *
  122  *     This software is supplied under the terms of a license 
  123  *    agreement or nondisclosure agreement with Intel Corpo-
  124  *    ration and may not be copied or disclosed except in
  125  *    accordance with the terms of that agreement.
  126  *    Copyright 1988  Intel Corporation.
  127  */
  128 
  129 /*
  130  *  AT Hard Disk Driver
  131  *  Copyright Ing. C. Olivetti & S.p.A. 1989
  132  *  All rights reserved.
  133  *
  134  */
  135 
  136 #include <platforms.h>
  137 #include <hd.h>
  138 
  139 #if NHD > 0
  140 
  141 #include <sys/types.h>
  142 #define PRIBIO 20
  143 #include <device/io_req.h>
  144 #include <device/buf.h>
  145 #include <device/errno.h>
  146 #include <device/device_types.h>
  147 #include <device/disk_status.h>
  148 
  149 typedef long paddr_t;           /* a physical address */
  150 
  151 #include <sys/ioctl.h>
  152 #include <i386/ipl.h>
  153 #include <i386ps2/bus.h>
  154 #include <i386ps2/abios.h>
  155 #include <i386ps2/debugf.h>
  156 #include <i386ps2/gdabios.h>
  157 #include <i386ps2/hdreg.h>
  158 #include <i386at/disk.h>
  159 
  160 #define LABEL_DEBUG(x,y) if (label_flag&x) y
  161 
  162 extern  struct buf *geteblk();
  163 
  164 #ifndef NHDC
  165 #define NHDC 1                  /* for systems without a full config */
  166 #endif
  167 
  168 #define ABIOS_WRITE_VERIFY      ABIOS_ADDITIONAL_XFER
  169 #define B_RESET 0x10000000      /* resetting the disk */
  170 
  171 struct hh               hh;
  172 struct buf              hd_buF[NHD];    /* buffer for raw io */
  173 struct buf              hdunit[NHD];
  174 struct alt_info alt_info[NHD];
  175 
  176 int hdgotvtoc[NHD];
  177 
  178 #define HD_MAX_XFER (I386_PGBYTES * 8)
  179 static char unaligned_buf[NHD][HD_MAX_XFER]; /* buffer for unaligned xfers */
  180 static caddr_t                  u_buf[NHD];                 /* pointer to the buffer */
  181 static struct buf               *bp1, *bp2;
  182 static struct Gd_request        rb[NHD];
  183 static struct Gd_request        ctlr_rb[NHDC];
  184 static struct Gd_request        save_rb[NHD];
  185 struct disklabel                label[NHD];
  186 int                             labeloffset[NHD];
  187 int                             labelsector[NHD];
  188 static hdisk_t                  hdparams[NHD];  
  189 static saveaddr_t               save_addr[NHD][34];
  190 static struct Logical_id_params params = {0};
  191 
  192 int hd_write_verify = 0; /* will we use write-verify function? */
  193 
  194 static void start_rw(long read);
  195 static int hdintr(int vec);
  196 static int hdabioswait(int abios_function, int gd_flag, int unit);
  197 int hdstrategy(struct buf *);
  198 static void hdinit(void);
  199 static hd_error_decode(int code, char *msg);
  200 
  201 static int hdprobe();
  202 static int hdslave();
  203 static int hdattach();
  204 
  205 int (*hdcintrs[])(int) = {hdintr, 0};
  206 
  207 static struct i386_dev *hdinfo[NHD];
  208 static struct i386_ctlr *hdcinfo[NHDC];
  209 
  210 #define WHOLE_DISK(unit) ((unit << 4) + PART_DISK)
  211 
  212 struct  i386_driver      hdcdriver = {
  213         /* probe slave    attach   dname  dinfo   mname  minfo */
  214         hdprobe, hdslave, hdattach, "hd", hdinfo, "hdc", hdcinfo};
  215 
  216 #define DEV_CTRL_FLAGS_FMT "\2\3CHANGE-SIGNAL\4WRITE-MANY\5CACHING\6READABLE\7LOCKABLE\10SEQUENTIAL\11EJECTABLE\12CONCURRENT\13ST506\14FORMAT-TRACK\15FORMAT-UNIT\17SCSI\20SCB"
  217 #define LOGICAL_ID_FLAGS_FMT "\2\1DATA-POINTER1-LOGICAL\2DATA-POINTER2-PHYSICAL\4OVERLAPPED-IO"
  218 
  219 /*
  220  * probe for the specified controller. 
  221  * we look for the n'th (actually stored in unit) hard disk LID.
  222  * if not found we return that the device doesn't exist.
  223  * if found we get the information about that controller. 
  224  * we use "rb" as a working area, and copy the results back
  225  * into ctlr_rb after we are finished. This is mainly so that we 
  226  * don't have to change abioswait to accept a request block parameter.
  227  */
  228 static int hdprobe(addr, ctlr)
  229 int addr;
  230 struct i386_ctlr *ctlr;
  231 {
  232         int lid_num = 2; /* starting lid number */
  233         int i;
  234         int unit = ctlr->ctlr_ctlr;
  235         static intr_num = -1; /* avoid duplicating interrupt handlers */
  236         struct Gd_request *rbp = &rb[unit];
  237 
  238         hdinit();               /* do other initializations */
  239 
  240         /*
  241          * scan thru the available abios devices looking for this 
  242          * controller (unit) number.
  243          */
  244         for (i=0; (lid_num = abios_next_LID(HD_ID, lid_num)) && i < unit; ++i);
  245 
  246         if (lid_num == 0)
  247                 return 0; /* no such LID */
  248 
  249         /*
  250          * at this point we have determined that the requested controller
  251          * (e.g. LID) exists.
  252          */
  253 
  254         rbp->r_current_req_blck_len = sizeof(struct Gd_request);
  255         rbp->request_header.Request_Block_Flags = 0;
  256         rbp->request_header.ELA_Offset = 0;
  257 
  258         GD_SET_RESERVED_ABIOS_LOGICAL_PARAMETER(*rbp);
  259         rbp->r_logical_id = lid_num;
  260         rbp->r_unit = 0;
  261 
  262         if (hdabioswait(ABIOS_LOGICAL_PARAMETER, params.Logical_id_flags, unit))
  263                 return ENXIO;
  264 
  265         params = rbp->un.logical_id_params;
  266 
  267         /*
  268          * Now we need to update certain field based on what ABIOS
  269          * just told us...
  270          */
  271 
  272         if (rbp->r_request_block_length > rbp->r_current_req_blck_len) {
  273                 printf("hdc%d: Required Request block length is too large.\n",unit);
  274                 return(0);
  275         }
  276 
  277         rbp->r_current_req_blck_len = rbp->r_request_block_length;
  278 
  279         if (!(params.Logical_id_flags & 0x2)) {
  280                 printf ("hdc%d: can not support virtual addresses.\n", unit);
  281                 return(0);
  282         }
  283 
  284         /* if we haven't already gotten this IRQ then obtain it */
  285         if (intr_num != rbp->r_hardware_intr) {
  286                 ctlr->ctlr_pic = intr_num = rbp->r_hardware_intr;
  287                 ctlr->ctlr_spl = SPL5;
  288                 take_ctlr_irq(ctlr);
  289                 printf("hdc%d: port = %x, spl = %d, pic = %d.\n",
  290                         ctlr->ctlr_ctlr, ctlr->ctlr_addr, ctlr->ctlr_spl, ctlr->ctlr_pic);
  291         }
  292 
  293         ctlr_rb[unit] = *rbp;                   /* save controller's rb */
  294 
  295         return 1;
  296 
  297 }
  298 
  299 /*
  300  * see if this unit exists and if it does get the information about it.
  301  */
  302 static int hdslave(iod)
  303 struct i386_dev *iod;
  304 {
  305         int unit = iod->dev_unit;
  306         int slave = iod->dev_slave;
  307 
  308         if (slave >= ctlr_rb[iod->dev_ctlr].r_number_units)
  309                 return(0);              /* not that many units */
  310 
  311         rb[unit] = ctlr_rb[iod->dev_ctlr];      /* copy from controller */
  312         rb[unit].r_unit = slave;
  313         hdunit[unit].b_active = 0;
  314         hdunit[unit].b_actf = 0;
  315         hdunit[unit].b_actl = 0;
  316         hdparams[unit].landzone = 0;
  317         hdparams[unit].precomp = 0;
  318         hdparams[unit].lid  = rb[unit].r_logical_id;
  319         hdparams[unit].unit  = slave;
  320         GD_SET_RESERVED_ABIOS_READ_PARAMETER(rb[unit]);
  321 
  322         if (hdabioswait(ABIOS_READ_PARAMETER, params.Logical_id_flags, unit))
  323                 return(0);
  324 
  325         hdparams[unit].ncylinders = gd_number_cylinders(rb[unit]);
  326         hdparams[unit].nheads = gd_number_heads(rb[unit]);
  327         hdparams[unit].nblocks = gd_max_block_number(rb[unit]);
  328         hdparams[unit].nsecpertrack = gd_sector_per_track(rb[unit]);
  329         hdparams[unit].flags = gd_dev_ctrl_flag(rb[unit]);
  330         hdparams[unit].retries = gd_max_retries(rb[unit]);
  331         hdparams[unit].max_transfer = gd_max_transfer(rb[unit]);
  332         /*
  333          * copy initial parameters into label
  334          */
  335         fudge_bsd_label(&label[unit], DTYPE_ESDI,
  336                         hdparams[unit].ncylinders,
  337                         hdparams[unit].nheads,
  338                         hdparams[unit].nsecpertrack,
  339                         2);
  340 
  341         printf("hd%d: ncylinders=%d nheads=%d nsecpertrack=%d nblocks=%d\n",
  342                 unit,
  343                 hdparams[unit].ncylinders,
  344                 hdparams[unit].nheads, 
  345                 hdparams[unit].nsecpertrack,
  346                 hdparams[unit].nblocks);
  347 
  348         hh.num_units++; /* accumulate total number of units */
  349         params.Device_id = rb[unit].r_logical_id;;
  350 
  351         return(1);
  352 }
  353 
  354 static hdattach(iod)
  355 struct i386_dev *iod;
  356 {
  357 }
  358 
  359 /*
  360  * initialize the disk.
  361  */
  362 static void hdinit(void)
  363 {
  364         int i;
  365         static int hdinit_done = 0;
  366 
  367         if (hdinit_done++)
  368                 return;
  369 
  370         for (i = 0; i < NHD; i++)
  371                 u_buf[i] = &unaligned_buf[i][0];
  372         hh.un_aligned = 0;
  373 
  374 }
  375 
  376 static void hd_delay(register int ticks)
  377 {
  378         assert_wait(0, FALSE);
  379         thread_set_timeout(ticks);
  380         thread_block((continuation_t) 0);
  381 }
  382 
  383 static int hdabioswait(int abios_function, int gd_flag, int unit)
  384 {
  385         int i, j, n;
  386 
  387         struct Gd_request *rbp = &rb[unit];
  388 
  389         rbp->r_function = abios_function;
  390         rbp->r_return_code = ABIOS_UNDEFINED;
  391 
  392         abios_common_start(rbp, gd_flag);
  393 
  394         /* Wait for ABIOS to tell us that it is done. */
  395         while (rbp->r_return_code == ABIOS_UNDEFINED)
  396                 hd_delay(10);   
  397 
  398         if (rbp->r_return_code & 0x8000) {
  399                 printf("[hdabioswait] rb[unit].r_return_code [%x] ", rbp->r_return_code);
  400                 hd_error_decode(rbp->r_return_code, "\n");
  401                 return ENXIO;
  402         }
  403         
  404         hh.status = rbp->r_return_code;
  405 
  406         while (rbp->r_return_code != ABIOS_DONE) {
  407 
  408                 hh.status = rbp->r_return_code; 
  409 
  410                 switch (hh.status) {
  411                 
  412                         case ABIOS_STAGE_ON_INT:
  413                                 hd_delay(1);
  414                                 break;
  415 
  416                         case ABIOS_STAGE_ON_TIME:
  417                                 hd_delay(gd_wait_time(*rbp));
  418                                 abios_common_interrupt(rbp, params.Logical_id_flags);
  419                                 break;
  420 
  421                         case (ABIOS_NOT_MY_INT | ABIOS_STAGE_ON_INT):
  422                                 break;
  423 
  424                         case ABIOS_DONE:
  425                                 return;
  426 
  427                         default:
  428                                 printf("hdabioswait: return code [%x]...\n", hh.status);
  429                                 hd_error_decode(rbp->r_return_code,"\n");
  430                                 return ENXIO;
  431                 }
  432         }
  433         
  434         return 0;
  435 
  436 }
  437 getvtoc(unit)
  438 {
  439         hdreadlabel(unit, 0);
  440 }
  441 
  442 static hdreset(int unit)
  443 {
  444         struct buf *bp = (struct buf *)geteblk(SECSIZE);
  445 
  446 #if     0
  447         if (label[unit].d_partitions[PART_DISK].p_tag == 0) {
  448                 label[unit].d_partitions[PART_DISK].p_tag = V_BACKUP;
  449                 label[unit].d_partitions[PART_DISK].p_flag = V_OPEN | V_UNMNT | V_VALID;
  450                 label[unit].d_partitions[PART_DISK].p_offset = 0; 
  451                 label[unit].d_partitions[PART_DISK].p_size = 10;
  452         }
  453 #endif  /* 0 */
  454 
  455         bp->b_flags = B_RESET|B_MD1;
  456         bp->b_blkno = 0;
  457         bp->b_dev = WHOLE_DISK(unit);
  458         bp->b_bcount = 0;
  459         hdstrategy(bp);
  460         biowait(bp);
  461 
  462         getvtoc(unit);
  463 
  464 }
  465 
  466 io_return_t hdopen(register dev_t dev,
  467                    register dev_mode_t flags,
  468                    io_req_t not_used)
  469 {
  470         int unit = UNIT(dev);
  471         int part = PARTITION(dev);
  472         int n;
  473         static int hdopen_done = 0;
  474 
  475         if (part >= MAXPARTITIONS || unit >= NHD)
  476                 return ENXIO;
  477 
  478         if (!hdopen_done++) {
  479                 hdinit();
  480                 for (n = 0; n < hh.num_units; n++)
  481                         hdreset(n);
  482         }
  483 
  484         if (!label[unit].d_partitions[part].p_offset &&
  485             !label[unit].d_partitions[part].p_size)
  486                 return ENXIO;
  487 
  488         return D_SUCCESS;
  489 
  490 }
  491 
  492 
  493 io_return_t hdclose(register dev_t dev)
  494 {
  495 
  496         return D_SUCCESS;
  497 
  498 }
  499 
  500 int hdread(register dev_t dev, register struct uio *uio)
  501 {
  502         register struct buf *bp = &hd_buF[UNIT(dev)];
  503 
  504         return physio(hdstrategy, bp, dev, B_READ, minphys, uio);
  505 
  506 }
  507 
  508 int hdwrite(register dev_t dev, register struct uio *uio)
  509 {
  510         register struct buf *bp = &hd_buF[UNIT(dev)];
  511 
  512         return physio(hdstrategy, bp, dev, B_WRITE, minphys, uio);
  513 
  514 }
  515 
  516 static int abs_sec   = -1;
  517 static int abs_count = -1;
  518 
  519 io_return_t hdgetstat(dev, flavor, data, count)
  520         dev_t           dev;
  521         int             flavor;
  522         int *           data;           /* pointer to OUT array */
  523         unsigned int    *count;         /* OUT */
  524 {
  525         int unit = UNIT(dev);
  526         struct disklabel *lp = &label[unit];
  527         int part = PARTITION(dev);
  528         io_return_t errcode = D_SUCCESS;
  529         struct disk_parms *dp;
  530         unsigned int snum;
  531         int xcount, i;
  532         int code;
  533 
  534 
  535         switch (flavor) {
  536 
  537         case DEV_GET_SIZE:
  538                 data[DEV_GET_SIZE_DEVICE_SIZE] =
  539                         lp->d_partitions[part].p_size * lp->d_secsize;
  540                 data[DEV_GET_SIZE_RECORD_SIZE] = lp->d_secsize;
  541                 *count = DEV_GET_SIZE_COUNT;
  542                 break;
  543 
  544         /* BsdLabel flavors */
  545         case DIOCGDINFO:
  546         case DIOCGDINFO - (0x10<<16):
  547                 dkgetlabel(lp, flavor, data, count);
  548                 break;
  549 
  550         /* Extra flavors */
  551         case V_GETPARMS:
  552                 if (*count < sizeof (struct disk_parms)/sizeof(int)) {
  553                         printf("hd%d%c: V_GETPARMS bad size %x",
  554                                unit,
  555                                'a' + part,
  556                                count);
  557                         return D_INVALID_OPERATION;
  558                 }
  559                 dp = (struct disk_parms *) data;
  560                 dp->dp_type = DPT_WINI;
  561                 dp->dp_heads = lp->d_ntracks;
  562                 dp->dp_cyls = lp->d_ncylinders;
  563                 dp->dp_sectors  = lp->d_nsectors;
  564                 dp->dp_dosheads = hdparams[unit].nheads;
  565                 dp->dp_doscyls = hdparams[unit].ncylinders;
  566                 dp->dp_dossectors = hdparams[unit].nsecpertrack;
  567                 dp->dp_secsiz = SECSIZE;
  568                 dp->dp_ptag = 0 /* label[unit].d_partitions[part].p_tag */;
  569                 dp->dp_pflag = 0 /* label[unit].d_partitions[part].p_flag */;
  570                 dp->dp_pstartsec = label[unit].d_partitions[part].p_offset;
  571                 dp->dp_pnumsec =label[unit].d_partitions[part].p_size;
  572                 *count = sizeof (struct disk_parms)/sizeof(int);
  573                 break;
  574 
  575         case V_PDLOC:
  576                 *data = label[unit].d_partitions[PART_DISK].p_offset + PDLOCATION;
  577                 break;
  578 
  579         case V_RDABS:
  580                 if (*count < SECSIZE/sizeof (int)) {
  581                         printf("hd%d: V_RDABS bad size %x",
  582                                unit,
  583                                count);
  584                         return D_INVALID_OPERATION;
  585                 }
  586                 bp1 = geteblk(SECSIZE);
  587                 bp1->b_flags = B_READ | B_MD1;
  588                 bp1->b_blkno = abs_sec;
  589                 bp1->b_dev = WHOLE_DISK(unit);
  590                 bp1->b_bcount = SECSIZE;
  591                 hdstrategy(bp1);
  592                 biowait(bp1);
  593                 if (bp1->b_flags & B_ERROR) {
  594                         printf("hd%d: V_RDABS failed\n", unit);
  595                         errcode = ENXIO;
  596                         brelse(bp1);
  597                         break;
  598                 }
  599                 bcopy((caddr_t)paddr(bp1), (caddr_t) data, SECSIZE);
  600                 brelse(bp1);
  601                 *count = SECSIZE/sizeof(int);
  602                 break;
  603 
  604         case V_VERIFY:
  605                 bp1 = geteblk(PAGESIZ);
  606                 bp1->b_flags = B_READ | B_MD1;
  607                 bp1->b_blkno = abs_sec;
  608                 bp1->b_dev = WHOLE_DISK(unit);
  609                 xcount = abs_count;
  610                 snum = PAGESIZ >> 9;
  611                 code = 0;
  612                 while (xcount > 0) {
  613                         i = (xcount > snum) ? snum : xcount;
  614                         bp1->b_bcount = i << 9;
  615                         hdstrategy(bp1);
  616                         biowait(bp1);
  617                         if (bp1->b_flags & B_ERROR) {
  618                                 code = BAD_BLK;
  619                                 break;
  620                         }
  621                         xcount -= i;
  622                         bp1->b_blkno += i;
  623                         bp1->b_flags &= ~B_DONE;
  624                 }
  625                 brelse(bp1);
  626                 data[0] = code;
  627                 *count = 1;
  628                 break;
  629 
  630         default:
  631                 return D_INVALID_OPERATION;
  632         }
  633 
  634         return errcode;
  635 
  636 }
  637 
  638 io_return_t hdsetstat(dev_t dev, int flavor, int *data, unsigned int count)
  639 {
  640         io_return_t     errcode = D_SUCCESS;
  641         int             unit = UNIT(dev);
  642         struct disklabel*lp = &label[unit];
  643         int             part = PARTITION(dev);
  644 
  645         switch (flavor) {
  646         /* BsdLabel flavors */
  647         case DIOCWLABEL:
  648         case DIOCWLABEL - (0x10<<16):
  649         case DIOCSDINFO:
  650         case DIOCSDINFO - (0x10<<16):
  651         case DIOCWDINFO:
  652         case DIOCWDINFO - (0x10<<16):
  653                 return hdsetlabel(dev, flavor, data, count);
  654 
  655         /* LocalLabel flavors */
  656         case V_REMOUNT:
  657                 hdgotvtoc[unit] = 0;
  658                 getvtoc(unit);  
  659                 break;
  660 
  661         case V_ABS:
  662                 abs_sec = *(int *)data;
  663                 if (count == 2)
  664                         abs_count = data[1];
  665                 break;
  666 
  667         case V_WRABS:
  668                 if (count < 512/sizeof (int)) {
  669                         printf("hdsetstat: hd%d WRABS bad size %x",
  670                                unit,
  671                                count);
  672                         return D_INVALID_OPERATION;
  673                 }
  674                 bp1 = geteblk(SECSIZE);
  675                 bcopy( (caddr_t)data, (caddr_t)paddr(bp1), SECSIZE);
  676                 bp1->b_flags = B_WRITE | B_MD1;
  677                 bp1->b_blkno = abs_sec;
  678                 bp1->b_dev = WHOLE_DISK(unit);
  679                 bp1->b_bcount = SECSIZE;
  680                 hdstrategy(bp1);
  681                 biowait(bp1);
  682                 if (bp1->b_flags & B_ERROR) {
  683                         printf("hdsetstat: hd%d WRABS failed\n", unit);
  684                         errcode = ENXIO;
  685                 }
  686                 brelse(bp1);
  687                 break;
  688 
  689         default:
  690                 return D_INVALID_OPERATION;
  691         }
  692 
  693         return errcode;
  694 }
  695 
  696 setcontroller(int unit)
  697 {
  698 }
  699 
  700 /* hdstart() is called at spl5 */
  701 static void hdstart(void)
  702 {
  703         struct partition *part_p;
  704         int drivecount;
  705         register struct buf *bp, *dp;
  706 
  707         if (hh.busy)
  708                 return;
  709 
  710         for (drivecount = 0; drivecount < NHD; drivecount++) {
  711                 if (hh.curdrive < (NHD-1))
  712                         hh.curdrive++;
  713                 else
  714                         hh.curdrive = 0;
  715                 dp = &hdunit[hh.curdrive];
  716                 if ((bp = dp->b_actf) != NULL)
  717                         break;
  718         }
  719         if (drivecount == NHD)
  720                 return;
  721 
  722         hh.busy = 1;
  723         hh.blocktotal = (bp->b_bcount + 511) >> 9;
  724 
  725         assert(hh.blocktotal > 0 || (bp->b_flags&B_RESET));
  726 
  727         part_p = &label[UNIT(bp->b_dev)].d_partitions[PARTITION(bp->b_dev)];
  728         
  729         if (bp->b_flags & B_MD1) {
  730                 int end = label[UNIT(bp->b_dev)].d_secperunit - 1;
  731                 hh.physblock = bp->b_blkno;
  732                 if ((bp->b_blkno + hh.blocktotal) > end)
  733                         hh.blocktotal = end - bp->b_blkno + 1;
  734         } else {
  735                 hh.physblock = part_p->p_offset + bp->b_blkno;
  736                 if ((bp->b_blkno + hh.blocktotal ) > part_p->p_size) {
  737                         hh.blocktotal = part_p->p_size - bp->b_blkno + 1;
  738                 }
  739         }
  740         hh.blockcount = 0;
  741         hh.rw_addr = (paddr_t)bp->b_un.b_addr;
  742         hh.retries = 0;
  743 
  744         start_rw(bp->b_flags & (B_READ | B_RESET)); 
  745 
  746 }
  747 
  748 hdstrategy(struct buf *bp)
  749 {
  750         unsigned char unit, partition;
  751         struct disklabel *lp;
  752         struct partition *part_p;
  753         unsigned int opri;
  754         long count, total;
  755         u_int p_addr, baddr;
  756         int i;
  757         long size;
  758 
  759         if (!bp->b_bcount)
  760                 if (bp->b_flags != (bp->b_flags & B_RESET))
  761                         goto done;
  762 
  763         unit = UNIT((bp->b_dev));
  764         lp = &label[unit];
  765         partition = PARTITION((bp->b_dev));
  766         part_p= &(label[unit].d_partitions[partition]);
  767 
  768 #if     0
  769         if (!(bp->b_flags & B_READ) && (part_p->p_flag & V_RONLY))  {
  770                 printf("hd%d%c: attempt to write read-only partition\n",
  771                        unit,
  772                        'a' + partition);
  773                 bp->b_error = ENXIO;
  774                 goto bad;
  775         }
  776 #endif  /* 0 */
  777 
  778         /* if request is off the end or trying to write last block on out */
  779         size = (bp->b_flags & B_MD1) ? lp->d_secperunit : part_p->p_size;
  780         if ((bp->b_blkno > size) ||
  781             (bp->b_blkno == size & !(bp->b_flags & B_READ))) {
  782                 printf("hd%d%c: invalid block %d >= %d\n",
  783                        unit,
  784                        'a' + partition,
  785                        bp->b_blkno,
  786                        size);
  787                 bp->b_error = ENXIO;
  788                 goto bad;
  789         }
  790         if (bp->b_blkno == size) {
  791                 /* indicate (read) EOF by setting b_resid to b_bcount on last block */ 
  792                 bp->b_resid = bp->b_bcount;
  793                 goto done;
  794         }
  795         bp->b_cylin = ((bp->b_flags&B_MD1 ? 0 : part_p->p_offset) + bp->b_blkno)
  796                 / (lp->d_nsectors * lp->d_ntracks);
  797 
  798         opri = spl5();
  799         disksort(&hdunit[unit], bp);
  800         if (!hh.busy)
  801                 hdstart();
  802         splx(opri);
  803 
  804         return;
  805 
  806 bad:
  807         bp->b_flags |= B_ERROR;
  808 done:
  809         iodone(bp);
  810         return;
  811 
  812 }
  813 
  814 static hderror(struct buf *bp)
  815 {
  816         int unit = UNIT(bp->b_dev);
  817 
  818         if ((hh.status&0x8000) == 0 || ++hh.retry_count > hdparams[unit].retries) {
  819                 if(bp) {
  820                         /************************************************
  821                         * We have a problem with this block, set the    *
  822                         * error flag, terminate the operation and move  *
  823                         * on to the next request.                       *
  824                         * With every hard disk transaction error we set *
  825                         * the reset requested flag so that the contrlr  *
  826                         * is reset before next operation is started.    *
  827                         * A reset is a relatively long operation, the   *
  828                         * upper level routines are better qualified for *
  829                         * such an operation than the interrupt service  *
  830                         * routines.                                     *
  831                         ************************************************/
  832                         hdunit[hh.curdrive].b_actf = bp->av_forw;
  833                         bp->b_flags |= B_ERROR;
  834                         bp->b_resid = 0;
  835                         biodone(bp);
  836                         hh.busy = 0;
  837                         hdstart();
  838                 }
  839         } else {
  840                 /*
  841                  * retry the operation using the saved request block
  842                  */
  843                 rb[unit] = save_rb[unit];
  844                 abios_common_start(&rb[unit], params.Logical_id_flags);
  845         }
  846 }
  847 
  848 /*
  849  * The following function is used to get the proper physical
  850  * addresses for transfering data.
  851  */
  852 static u_int hd_max_page(struct buf *bp,
  853                           u_int baddr,
  854                           u_int *p_addr,
  855                           u_int max)
  856 {
  857         u_int   count = ((u_int)baddr) & (I386_PGBYTES - 1);
  858         u_int   old_addr;
  859         u_int   new_addr;
  860 
  861 
  862         if ((*p_addr = pmap_extract(get_pmap(bp), baddr)) == 0)
  863                 return(0);
  864 
  865         /* if the count is aligned, we can transfer a whole page. */
  866         if (count==0)
  867                 count = I386_PGBYTES;
  868         else
  869                 count = I386_PGBYTES - count;
  870 
  871         /* Now loop through and get the phisical address of each of the 
  872            following pages.  Break on the first non-contiguous page, or when
  873            we exceed count.
  874         */
  875 
  876         baddr += count;
  877         old_addr = *p_addr + count;
  878         while ((count <max) &&
  879             ((new_addr = pmap_extract(get_pmap(bp), baddr)) != 0) &&
  880             (new_addr == old_addr)) {
  881                 count += I386_PGBYTES;
  882                 baddr += I386_PGBYTES;
  883                 old_addr += I386_PGBYTES;
  884         }
  885 
  886         return (count > max) ? max : count;
  887 
  888 }
  889 
  890 /*
  891  * routine called from timeout code at lower priority
  892  * we just call hdintr with the provided parameter.
  893  */
  894 static void hdtimeout(int vec)
  895 {
  896         unsigned int  s = spl5();
  897         hdintr(vec);
  898         splx(s);
  899 }
  900 
  901 static void start_rw(long read)
  902 {
  903         unsigned int track, disk_block, xblk;
  904         u_int numblocks;
  905         unsigned int p_block;
  906         int function;
  907         paddr_t vert_addr;
  908         u_int   p_addr;
  909         register struct buf *bp, *dp;
  910         int     i;
  911         u_int   total;
  912         u_char  unit;
  913 
  914         dp = &hdunit[unit = hh.curdrive];
  915         bp = dp->b_actf;
  916 
  917 restart:
  918 
  919         hh.retry_count = 0; /* start of operation */
  920         rb[unit].r_current_req_blck_len = sizeof(struct Gd_request);
  921         rb[unit].r_logical_id = hdparams[unit].lid;
  922         rb[unit].r_unit = hdparams[unit].unit;
  923         rb[unit].r_return_code = ABIOS_UNDEFINED;
  924 
  925         vert_addr = hh.rw_addr + (hh.blockcount * SECSIZE);
  926         hh.vert_addr = vert_addr;
  927         if ((u_int)vert_addr & 0x1ff) {
  928                 hh.un_aligned = 1;
  929                 vert_addr = (paddr_t)u_buf[unit];
  930         }
  931         p_block = hh.physblock + hh.blockcount;
  932 
  933         numblocks = hd_max_page(bp, vert_addr, &p_addr, 
  934             ((hh.blocktotal - hh.blockcount)*SECSIZE));
  935         numblocks  = ((numblocks + 511) >> 9);
  936 
  937         assert(numblocks > 0 || (bp->b_flags&B_RESET));
  938 
  939         hh.phys_addr = p_addr;
  940         hh.blockcount += numblocks;
  941         hh.numblocks = numblocks;
  942 
  943         switch (read) {
  944 
  945         case B_READ:
  946                 rb[unit].r_function = ABIOS_READ;
  947                 function = ABIOS_READ;
  948                 rb[unit].request_header.Request_Block_Flags = 0;
  949                 rb[unit].request_header.ELA_Offset = 0;
  950                 gd_physical_ptr(rb[unit]) = p_addr;
  951                 gd_logical_ptr(rb[unit]) = 0;
  952                 gd_blocks_to_read(rb[unit]) = numblocks; /*hh.blocktotal;*/
  953                 gd_relative_block_address(rb[unit]) = p_block; /*hh.physblock;*/
  954                 gd_caching_ok(rb[unit]) = GD_DONT_CACHE;
  955                 GD_SET_RESERVED_ABIOS_READ(rb[unit]);
  956                 break;
  957 
  958         case B_RESET:
  959                 rb[unit].r_function = ABIOS_RESET;
  960                 function = ABIOS_RESET;
  961                 GD_SET_RESERVED_ABIOS_RESET(rb[unit]);
  962                 break;
  963 
  964         default:
  965                 rb[unit].r_function = hd_write_verify ? ABIOS_WRITE_VERIFY : ABIOS_WRITE;
  966                 function = hd_write_verify ? ABIOS_WRITE_VERIFY : ABIOS_WRITE;
  967                 rb[unit].request_header.Request_Block_Flags = 0;
  968                 rb[unit].request_header.ELA_Offset = 0;
  969                 gd_physical_ptr(rb[unit]) = p_addr;
  970                 gd_logical_ptr(rb[unit]) = 0;
  971                 gd_blocks_to_read(rb[unit]) = numblocks; /*hh.blocktotal;*/
  972                 gd_relative_block_address(rb[unit]) = p_block; /*hh.physblock;*/
  973                 gd_caching_ok(rb[unit]) = GD_DONT_CACHE;
  974                 GD_SET_RESERVED_ABIOS_WRITE(rb[unit]);
  975                 if(hh.un_aligned) {
  976                     i = 0;
  977                     total = 0;
  978                     while (save_addr[unit][i].phys_addr != NULL) {
  979                         bcopy(phystokv(save_addr[unit][i].phys_addr), 
  980                             (caddr_t)((u_int)u_buf[unit] + total), 
  981                             save_addr[unit][i].count);
  982                         total += save_addr[unit][i].count;
  983                         i++;
  984                     }
  985                 }
  986                 break;
  987         }
  988 
  989         save_rb[unit] = rb[unit]; /* save in case of retry */
  990 
  991         abios_common_start(&rb[unit], params.Logical_id_flags);
  992 
  993         hh.status = rb[unit].r_return_code; 
  994 
  995         switch (hh.status) {
  996                 
  997                 case ABIOS_STAGE_ON_INT:
  998                         break;
  999 
 1000                 case ABIOS_STAGE_ON_TIME:
 1001                         timeout(hdtimeout,0,(gd_wait_time(rb[unit])/1000000)*HZ);
 1002                         break;
 1003 
 1004                 case (ABIOS_NOT_MY_INT | ABIOS_STAGE_ON_INT):
 1005                         /* Eventually we need to chain to the next */
 1006                         /* interrupt. */
 1007                         break;
 1008 
 1009                 case ABIOS_DONE:
 1010                         if (hh.blockcount == hh.blocktotal) {
 1011                             hh.blockcount = 0;
 1012                             hh.blockcount = 0;
 1013                             hh.phys_addr = 0;
 1014                             hh.vert_addr = 0;
 1015                             hh.numblocks = 0;
 1016                             dp->b_actf = bp->av_forw;
 1017                             bp->b_resid = 0;
 1018                             iodone(bp);
 1019                             hh.busy = 0;
 1020                             hdstart();
 1021                             break;
 1022                         }
 1023                         else {
 1024                             hh.phys_addr = 0;
 1025                             hh.vert_addr = 0;
 1026                             hh.numblocks = 0;
 1027                             goto restart;
 1028                         }
 1029 
 1030                 default:
 1031                         printf("start_rw: return code [%x]...\n", hh.status); 
 1032                         hd_error_decode(hh.status, "\n");
 1033         }       
 1034 
 1035 }
 1036 
 1037 #define B_FLAGS_FMT "\2\1READ\2DONE\3ERROR\4BUSY\5PHYS\6XXX\7WANTED\10AGE\11ASYNC\12DELWRI\13TAPE\20CACHE\21INVAL\22LOCKED\23HEAD\24USELESS\25BAD\27RAW\30NOCACHE\31PRIVATE\32WRITEV\33HWRELOC\34WANTFREE"
 1038 
 1039 int hd_bp_all = 0;
 1040 
 1041 static void hd_bp_print(char *msg1, struct buf *bp, char *msg2)
 1042 {
 1043         printf("%sbp=%x ", msg1 ? msg1 : "", bp);
 1044         if (bp) {
 1045                 printf("b_dev=0x%x b_blkno=0x%x (%d) b_addr=0x%x b_bcount=0x%x b_flags=%b",
 1046                         bp->b_dev, bp->b_blkno, bp->b_blkno, bp->b_un.b_addr, bp->b_bcount,
 1047                         bp->b_flags,B_FLAGS_FMT);
 1048                 if (hd_bp_all) {
 1049                         printf(" b_forw=0x%x b_back=0x%x av_forw=0x%x av_back=0x%x b_bufsize=%d",
 1050                                 bp->b_forw, bp->b_back, bp->av_forw, bp->av_back,
 1051                                 bp->b_bufsize);
 1052                 }
 1053         }
 1054         if (msg2)
 1055                 printf(msg2);
 1056 }
 1057 
 1058 static struct hd_errors { int code; char *msg; } hd_err_codes [] = {
 1059         {0x00,  "timeout"},
 1060         {0x01,  "bad-command"},
 1061         {0x02,  "address-mark-not-found"},
 1062         {0x04,  "record-not-found"},
 1063         {0x05,  "reset-failed"},
 1064         {0x07,  "activity-failed"},
 1065         {0x0a,  "defective-sector"},
 1066         {0x0b,  "bad-track"},
 1067         {0x0d,  "invalid-sector"},
 1068         {0x0e,  "CAM-detected"},
 1069         {0x0f,  "DMA-arb-level-bad"},
 1070         {0x10,  "bad-ecc-error"},
 1071         {0x11,  "ecc-corrected"},
 1072         {0x20,  "bad-controller"},
 1073         {0x21,  "equipment-check"},
 1074         {0x40,  "bad-seek"},
 1075         {0x80,  "device-didn't-respond"},
 1076         {0xaa,  "drive-not-ready"},
 1077         {0xbb,  "undefined-error"},
 1078         {0xcc,  "write-fault"},
 1079         {0xff,  "incomplete-sense"},
 1080         {0xc000,"invalid LID"},
 1081         {0xc001,"invalid function"},
 1082         {0xc003,"invalid unit number"},
 1083         {0xc004,"invalid request block length"},
 1084         {0xc005,"invalid parameter"}
 1085 
 1086 };
 1087 
 1088 static hd_error_decode(int code, char *msg)
 1089 {
 1090         int i;
 1091         int n = code&0x00ff;
 1092 
 1093         if ((code&0x8000) == 0) {
 1094                 char *p;
 1095                 switch(code)
 1096                 {
 1097                 case 0:
 1098                         p = "completed ok";
 1099                         break;
 1100                 case 1:
 1101                         p = "stage on int";
 1102                         break;
 1103                 case 2:
 1104                         p = "stage on time";
 1105                         break;
 1106                 case 5:
 1107                         p = "not my int";
 1108                         break;
 1109                 default:
 1110                         printf("unknown[0x%x]%s", code, msg);
 1111                         return;
 1112                 }
 1113                 printf("%s%s", p, msg);
 1114                 return;
 1115         }
 1116         if (code&0x4000) {
 1117                 printf("PARAMETER ");
 1118                 n = code;
 1119         }
 1120         if (code&0x2000)
 1121                 printf("TIME-OUT ");
 1122         if (code&0x1000)
 1123                 printf("DEVICE ");
 1124         if (code&0x100)
 1125                 printf("RETRYABLE ");
 1126         printf("ERROR ");
 1127         for (i=0; i<(sizeof hd_err_codes)/(sizeof hd_err_codes[0]); ++i)
 1128                 if (hd_err_codes[i].code == n)
 1129                         {
 1130                         printf("%s%s", hd_err_codes[i].msg, msg);
 1131                         return;
 1132                         }
 1133         printf("unknown[0x%x]%s", code, msg);
 1134 }
 1135 
 1136 static int hdintr(int vec)
 1137 {
 1138         register struct buf *bp, *dp;
 1139         int i;
 1140         unsigned long   count, total;
 1141         unsigned char unit = hh.curdrive;
 1142         int rc = 1;                             /* assume it is ours */
 1143 
 1144         if (!hh.busy && !hh.restoring) {
 1145                 printf("hdintr: false interrupt continuing . . .\n");
 1146                 printf("hdintr: hh.busy = %d, hh.restoring = %d\n",
 1147                         hh.busy, hh.restoring);
 1148                 printf("hdintr: hh.single_mode = %d, ",hh.single_mode);
 1149                 printf("hdintr: hh.physblock = %d, ",hh.physblock);
 1150                 printf("hh.blockcount = %d, ",hh.blockcount);
 1151                 printf("hh.blocktotal = %d\n",hh.blocktotal);
 1152                 return;
 1153         }
 1154 
 1155         abios_common_interrupt(&rb[unit], params.Logical_id_flags);
 1156 
 1157         hh.status = rb[unit].r_return_code; 
 1158 
 1159         dp = &hdunit[hh.curdrive];
 1160         bp = dp->b_actf;
 1161 
 1162         switch (hh.status) {
 1163         
 1164         case ABIOS_STAGE_ON_INT:
 1165                 break;
 1166 
 1167         case ABIOS_STAGE_ON_TIME:
 1168                 timeout(hdtimeout, 0, (gd_wait_time(rb[unit])/1000000)*HZ);
 1169                 break;
 1170 
 1171         case ABIOS_NOT_MY_INT:
 1172         case (ABIOS_NOT_MY_INT | ABIOS_STAGE_ON_INT):
 1173                 rc = 0;
 1174                 break;
 1175 
 1176         case ABIOS_DONE:
 1177                 if (hh.un_aligned) {
 1178                     hh.un_aligned = 0;
 1179                     if (bp->b_flags & B_READ) {
 1180                         unit = UNIT((bp->b_dev));
 1181                         i = 0;
 1182                         total = 0;
 1183                         while (save_addr[unit][i].phys_addr) {
 1184                             bcopy( 
 1185                                 (caddr_t)((u_int)u_buf[unit] + total), 
 1186                                 phystokv(save_addr[unit][i].phys_addr),
 1187                                 save_addr[unit][i].count);
 1188                             total += save_addr[unit][i].count;
 1189                             i++;
 1190                         }
 1191                     }
 1192                 }
 1193                 if (hh.blockcount == hh.blocktotal) {
 1194                         dp->b_actf = bp->av_forw;
 1195                         bp->b_resid = 0;
 1196                         if (hh.retry_count)
 1197                                 printf("retry worked!\n");
 1198                         biodone(bp);
 1199                         hh.busy = 0;
 1200                         hdstart();
 1201                 }
 1202                 else {
 1203                         start_rw(bp->b_flags & (B_READ|B_RESET));
 1204                 }
 1205                 break;
 1206 
 1207         default:
 1208                 printf("[HD Driver] return code [%x]...", hh.status);
 1209                 hd_error_decode(hh.status,""); 
 1210                 hd_bp_print(" ", bp, "\n");
 1211                 hderror(bp);
 1212                 break;
 1213 
 1214         }
 1215 
 1216         return rc;
 1217 
 1218 }
 1219 
 1220 #endif NHD > 0

Cache object: b0c0fe5d11664dd43c86ed2c6587410c


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