Hard disk problem solved

From: Peter Holzer <hp_at_nospam.org>
Date: Thu Sep 09 1993 - 04:28:44 PDT

Yesterday I managed to coax my hard drive into seeking at maximum
speed. Here are the patches to wd.c and wd.h. They also limit read and
write operations to a single track, because my drive obviously had
trouble with track switching.

*** wd.c 1993/08/02 20:17:07 1.5
--- wd.c 1993/09/08 23:06:42
***************
*** 14,21 ****
  static int wd_cmd(int);
  static void wd_start(), wd_readp(int), wd_cmos(int),
          wd_parseparms(int, char *);
  
! uint first_unit; /* Lowerst unit # configured */
  
  /*
   * The parameters we read on each disk, and a flag to ask if we've
--- 14,22 ----
  static int wd_cmd(int);
  static void wd_start(), wd_readp(int), wd_cmos(int),
          wd_parseparms(int, char *);
+ static void wd_calibrate (int);
  
! uint first_unit; /* Lowest unit # configured */
  
  /*
   * The parameters we read on each disk, and a flag to ask if we've
***************
*** 23,28 ****
--- 24,30 ----
   */
  struct wdparms parm[NWD];
  char configed[NWD];
+ char calibrated[NWD];
  
  /*
   * Miscellaneous counters
***************
*** 160,165 ****
--- 162,168 ----
                  if (configed[unit]) {
                          uint s = parm[unit].w_size * SECSZ;
                          const uint m = 1024*1024;
+ int status;
  
                          printf("wd%d: %d.%dM\n", unit,
                                  s / m, (s % m) / (m/10));
***************
*** 167,172 ****
--- 170,176 ----
                          if (unit < first_unit) {
                                  first_unit = unit;
                          }
+ wd_calibrate (unit);
                  }
          }
          if (!found_first) {
***************
*** 239,249 ****
          /*
           * Given disk geometry, calculate parameters for next I/O
           */
          cyl = cur_sec / w->w_secpercyl;
          sect = cur_sec % w->w_secpercyl;
- lsect = w->w_secpercyl - sect;
          trk = sect / w->w_secpertrk;
          sect = (sect % w->w_secpertrk) + 1;
  
          /*
           * Transfer size--either the rest, or the remainder of this track
--- 243,255 ----
          /*
           * Given disk geometry, calculate parameters for next I/O
           */
+
+ if (!calibrated [cur_unit]) wd_calibrate (cur_unit);
          cyl = cur_sec / w->w_secpercyl;
          sect = cur_sec % w->w_secpercyl;
          trk = sect / w->w_secpertrk;
          sect = (sect % w->w_secpertrk) + 1;
