WD INITIALIZATION AND PARTITION BOUNDARY
[unix-history] / usr / src / sys.386bsd / i386 / isa / wd.c
index f20ff0e..775284a 100644 (file)
  *
  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
  * --------------------         -----   ----------------------
  *
  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
  * --------------------         -----   ----------------------
- * CURRENT PATCH LEVEL:         2       00021
+ * CURRENT PATCH LEVEL:         4       00072
  * --------------------         -----   ----------------------
  *
  * --------------------         -----   ----------------------
  *
+ * 17 Sep 92   Frank Maclachlan        Fixed I/O error reporting on raw device
  * 31 Jul 92   Christoph Robitschko    Fixed second disk recognition,
  *                                     bzero of malloced memory for warm
  *                                     boot problem.
  * 19 Aug 92    Frank Maclachlan       Fixed bug when first sector of a
  *                                     multisector read is in bad144 table.
  * 31 Jul 92   Christoph Robitschko    Fixed second disk recognition,
  *                                     bzero of malloced memory for warm
  *                                     boot problem.
  * 19 Aug 92    Frank Maclachlan       Fixed bug when first sector of a
  *                                     multisector read is in bad144 table.
+ * 17 Jan 93   B. Evans & A.Chernov    Fixed bugs from previous patches,
+ *                                     driver initialization, and cylinder
+ *                                     boundary conditions.
  */
 
 /* TODO:peel out buffer at low ipl, speed improvement */
  */
 
 /* TODO:peel out buffer at low ipl, speed improvement */
@@ -169,9 +173,8 @@ wdprobe(struct isa_device *dvp)
        wdc = du->dk_port = dvp->id_iobase;
        
        /* check if we have registers that work */
        wdc = du->dk_port = dvp->id_iobase;
        
        /* check if we have registers that work */
-       outb(wdc+wd_error, 0x5a) ;      /* error register not writable */
-       outb(wdc+wd_cyl_lo, 0xa5) ;     /* but all of cyllo are implemented */
-       if(inb(wdc+wd_error) == 0x5a || inb(wdc+wd_cyl_lo) != 0xa5)
+       outb(wdc+wd_cyl_lo, 0xa5) ;     /* wd_cyl_lo is read/write */
+       if(inb(wdc+wd_cyl_lo) != 0xa5)
                goto nodevice;
 
        /* reset the device */
                goto nodevice;
 
        /* reset the device */
@@ -236,8 +239,9 @@ wdattach(struct isa_device *dvp)
                        du->dk_unit = unit;
                }
                else {
                        du->dk_unit = unit;
                }
                else {
-                       free(du, M_TEMP);
-                       wddrives[unit] = 0;
+                       /* old ST506 controller */
+                       printf(" %d:<wdgetctlr failed, assuming OK>",
+                              unit);
                }
        }
        return(1);
                }
        }
        return(1);
@@ -396,12 +400,11 @@ loop:
        lp = &du->dk_dd;
        secpertrk = lp->d_nsectors;
        secpercyl = lp->d_secpercyl;
        lp = &du->dk_dd;
        secpertrk = lp->d_nsectors;
        secpercyl = lp->d_secpercyl;
+       if ((du->dk_flags & DKFL_BSDLABEL) != 0 && wdpart(bp->b_dev) != WDRAW)
+               blknum += lp->d_partitions[wdpart(bp->b_dev)].p_offset;
        cylin = blknum / secpercyl;
        head = (blknum % secpercyl) / secpertrk;
        sector = blknum % secpertrk;
        cylin = blknum / secpercyl;
        head = (blknum % secpercyl) / secpertrk;
        sector = blknum % secpertrk;
-       if ((du->dk_flags & DKFL_BSDLABEL) != 0 && wdpart(bp->b_dev) != WDRAW)
-               cylin += lp->d_partitions[wdpart(bp->b_dev)].p_offset
-                               / secpercyl;
 
        /* 
         * See if the current block is in the bad block list.
 
        /* 
         * See if the current block is in the bad block list.
@@ -558,6 +561,7 @@ wdintr(struct intrframe wdif)
                }
 #ifdef B_FORMAT
                if (bp->b_flags & B_FORMAT) {
                }
 #ifdef B_FORMAT
                if (bp->b_flags & B_FORMAT) {
+                       bp->b_error = EIO;              /* 17 Sep 92*/
                        bp->b_flags |= B_ERROR;
                        goto done;
                }
                        bp->b_flags |= B_ERROR;
                        goto done;
                }
@@ -578,6 +582,7 @@ wdintr(struct intrframe wdif)
                                                inb(wdc+wd_error), WDERR_BITS);
 #endif
                                }
                                                inb(wdc+wd_error), WDERR_BITS);
 #endif
                                }
+                               bp->b_error = EIO;      /* 17 Sep 92*/
                                bp->b_flags |= B_ERROR; /* flag the error */
                        }
                } else if((du->dk_flags&DKFL_QUIET) == 0) {
                                bp->b_flags |= B_ERROR; /* flag the error */
                        }
                } else if((du->dk_flags&DKFL_QUIET) == 0) {
@@ -800,6 +805,11 @@ wdcontrol(register struct buf *bp)
 
                outb(wdc+wd_sdh, WDSD_IBM | (unit << 4));
                wdtab.b_active = 1;
 
                outb(wdc+wd_sdh, WDSD_IBM | (unit << 4));
                wdtab.b_active = 1;
+
+               /* wait for drive and controller to become ready */
+               for (i = 1000000; (inb(wdc+wd_status) & (WDCS_READY|WDCS_BUSY))
+                                 != WDCS_READY && i-- != 0; )
+                       ;
                outb(wdc+wd_command, WDCC_RESTORE | WD_STEP);
                du->dk_state++;
                splx(s);
                outb(wdc+wd_command, WDCC_RESTORE | WD_STEP);
                du->dk_state++;
                splx(s);
@@ -813,8 +823,10 @@ wdcontrol(register struct buf *bp)
                                        stat, WDCS_BITS, inb(wdc+wd_error),
                                        WDERR_BITS);
                        }
                                        stat, WDCS_BITS, inb(wdc+wd_error),
                                        WDERR_BITS);
                        }
-                       if (++wdtab.b_errcnt < RETRIES)
+                       if (++wdtab.b_errcnt < RETRIES) {
+                               du->dk_state = WANTOPEN;
                                goto tryagainrecal;
                                goto tryagainrecal;
+                       }
                        bp->b_error = ENXIO;    /* XXX needs translation */
                        goto badopen;
                }
                        bp->b_error = ENXIO;    /* XXX needs translation */
                        goto badopen;
                }