* RP06/RM03/RM05 disk driver
int hpcs1
; /* control and Status register 1 */
int hpds
; /* Drive Status */
int hper1
; /* Error register 1 */
int hpmr
; /* Maintenance */
int hpas
; /* Attention Summary */
int hpda
; /* Desired address register */
int hpdt
; /* Drive type */
int hpla
; /* Look ahead */
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 */
15884, 0, /* A=cyl 0 thru 37 */
33440, 38, /* B=cyl 38 thru 117 */
340670, 0, /* C=cyl 0 thru 814 */
291346, 118, /* G=cyl 118 thru 814 */
15884, 0, /* A=cyl 0 thru 99 */
33440, 100, /* B=cyl 100 thru 309 */
131680, 0, /* C=cyl 0 thru 822 */
82080, 310, /* G=cyl 310 thru 822 */
15884, 0, /* A=cyl 0 thru 26 */
33440, 27, /* B=cyl 27 thru 81 */
500992, 0, /* C=cyl 0 thru 823 */
15884, 562, /* D=cyl 562 thru 588 */
55936, 589, /* E=cyl 589 thru 680 */
86944, 681, /* F=cyl 681 thru 823 */
159296, 562, /* G=cyl 562 thru 823 */
291346, 82, /* H=cyl 82 thru 561 */
P1200
, M1200
, P1200
, M1200
,
char hp_type
[NHP
]; /* drive type */
register unit
, xunit
, nspc
;
if ((mbaact
&(1<<HPMBANUM
)) == 0)
xunit
= minor(bp
->b_dev
) & 077;
if (hp_type
[unit
] == 0) {
/* determine device type */
hpaddr
= mbadev(HPMBA
, unit
);
/* record transfer rate (these are guesstimates secs/word) */
switch (hp_type
[unit
] = hpaddr
->hpdt
) {
case RM
: mspw
= .0000019728; break;
case RM5
: mspw
= .0000020345; break;
case RP
: mspw
= .0000029592; break;
if (HPDK_N
+ unit
<= HPDK_NMAX
)
dk_mspw
[HPDK_N
+unit
] = mspw
;
printf("hp: unknown device type 0%o\n", hp_type
[unit
]);
unit
= NHP
+1; /* force error */
(bn
= dkblock(bp
))+sz
> sizes
[xunit
&07].nblocks
) {
bp
->b_cylin
= bn
/nspc
+ sizes
[xunit
&07].cyloff
;
register struct buf
*bp
, *dp
;
register struct device
*hpaddr
;
((struct mba_regs
*)HPMBA
)->mba_cr
|= MBAIE
;
hpaddr
= mbadev(HPMBA
, 0);
if (unit
+HPDK_N
<= HPDK_NMAX
)
dk_busy
&= ~(1<<(unit
+HPDK_N
));
if((bp
=dp
->b_actf
) == NULL
)
hpaddr
= mbadev(HPMBA
, unit
);
if((hpaddr
->hpds
& VV
) == 0) {
hpaddr
->hpcs1
= PRESET
|GO
;
if ((hpaddr
->hpds
& (DPR
|MOL
)) != (DPR
|MOL
))
sn
= bn
%(NRMSECT
*NRMTRAC
);
sn
= (sn
+NRMSECT
-hpSDIST
)%NRMSECT
;
sn
= (sn
+NRMSECT
-hpSDIST
)%NRMSECT
;
sn
= (sn
+NSECT
-hpSDIST
)%NSECT
;
if(cn
- (hpaddr
->hpdc
& 0xffff))
csn
= ((hpaddr
->hpla
& 0xffff)>>6) - sn
+ 1;
hpaddr
->hpcs1
= SEARCH
|GO
;
hptab
.b_actl
->b_forw
= dp
;
register struct buf
*bp
, *dp
;
register struct device
*hpaddr
;
int dn
, sn
, tn
, cn
, nspc
, ns
;
if ((dp
= hptab
.b_actf
) == NULL
)
if ((bp
= dp
->b_actf
) == NULL
) {
hptab
.b_actf
= dp
->b_forw
;
unit
= minor(bp
->b_dev
) & 077;
cn
= rm_sizes
[unit
&07].cyloff
;
cn
= rm5_sizes
[unit
&07].cyloff
;
cn
= hp_sizes
[unit
&07].cyloff
;
hpaddr
= mbadev(HPMBA
, dn
);
if ((hpaddr
->hpds
& (DPR
|MOL
)) != (DPR
|MOL
)) {
dp
->b_actf
= bp
->av_forw
;
if(hptab
.b_errcnt
>= 16 && (bp
->b_flags
&B_READ
) != 0) {
hpaddr
->hpof
= hp_offset
[hptab
.b_errcnt
& 017] | FMT22
;
hpaddr
->hpcs1
= OFFSET
|GO
;
while(hpaddr
->hpds
& PIP
)
hpaddr
->hpda
= (tn
<< 8) + sn
;
mbastart(bp
, (int *)hpaddr
);
dk_wds
[unit
] += bp
->b_bcount
>>6;
register struct buf
*bp
, *dp
;
register struct device
*hpaddr
;
if (HPDK_N
+unit
<= HPDK_NMAX
)
dk_busy
&= ~(1<<(HPDK_N
+unit
));
hpaddr
= mbadev(HPMBA
, unit
);
if (hpaddr
->hpds
& ERR
|| mbastat
& MBAEBITS
) {
while((hpaddr
->hpds
& DRY
) == 0)
if(++hptab
.b_errcnt
> 28 || hpaddr
->hper1
&WLE
)
deverror(bp
, mbastat
, hpaddr
->hper1
);
if ((hpaddr
->hper1
&0xffff) == DCK
) {
if((hptab
.b_errcnt
&07) == 4) {
hpaddr
->hpcs1
= RECAL
|GO
;
while(hpaddr
->hpds
& PIP
)
while(hpaddr
->hpds
& PIP
)
hptab
.b_actf
= dp
->b_forw
;
dp
->b_actf
= bp
->av_forw
;
bp
->b_resid
= -HPMBA
->mba_bcr
& 0xffff;
for(unit
=0; unit
<NHP
; unit
++)
physio(hpstrategy
, &rhpbuf
, dev
, B_READ
, minphys
);
physio(hpstrategy
, &rhpbuf
, dev
, B_WRITE
, minphys
);
register struct device
*rp
;
struct mba_regs
*mbp
= HPMBA
;
int reg
, bit
, byte
, npf
, mask
, o
;
int dn
, bn
, cn
, tn
, sn
, ns
, nt
;
extern char buffers
[NBUF
][BSIZE
];
* Npf is the number of sectors transferred before the sector
* containing the ECC error, and reg is the MBA register
* mapping (the first part of)the transfer.
* O is offset within a memory page of the first byte transferred.
bcr
= mbp
->mba_bcr
& 0xffff;
bcr
|= 0xffff0000; /* sxt */
npf
= btop(bcr
+ bp
->b_bcount
) - 1;
o
= (int)bp
->b_un
.b_addr
& PGOFSET
;
printf("%D ", bp
->b_blkno
+ npf
);
* Compute the byte and bit position of the error.
* The variable i is the byte offset in the transfer,
* the variable byte is the offset from a page boundary
i
= (rp
->hpec1
&0xffff) - 1; /* -1 makes 0 origin */
* Correct while possible bits remain of mask. Since mask
* contains 11 bits, we continue while the bit offset is > -11.
* Also watch out for end of this block and the end of the whole
while (i
< 512 && (int)ptob(npf
)+i
< bp
->b_bcount
&& bit
> -11) {
mpte
= mbp
->mba_map
[reg
+btop(byte
)];
addr
= ptob(mpte
.pg_pfnum
) + (byte
& PGOFSET
);
putmemc(addr
, getmemc(addr
)^(mask
<<bit
));
hptab
.b_active
++; /* Either complete or continuing */
* Have to continue the transfer... clear the drive,
* and compute the position where the transfer is to continue.
* We have completed npf+1 sectores of the transfer already;
* restart at offset o of next sector (i.e. in MBA register reg+1).
ns
= NRMSECT
; nt
= NRMTRAC
; break;
ns
= NRMSECT
; nt
= NTRAC
; break;
ns
= NSECT
; nt
= NTRAC
; break;
sn
= bn
%(ns
*nt
) + npf
+ 1;
mbp
->mba_var
= (int)ptob(reg
+1) + o
;
int num
, blk
, unit
, nsect
, ntrak
, nspc
;
HPPHYSMBA
->mba_cr
= MBAINIT
;
hpaddr
= mbadev(HPPHYSMBA
, unit
);
hp_type
[unit
] = hpaddr
->hpdt
;
if((hpaddr
->hpds
& VV
) == 0) {
hpaddr
->hpcs1
= PRESET
|GO
;
nsect
= NRMSECT
; ntrak
= NTRAC
; sizes
= rm5_sizes
; break;
nsect
= NRMSECT
; ntrak
= NRMTRAC
; sizes
= rm_sizes
; break;
nsect
= NSECT
; ntrak
= NTRAC
; sizes
= hp_sizes
; break;
printf("hp unknown type %x\n", hp_type
[unit
]);
if (dumplo
< 0 || dumplo
+ num
>= sizes
[minor(dev
)&07].nblocks
) {
printf("dumplo+num, sizes %d %d\n", dumplo
+num
, sizes
[minor(dev
)&07].nblocks
);
register struct pte
*hpte
= HPPHYSMBA
->mba_map
;
blk
= num
> DBSIZE
? DBSIZE
: num
;
bn
= dumplo
+ btop(start
);
cn
= bn
/nspc
+ sizes
[minor(dev
)&07].cyloff
;
hpaddr
->hpda
= (tn
<< 8) + sn
;
for (i
= 0; i
< blk
; i
++)
*(int *)hpte
++ = (btop(start
)+i
) | PG_V
;
((struct mba_regs
*)HPPHYSMBA
)->mba_sr
= -1;
((struct mba_regs
*)HPPHYSMBA
)->mba_bcr
= -(blk
*NBPG
);
((struct mba_regs
*)HPPHYSMBA
)->mba_var
= 0;
hpaddr
->hpcs1
= WCOM
| GO
;
while ((hpaddr
->hpds
& DRY
) == 0)
printf("hp dump dsk err: (%d,%d,%d) ds=%X er=%X\n",
cn
, tn
, sn
, hpaddr
->hpds
, hpaddr
->hper1
);