+ lsect = w->w_secpertrk + 1 - sect;
  
          /*
           * Transfer size--either the rest, or the remainder of this track
***************
*** 564,566 ****
--- 570,630 ----
          w->w_size = w->w_secpercyl * w->w_cyls;
          configed[unit] = 1;
  }
+
+ /*
+ * specify: part one of drive calibration
+ */
+
+ static void wd_specify (int unit) {
+
+ cur_op = WDC_SPECIFY;
+ outportb(WD_PORT+WD_CTLR, 0);
+ outportb(WD_PORT+WD_ERROR, 0xFF);
+ outportb(WD_PORT+WD_SCNT, parm[unit].w_secpertrk);
+ outportb(WD_PORT+WD_SNUM, 0);
+ outportb(WD_PORT+WD_CYL0, 0);
+ outportb(WD_PORT+WD_CYL1, 0);
+ outportb(WD_PORT+WD_SDH,
+ WDSDH_EXT|WDSDH_512 | parm[unit].w_tracks | (unit << 4));
+ outportb(WD_PORT+WD_CMD,
+ WDC_SPECIFY);
+ }
+
+ /*
+ * calibrate: part two of drive calibration
+ */
+
+ static void
+ wd_calibrate (int unit)
+ {
+ int status;
+
+ cur_op = WDC_CALIBRATE;
+ outportb(WD_PORT+WD_CTLR, 0);
+ outportb(WD_PORT+WD_ERROR, 0xFF);
+ outportb(WD_PORT+WD_SCNT, parm[unit].w_secpertrk);
+ outportb(WD_PORT+WD_SNUM, 0);
+ outportb(WD_PORT+WD_CYL0, 0);
+ outportb(WD_PORT+WD_CYL1, 0);
+ outportb(WD_PORT+WD_SDH,
+ WDSDH_EXT|WDSDH_512 | 0 | (unit << 4));
+ outportb(WD_PORT+WD_CMD, WDC_CALIBRATE);
+
+ while (inportb (WD_PORT+WD_STATUS) & WDS_BUSY);
+ status = inportb (WD_PORT+WD_STATUS);
+ if (status & WDS_ERROR) {
+ printf ("calibrate %d: status %x, error %x\n",
+ unit, status, inportb (WD_PORT+WD_ERROR));
+ } else {
+ calibrated [unit] = 1;
+ }
+ }
+
+ char wd_c_rcs_id [] =
+ "$Id: wd.c 1.5.1.1 1993/09/08 23:04:51 hjp Exp $";
+ /* $Log: wd.c $
+ * Revision 1.5.1.1 1993/09/08 23:04:51 hjp
+ * Added calibration at start to set step rate to fastest value.
+ * Limited read ops to one track to avoid read errors at start of track.
+ *
+ */
*** wd.h 1993/08/02 20:17:58 1.4
--- wd.h 1993/09/08 23:08:42
***************
*** 2,8 ****
  #define _WD_H
  /*
   * wd.h
! * Wester Digital ST-506 type hard disk interface definitions
   */
  #include <sys/types.h>
  #include <sys/perm.h>
--- 2,8 ----
  #define _WD_H
  /*
   * wd.h
! * Western Digital ST-506 type hard disk interface definitions
   */
  #include <sys/types.h>
  #include <sys/perm.h>
***************
*** 36,43 ****
--- 36,47 ----
   * Status bits
   */
  #define WDS_ERROR 0x1 /* Error */
+ #define WDS_INDEX 0x2 /* Index pulse */
  #define WDS_ECC 0x4 /* Soft ECC error */
  #define WDS_DRQ 0x8 /* Data request */
+ #define WDS_SEEKCMPL 0x10 /* Seek completed */
+ #define WDS_WRITEFLT 0x20 /* Write fault */
+ #define WDS_READY 0x40 /* Ready (obviously not the same as not busy) */
  #define WDS_BUSY 0x80 /* Busy */
  
  /*
***************
*** 56,65 ****
  /*
   * Commands
   */
! #define WDC_READ 0x20 /* Command: read */
  #define WDC_WRITE 0x30 /* ...write */
  #define WDC_READP 0xEC /* ...read parameters */
- #define WDC_DIAG 0x90 /* Run controller diags */
  
  /*
   * Read parameters command (WDC_READP) returns this. I think this
--- 60,71 ----
  /*
   * Commands
   */
! #define WDC_CALIBRATE 0x10 /* Command: calibrate */
! #define WDC_READ 0x20 /* ...read */
  #define WDC_WRITE 0x30 /* ...write */
+ #define WDC_DIAG 0x90 /* ...run controller diags */
+ #define WDC_SPECIFY 0x91 /* ...specify parameters */
  #define WDC_READP 0xEC /* ...read parameters */
  
  /*
   * Read parameters command (WDC_READP) returns this. I think this
***************
*** 159,163 ****
--- 165,176 ----
  extern void wd_init(int, char **);
  extern void iodone();
  extern char configed[];
+
+ /* $Id: wd.h 1.4.1.1 1993/09/08 23:08:19 hjp Exp $
+ * $Log: wd.h $
+ * Revision 1.4.1.1 1993/09/08 23:08:19 hjp
+ * add calibrate and specify commands and missing bits from status
+ *
+ */
  
  #endif /* _WD_H */

-- 
|    _  | Peter J. Holzer                       | Think of it   |
| |_|_) | Technical University Vienna           | as evolution  |
| | |   | Computer Science/Real-Time Systems    | in action!    |
| __/   | hp@vmars.tuwien.ac.at                 |     Tony Rand |
Received on Thu Sep 9 04:38:32 1993

This archive was generated by hypermail 2.1.8 : Wed Sep 21 2005 - 19:37:12 PDT