USG_PG3/usr/source/io1/hp.c
#
/*
* RP04 disk driver
*/
#include "../head/param.h"
#include "../head/systm.h"
#include "../head/buf.h"
#include "../head/conf.h"
#include "../head/user.h"
#include "../head/userx.h"
#include "../head/elog.h"
#define NSECT 22 /* 22 sectors per track */
#define NTRACK 19
#define NCYL NSECT*NTRACK /* 418 sectors per cylinder */
struct hpregs {
int hpcs1; /* Control and Status register 1 */
int hpwc; /* Word count register */
int hpba; /* UNIBUS address register */
int hpda; /* Desired address register */
int hpcs2; /* Control and Status register 2*/
int hpds; /* Drive Status */
int hper1; /* Error register 1 */
int hpas; /* Attention Summary */
int hpla; /* Look ahead */
int hpdb; /* Data buffer */
int hpmr; /* Maintenance register */
int hpdt; /* Drive type */
int hpsn; /* Serial number */
int hpof; /* Offset register */
int hpdc; /* Desired Cylinder address register*/
int hpcc; /* Current Cylinder */
int hper2; /* Error register 2 */
int hper3; /* Error register 3 */
int hpec1; /* Burst error bit position */
int hpec2; /* Burst error bit pattern */
int hpbae; /* Bus address extension */
int hpcs3; /* Control and status register 3 */
};
#define HPADDR 0176700
#define NHP 2
struct {
char *nblocks;
int cyloff;
} hp_sizes[] {
23*NCYL, 0, /* 0: cyl 0 thru 22 incl. */
/* cyl 23 thru 43 incl. unused */
65535l, 44, /* 1: cyl 44 thru 200 incl. (158) */
65535l, 201, /* 2: cyl 201 thru 357 incl. */
50*NCYL, 358, /* 3: cyl 358 thru 407 incl. */
/* cyl 408 thru 410 incl. unused */
100*NCYL, 0, /* 4: cyl 0 thru 99 incl. */
100*NCYL, 100, /* 5: cyl 100 thru 199 incl. */
99*NCYL, 201, /* 6: cyl 201 thru 299 incl. */
100*NCYL, 300, /* 7: cyl 300 thru 399 incl. */
44*NCYL, 0, /* 8: cyl 0 thru 43 incl. */
65535l, 44, /* 9: cyl 44 thru 201 incl.(158) */
65535l, 202, /* 10: cyl 202 thru 359 incl.(158) */
48*NCYL, 360, /* 11: cyl 360 thru 407 incl. */
65535l, 408, /* 12: cyl 408 thru 565 incl.(158) */
65535l, 566, /* 13: cyl 566 thru 723 incl.(158) */
89*NCYL, 724, /* 14: cyl 724 thru 812 incl. */
/* cyl 813 thru 814 spare */
79*NCYL, 44, /* 15: cyl 44 thru 122 incl. */
79*NCYL, 123, /* 16: cyl 123 thru 201 incl. */
79*NCYL, 202, /* 17: cyl 202 thru 280 incl. */
79*NCYL, 281, /* 18: cyl 281 thru 359 incl. */
/* cyl 360 thru 379 spare */
28*NCYL, 380, /* 19: cyl 380 thru 407 incl. */
79*NCYL, 408, /* 20: cyl 408 thru 486 incl. */
79*NCYL, 487, /* 21: cyl 487 thru 565 incl. */
79*NCYL, 566, /* 22: cyl 566 thru 644 incl. */
79*NCYL, 645, /* 23: cyl 645 thru 723 incl. */
/* Negative Filesystems */
/* Backward version of first 8 filsys */
NCYL*23, -22, /* 24: cyl 0 thru 23 incl. rev. */
/* cyl 24 thru 43 incl. unused */
65535l, -200, /* 25: cyl 44 thru 200 incl. (158) */
65535l, -357, /* 26: cyl 201 thru 357 incl. (158) */
50*NCYL, -407, /* 27: cyl 358 thru 407 incl. rev. */
/* cyl 408 thru 410 incl. unused */
100*NCYL, -99, /* 28: cyl 0 thru 99 incl. rev. */
100*NCYL, -199, /* 29: cyl 100 thru 199 incl. rev. */
99*NCYL, -299, /* 30: cyl 201 thru 299 incl. rev. */
100*NCYL, -399, /* 31: cyl 300 thru 399 incl. rev. */
};
/*
* NOTE: THE SWAP AREA MAY NOT BE ON AN INVERTED DISK AREA
*/
struct devtab hptab;
struct buf rhpbuf;
struct iostat hpstat[NHP];
struct errtab hpetab { etabinit(E_BLK|E_RH70,NHP,HP,hpstat) };
/* Drive Commands */
#define GO 01
#define PRESET 020
#define RECAL 06
#define RCLR 010
#define VV 0100
#define OFFSET 014
#define READY 0200 /* hpds - drive ready */
#define PIP 020000 /* hpds - Positioning Operation in Progress */
#define ERR 040000 /* hpcs1 - composite error */
#define DU 040000 /* hper1 - Drive Unsafe */
#define DTE 010000 /* hper1 - Drive Timing Error */
#define OPI 020000 /* hper1 - Operation Incomplete */
/* Error Correction Code errors */
#define DCK 0100000 /* hper1 - Data Check error */
#define ECH 0100 /* hper1 - ECC hard error */
#define CLR 040 /* hpcs2 - Controller Clear */
#define FMT22 010000 /* hpof - 16 bit /word format */
/*
* Use av_back to save track+sector,
* b_resid for cylinder.
*/
#define trksec av_back
#define cylin b_resid
#define DK_N 2
hpopen(dev, flag)
{
if(dev.d_minor >= (NHP<<5))
u.u_error = ENXIO;
}
hpstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register char *p1, *p2;
char *p3;
bp = abp;
p3 = p1 = &hp_sizes[bp->b_dev.d_minor&037];
if(bp->b_blkno >= p1->nblocks){
if (bp->b_flags&B_READ)
bp->b_resid = bp->b_wcount;
else{
bp->b_flags =| B_ERROR;
bp->b_error = ENXIO;
}
iodone(bp);
return;
}
bp->av_forw = 0;
bp->cylin = p1->cyloff;
p1 = bp->b_blkno;
p2 = lrem(p1, 22);
p1 = ldiv(p1, 22);
bp->trksec = (p1%19)<<8 | p2;
bp->cylin =+ p1/19;
if(p3->cyloff < 0){
bp->cylin = -bp->cylin;
}
spl5();
if ((p1 = hptab.d_actf)==0)
hptab.d_actf = bp;
else {
for (; p2 = p1->av_forw; p1 = p2) {
if (p1->cylin <= bp->cylin
&& bp->cylin < p2->cylin
|| p1->cylin >= bp->cylin
&& bp->cylin > p2->cylin)
break;
}
bp->av_forw = p2;
p1->av_forw = bp;
}
if (hptab.d_active==0)
hpstart();
spl0();
}
hpstart()
{
register struct buf *bp;
register unit;
if ((bp = hptab.d_actf) == 0)
return;
hptab.d_active++;
unit = (bp->b_dev.d_minor>>5)&07;
HPADDR->hpcs2 = unit;
hpetab.e_aunit = &hpstat[unit];
if((HPADDR->hpds&VV) == 0) {
HPADDR -> hpcs1 = PRESET | GO;
HPADDR -> hpof = FMT22;
hpetab.e_aunit->io_misc++;
}
hpetab.e_aunit->io_ops++;
blkacty =| (1<<HP);
HPADDR->hpdc = bp->cylin;
rhstart(bp, &HPADDR->hpda, bp->trksec, &HPADDR->hpbae);
dk_busy =| 1<<DK_N;
dk_numb[DK_N] =+ 1;
dk_wds[DK_N] =+ (-bp->b_wcount>>5) & 03777;
}
hpintr()
{
register struct buf *bp;
struct hpregs hpregs[0];
int ctr;
if (hptab.d_active == 0)
return;
bp = hptab.d_actf;
hptab.d_active = 0;
blkacty =& ~(1<<HP);
dk_busy =& ~(1<<DK_N);
if (HPADDR->hpcs1 & ERR) { /* error bit */
/* deverror(bp, HPADDR->hpcs2);/**/
fmtblk(&hpetab,HPADDR,sizeof(hpregs[0])/2,bp);
if(HPADDR->hper1 & (DU|DTE|OPI)) {
HPADDR->hpcs2 = CLR;
HPADDR->hpcs1 = RECAL|GO;
hpetab.e_aunit->io_misc++;
ctr = 0;
while ((HPADDR->hpds&PIP) && --ctr);
}
HPADDR->hpcs1 = RCLR|GO;
if (hptab.d_errcnt < 10) {
if(hptab.d_errcnt++ == 0)
logerr(&hpetab,E_FIRST);
hpstart();
return;
}
bp->b_flags =| B_ERROR;
}
if(hpetab.e_emsg != NULL)
logerr(&hpetab,E_RETRY);
hptab.d_errcnt = 0;
hptab.d_actf = bp->av_forw;
bp->b_resid = HPADDR->hpwc;
iodone(bp);
hpstart();
}
hpread(dev)
{
register nblks;
register char *p1;
p1 = &hp_sizes[dev.d_minor&037];
nblks = p1->nblocks;
if(p1->cyloff<0){
if(negcyl(hpstrategy, &rhpbuf, dev, B_READ, nblks, NCYL))
return;
if(u.u_error)
return;
}
physio(hpstrategy, &rhpbuf, dev, B_READ, nblks);
}
hpwrite(dev)
{
register nblks;
register char *p1;
p1 = &hp_sizes[dev.d_minor&037];
nblks = p1->nblocks;
if(p1->cyloff<0){
if(negcyl(hpstrategy, &rhpbuf, dev, B_WRITE, nblks, NCYL))
return;
if(u.u_error)
return;
}
physio(hpstrategy, &rhpbuf, dev, B_WRITE, nblks);
}