-/* up.c 4.30 81/03/07 */
+/* up.c 4.53 82/05/27 */
#include "up.h"
#if NSC > 0
* UNIBUS disk driver with overlapped seeks and ECC recovery.
*
* TODO:
- * Add reading of bad sector information and disk layout from sector 1
* Add bad sector forwarding code
- * Check multiple drive handling
- * Check unibus reset code
- * Check that offset recovery code, etc works
+ * Check that offset recovery code works
*/
-#define DELAY(N) { register int d; d = N; while (--d > 0); }
#include "../h/param.h"
#include "../h/systm.h"
daddr_t nblocks;
int cyloff;
} up_sizes[8] = {
+#ifdef ERNIE
+ 49324, 0, /* A=cyl 0 thru 26 */
+#else
15884, 0, /* A=cyl 0 thru 26 */
+#endif
33440, 27, /* B=cyl 27 thru 81 */
495520, 0, /* C=cyl 0 thru 814 */
15884, 562, /* D=cyl 562 thru 588 */
55936, 589, /* E=cyl 589 thru 680 */
- 81472, 681, /* F=cyl 681 thru 814 */
- 153824, 562, /* G=cyl 562 thru 814 */
+#ifndef NOBADSECT
+ 81376, 681, /* F=cyl 681 thru 814 */
+ 153728, 562, /* G=cyl 562 thru 814 */
+#else
+ 81472, 681,
+ 153824, 562,
+#endif
291346, 82, /* H=cyl 82 thru 561 */
}, fj_sizes[8] = {
15884, 0, /* A=cyl 0 thru 49 */
0, 0,
0, 0,
0, 0,
- 213760, 155, /* H=cyl 155 thru 822 */
+#ifndef NOBADSECT
+ 213664, 155, /* H=cyl 155 thru 822 */
+#else
+ 213760, 155,
+#endif
+}, upam_sizes[8] = {
+ 15884, 0, /* A=cyl 0 thru 31 */
+ 33440, 32, /* B=cyl 32 thru 97 */
+ 524288, 0, /* C=cyl 0 thru 1023 */
+ 27786, 668,
+ 27786, 723,
+ 125440, 778,
+ 181760, 668, /* G=cyl 668 thru 1022 */
+ 291346, 98, /* H=cyl 98 thru 667 */
};
/* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
-#define _upSDIST 2 /* 1.0 msec */
+/*
+ * On a 780 upSDIST could be 2, but
+ * in the interest of 750's...
+ */
+#define _upSDIST 3 /* 1.5 msec */
#define _upRDIST 4 /* 2.0 msec */
int upSDIST = _upSDIST;
int upprobe(), upslave(), upattach(), updgo(), upintr();
struct uba_ctlr *upminfo[NSC];
struct uba_device *updinfo[NUP];
-struct uba_device *upip[NSC][4];
+#define UPIPUNITS 8
+struct uba_device *upip[NSC][UPIPUNITS]; /* fuji w/fixed head gives n,n+4 */
u_short upstd[] = { 0776700, 0774400, 0776300, 0 };
struct uba_driver scdriver =
32, 19, 32*19, 823, up_sizes, /* 9300/cdc */
/* 9300 actually has 815 cylinders... */
32, 10, 32*10, 823, fj_sizes, /* fujitsu 160m */
+ 32, 16, 32*16, 1024, upam_sizes, /* ampex capricorn */
};
u_char up_offset[16] = {
- UP_P400, UP_M400, UP_P400, UP_M400, UP_P800, UP_M800, UP_P800, UP_M800,
- UP_P1200, UP_M1200, UP_P1200, UP_M1200, 0, 0, 0, 0
+ UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400,
+ UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800,
+ UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200,
+ 0, 0, 0, 0
};
struct buf rupbuf[NUP];
upaddr->upcs1 = 0; /* conservative */
upaddr->upcs2 = ui->ui_slave;
- if (upaddr->upcs2&UP_NED) {
+ upaddr->upcs1 = UP_NOP|UP_GO;
+ if (upaddr->upcs2&UPCS2_NED) {
upaddr->upcs1 = UP_DCLR|UP_GO;
return (0);
}
upattach(ui)
register struct uba_device *ui;
{
-#ifdef notdef
register struct updevice *upaddr;
-#endif
if (upwstart == 0) {
timeout(upwatch, (caddr_t)0, hz);
dk_mspw[ui->ui_dk] = .0000020345;
upip[ui->ui_ctlr][ui->ui_slave] = ui;
up_softc[ui->ui_ctlr].sc_ndrive++;
-#ifdef notdef
upaddr = (struct updevice *)ui->ui_addr;
upaddr->upcs1 = 0;
upaddr->upcs2 = ui->ui_slave;
- upaddr->uphr = -1;
- /* ... */
- if (upaddr-> ... == 10)
- ui->ui_type = 1;
-#endif
+ upaddr->uphr = UPHR_MAXTRAK;
+ if (upaddr->uphr == 9)
+ ui->ui_type = 1; /* fujitsu hack */
+ else if (upaddr->uphr == 15)
+ ui->ui_type = 2; /* ampex hack */
+ upaddr->upcs2 = UPCS2_CLR;
+/*
+ upaddr->uphr = UPHR_MAXCYL;
+ printf("maxcyl %d\n", upaddr->uphr);
+ upaddr->uphr = UPHR_MAXTRAK;
+ printf("maxtrak %d\n", upaddr->uphr);
+ upaddr->uphr = UPHR_MAXSECT;
+ printf("maxsect %d\n", upaddr->uphr);
+*/
}
upstrategy(bp)
* If drive has just come up,
* setup the pack.
*/
- if ((upaddr->upds & UP_VV) == 0) {
+ if ((upaddr->upds & UPDS_VV) == 0) {
/* SHOULD WARN SYSTEM THAT THIS HAPPENED */
upaddr->upcs1 = UP_IE|UP_DCLR|UP_GO;
upaddr->upcs1 = UP_IE|UP_PRESET|UP_GO;
- upaddr->upof = UP_FMT22;
+ upaddr->upof = UPOF_FMT22;
didie = 1;
}
/*
* If drive is offline, forget about positioning.
*/
- if ((upaddr->upds & (UP_DPR|UP_MOL)) != (UP_DPR|UP_MOL))
+ if ((upaddr->upds & (UPDS_DPR|UPDS_MOL)) != (UPDS_DPR|UPDS_MOL))
goto done;
/*
* If there is only one drive,
* Check that it is ready and online
*/
waitdry = 0;
- while ((upaddr->upds&UP_DRY) == 0) {
+ while ((upaddr->upds&UPDS_DRY) == 0) {
if (++waitdry > 512)
break;
upwaitdry++;
}
- if ((upaddr->upds & UP_DREADY) != UP_DREADY) {
+ if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
printf("up%d: not ready", dkunit(bp));
- if ((upaddr->upds & UP_DREADY) != UP_DREADY) {
+ if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
printf("\n");
um->um_tab.b_active = 0;
um->um_tab.b_errcnt = 0;
*/
printf(" (flakey)\n");
}
- /*
- * After 16th retry, do offset positioning
- */
- if (um->um_tab.b_errcnt >= 16 && (bp->b_flags&B_READ) != 0) {
- upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | UP_FMT22;
- upaddr->upcs1 = UP_IE|UP_OFFSET|UP_GO;
- while (upaddr->upds & UP_PIP)
- DELAY(25);
- }
/*
* Setup for the transfer, and get in the
* UNIBUS adaptor queue.
else
cmd = UP_IE|UP_WCOM|UP_GO;
um->um_cmd = cmd;
- ubago(ui);
+ (void) ubago(ui);
return (1);
}
{
register struct updevice *upaddr = (struct updevice *)um->um_addr;
+ um->um_tab.b_active = 2; /* should now be 2 */
upaddr->upba = um->um_ubinfo;
upaddr->upcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
}
* interrupt for attention status on seeking drives.
* Just service them.
*/
- if (um->um_tab.b_active == 0) {
+ if (um->um_tab.b_active != 2 && !sc->sc_recal) {
if (upaddr->upcs1 & UP_TRE)
upaddr->upcs1 = UP_TRE;
goto doattn;
}
+ um->um_tab.b_active = 1;
/*
* Get device and block structures, and a pointer
* to the uba_device for the drive. Select the drive.
* Check for and process errors on
* either the drive or the controller.
*/
- if ((upaddr->upds&UP_ERR) || (upaddr->upcs1&UP_TRE)) {
+ if ((upaddr->upds&UPDS_ERR) || (upaddr->upcs1&UP_TRE)) {
waitdry = 0;
- while ((upaddr->upds & UP_DRY) == 0) {
+ while ((upaddr->upds & UPDS_DRY) == 0) {
if (++waitdry > 512)
break;
upwaitdry++;
}
- if (upaddr->uper1&UP_WLE) {
+ if (upaddr->uper1&UPER1_WLE) {
/*
* Give up on write locked devices
* immediately.
* Otherwise fall through and retry the transfer
*/
um->um_tab.b_active = 0; /* force retry */
- if ((upaddr->uper1&(UP_DCK|UP_ECH))==UP_DCK)
+ if ((upaddr->uper1&(UPER1_DCK|UPER1_ECH))==UPER1_DCK)
if (upecc(ui))
return;
}
*/
upaddr->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;
needie = 0;
- if ((um->um_tab.b_errcnt&07) == 4) {
+ if ((um->um_tab.b_errcnt&07) == 4 && um->um_tab.b_active == 0) {
upaddr->upcs1 = UP_RECAL|UP_IE|UP_GO;
- um->um_tab.b_active = 1;
- sc->sc_recal = 1;
- return;
+ sc->sc_recal = 0;
+ goto nextrecal;
}
}
/*
- * Done retrying transfer... release
- * resources... if we were recalibrating,
- * then retry the transfer.
- * Mathematical note: 28%8 != 4.
+ * Advance recalibration finite state machine
+ * if recalibrate in progress, through
+ * RECAL
+ * SEEK
+ * OFFSET (optional)
+ * RETRY
*/
- ubadone(um);
- if (sc->sc_recal) {
+ switch (sc->sc_recal) {
+
+ case 1:
+ upaddr->updc = bp->b_cylin;
+ upaddr->upcs1 = UP_SEEK|UP_IE|UP_GO;
+ goto nextrecal;
+ case 2:
+ if (um->um_tab.b_errcnt < 16 || (bp->b_flags&B_READ) == 0)
+ goto donerecal;
+ upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | UPOF_FMT22;
+ upaddr->upcs1 = UP_IE|UP_OFFSET|UP_GO;
+ goto nextrecal;
+ nextrecal:
+ sc->sc_recal++;
+ um->um_tab.b_active = 1;
+ return;
+ donerecal:
+ case 3:
sc->sc_recal = 0;
- um->um_tab.b_active = 0; /* force retry */
+ um->um_tab.b_active = 0;
+ break;
}
/*
* If still ``active'', then don't need any more retries.
* return to centerline.
*/
if (um->um_tab.b_errcnt >= 16) {
- upaddr->upof = UP_FMT22;
+ upaddr->upof = UPOF_FMT22;
upaddr->upcs1 = UP_RTC|UP_GO|UP_IE;
- while (upaddr->upds & UP_PIP)
+ while (upaddr->upds & UPDS_PIP)
DELAY(25);
needie = 0;
}
needie = 0;
}
as &= ~(1<<ui->ui_slave);
+ /*
+ * Release unibus resources and flush data paths.
+ */
+ ubadone(um);
doattn:
/*
* Process other units which need attention.
* the unit start routine to place the slave
* on the controller device queue.
*/
- for (unit = 0; as; as >>= 1, unit++)
- if (as & 1) {
- upaddr->upas = 1<<unit;
- if (upustart(upip[sc21][unit]))
- needie = 0;
- }
+ while (unit = ffs(as)) {
+ unit--; /* was 1 origin */
+ as &= ~(1<<unit);
+ upaddr->upas = 1<<unit;
+ if (unit < UPIPUNITS && upustart(upip[sc21][unit]))
+ needie = 0;
+ }
/*
* If the controller is not transferring, but
* there are devices ready to transfer, start
printf("up%d%c: soft ecc sn%d\n", dkunit(bp),
'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
mask = up->upec2;
+#ifdef UPECCDEBUG
+ printf("npf %d reg %x o %d mask %o pos %d\n", npf, reg, o, mask,
+ up->upec1);
+#endif
/*
* Flush the buffered data path, and compute the
* byte and bit position of the error. The variable i
while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
(byte & PGOFSET);
+#ifdef UPECCDEBUG
+ printf("addr %x map reg %x\n",
+ addr, *(int *)(&ubp->uba_map[reg+btop(byte)]));
+ printf("old: %x, ", getmemc(addr));
+#endif
putmemc(addr, getmemc(addr)^(mask<<bit));
+#ifdef UPECCDEBUG
+ printf("new: %x\n", getmemc(addr));
+#endif
byte++;
i++;
bit -= 8;
}
- um->um_tab.b_active++; /* Either complete or continuing... */
if (up->upwc == 0)
return (0);
/*
up->upba = ubaddr;
cmd = (ubaddr >> 8) & 0x300;
cmd |= UP_IE|UP_GO|UP_RCOM;
+ um->um_tab.b_active = 2; /* continuing transfer ... */
up->upcs1 = cmd;
#endif
return (1);
um->um_tab.b_active = 0;
um->um_tab.b_actf = um->um_tab.b_actl = 0;
up_softc[sc21].sc_recal = 0;
+ up_softc[sc21].sc_wticks = 0;
if (um->um_ubinfo) {
printf("<%d>", (um->um_ubinfo>>28)&0xf);
ubadone(um);
}
- ((struct updevice *)(um->um_addr))->upcs2 = UP_CLR;
+ ((struct updevice *)(um->um_addr))->upcs2 = UPCS2_CLR;
for (unit = 0; unit < NUP; unit++) {
if ((ui = updinfo[unit]) == 0)
continue;
{
struct updevice *upaddr;
char *start;
- int num, blk, unit, i;
+ int num, blk, unit;
struct size *sizes;
register struct uba_regs *uba;
register struct uba_device *ui;
register short *rp;
struct upst *st;
+ register int retry;
unit = minor(dev) >> 3;
if (unit >= NUP)
uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
ubainit(uba);
upaddr = (struct updevice *)ui->ui_physaddr;
- DELAY(2000000);
+ DELAY(5000000);
num = maxfree;
- start = 0;
upaddr->upcs2 = unit;
DELAY(100);
- if ((upaddr->upcs1&UP_DVA) == 0)
- return (EFAULT);
- if ((upaddr->upds & UP_VV) == 0) {
- upaddr->upcs1 = UP_DCLR|UP_GO;
- upaddr->upcs1 = UP_PRESET|UP_GO;
- upaddr->upof = UP_FMT22;
- }
- if ((upaddr->upds & UP_DREADY) != UP_DREADY)
+ upaddr->upcs1 = UP_DCLR|UP_GO;
+ upaddr->upcs1 = UP_PRESET|UP_GO;
+ upaddr->upof = UPOF_FMT22;
+ retry = 0;
+ do {
+ DELAY(25);
+ if (++retry > 527)
+ break;
+ } while ((upaddr->upds & UP_RDY) == 0);
+ if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY)
return (EFAULT);
+ start = 0;
st = &upst[ui->ui_type];
sizes = phys(struct size *, st->sizes);
if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
*--rp = 0;
*--rp = -blk*NBPG / sizeof (short);
*--rp = UP_GO|UP_WCOM;
+ retry = 0;
do {
DELAY(25);
+ if (++retry > 527)
+ break;
} while ((upaddr->upcs1 & UP_RDY) == 0);
- if (upaddr->upcs1&UP_ERR)
+ if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
+ printf("up%d: not ready", unit);
+ if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
+ printf("\n");
+ return (EIO);
+ }
+ printf(" (flakey)\n");
+ }
+ if (upaddr->upds&UPDS_ERR)
return (EIO);
start += blk*NBPG;
num -= blk;