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