int rknosval
; /* DEBUG */
* RK611/RK0[67] disk driver
* This driver mimics up.c; see it for an explanation of common code.
* Learn why we lose an interrupt sometime when spinning drives down
#include "../machine/pte.h"
#include "../vaxuba/ubareg.h"
#include "../vaxuba/ubavar.h"
#include "../vaxuba/rkreg.h"
/* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
15884, 0, /* A=cyl 0 thru 240 */
10032, 241, /* B=cyl 241 thru 392 */
53790, 0, /* C=cyl 0 thru 814 */
27786, 393, /* G=cyl 393 thru 813 */
15884, 0, /* A=cyl 0 thru 240 */
11154, 241, /* B=cyl 241 thru 409 */
27126, 0, /* C=cyl 0 thru 410 */
/* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
short rktypes
[] = { RK_CDT
, 0 };
int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr();
struct uba_ctlr
*rkminfo
[NHK
];
struct uba_device
*rkdinfo
[NRK
];
struct uba_device
*rkip
[NHK
][4];
u_short rkstd
[] = { 0777440, 0 };
struct uba_driver hkdriver
=
{ rkprobe
, rkslave
, rkattach
, rkdgo
, rkstd
, "rk", rkdinfo
, "hk", rkminfo
, 1 };
NRKSECT
, NRKTRK
, NRKSECT
*NRKTRK
, NRK7CYL
, rk7_sizes
,
NRKSECT
, NRKTRK
, NRKSECT
*NRKTRK
, NRK6CYL
, rk6_sizes
,
{ RKAS_P400
,RKAS_M400
,RKAS_P400
,RKAS_M400
,RKAS_P800
,RKAS_M800
,RKAS_P800
,
RKAS_M800
,RKAS_P1200
,RKAS_M1200
,RKAS_P1200
,RKAS_M1200
,0,0,0,0
br
= 0; cvec
= br
; br
= cvec
;
((struct rkdevice
*)reg
)->rkcs1
= RK_CDT
|RK_IE
|RK_CRDY
;
((struct rkdevice
*)reg
)->rkcs1
= RK_CDT
;
return (sizeof (struct rkdevice
));
register struct rkdevice
*rkaddr
= (struct rkdevice
*)reg
;
rkaddr
->rkcs2
= ui
->ui_slave
;
rkaddr
->rkcs1
= RK_CDT
|RK_DCLR
|RK_GO
;
if (rkaddr
->rkcs2
&RKCS2_NED
|| (rkaddr
->rkds
&RKDS_SVAL
) == 0) {
if (rkaddr
->rkcs1
&RK_CERR
&& rkaddr
->rker
&RKER_DTYE
) {
register struct uba_device
*ui
;
timeout(rkwatch
, (caddr_t
)0, hz
);
dk_mspw
[ui
->ui_dk
] = 1.0 / (60 * NRKSECT
* 256);
rkip
[ui
->ui_ctlr
][ui
->ui_slave
] = ui
;
rk_softc
[ui
->ui_ctlr
].sc_ndrive
++;
register int unit
= minor(dev
) >> 3;
register struct uba_device
*ui
;
if (unit
>= NRK
|| (ui
= rkdinfo
[unit
]) == 0 || ui
->ui_alive
== 0)
register struct uba_device
*ui
;
register struct rkst
*st
;
int xunit
= minor(bp
->b_dev
) & 07;
sz
= (bp
->b_bcount
+511) >> 9;
if (ui
== 0 || ui
->ui_alive
== 0)
(bn
= dkblock(bp
))+sz
> st
->sizes
[xunit
].nblocks
)
bp
->b_cylin
= bn
/st
->nspc
+ st
->sizes
[xunit
].cyloff
;
dp
= &rkutab
[ui
->ui_unit
];
if (bp
->b_actf
&& bp
->b_active
== 0)
(void) rkstart(ui
->ui_mi
);
register struct uba_device
*ui
;
register struct buf
*bp
, *dp
;
register struct uba_ctlr
*um
;
register struct rkdevice
*rkaddr
;
dk_busy
&= ~(1<<ui
->ui_dk
);
dp
= &rkutab
[ui
->ui_unit
];
rkaddr
= (struct rkdevice
*)um
->um_addr
;
if (um
->um_tab
.b_active
) {
rk_softc
[um
->um_ctlr
].sc_softas
|= 1<<ui
->ui_slave
;
if ((bp
= dp
->b_actf
) == NULL
)
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_CERR
;
rkaddr
->rkcs2
= ui
->ui_slave
;
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_DCLR
|RK_GO
;
if ((rkaddr
->rkds
& RKDS_VV
) == 0 || ui
->ui_flags
== 0) {
/* SHOULD WARN SYSTEM THAT THIS HAPPENED */
struct rkst
*st
= &rkst
[ui
->ui_type
];
struct buf
*bbp
= &brkbuf
[ui
->ui_unit
];
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_PACK
|RK_GO
;
bbp
->b_flags
= B_READ
|B_BUSY
;
bbp
->b_un
.b_addr
= (caddr_t
)&rkbad
[ui
->ui_unit
];
bbp
->b_blkno
= st
->ncyl
*st
->nspc
- st
->nsect
;
bbp
->b_cylin
= st
->ncyl
- 1;
if ((rkaddr
->rkds
& RKDS_DREADY
) != RKDS_DREADY
)
if (rk_softc
[um
->um_ctlr
].sc_ndrive
== 1)
if (bp
->b_cylin
== rkcyl
[ui
->ui_unit
])
rkaddr
->rkcyl
= bp
->b_cylin
;
rkcyl
[ui
->ui_unit
] = bp
->b_cylin
;
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_IE
|RK_SEEK
|RK_GO
;
if (um
->um_tab
.b_actf
== NULL
)
um
->um_tab
.b_actl
->b_forw
= dp
;
register struct uba_ctlr
*um
;
register struct buf
*bp
, *dp
;
register struct uba_device
*ui
;
register struct rkdevice
*rkaddr
;
if ((dp
= um
->um_tab
.b_actf
) == NULL
)
if ((bp
= dp
->b_actf
) == NULL
) {
um
->um_tab
.b_actf
= dp
->b_forw
;
ui
= rkdinfo
[dkunit(bp
)];
rkaddr
= (struct rkdevice
*)ui
->ui_addr
;
rkaddr
->rkcs2
= ui
->ui_slave
;
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_DCLR
|RK_GO
;
if ((rkaddr
->rkds
&RKDS_SVAL
) == 0) {
if (rkaddr
->rkds
&RKDS_PIP
) {
if ((rkaddr
->rkds
&RKDS_DREADY
) != RKDS_DREADY
) {
printf("rk%d: not ready", dkunit(bp
));
if ((rkaddr
->rkds
&RKDS_DREADY
) != RKDS_DREADY
) {
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_DCLR
|RK_GO
;
dp
->b_actf
= bp
->av_forw
;
printf(" (came back!)\n");
rkaddr
->rkcyl
= bp
->b_cylin
;
rkcyl
[ui
->ui_unit
] = bp
->b_cylin
;
rkaddr
->rkda
= (tn
<< 8) + sn
;
rkaddr
->rkwc
= -bp
->b_bcount
/ sizeof (short);
if (bp
->b_flags
& B_READ
)
cmd
= rktypes
[ui
->ui_type
]|RK_IE
|RK_READ
|RK_GO
;
cmd
= rktypes
[ui
->ui_type
]|RK_IE
|RK_WRITE
|RK_GO
;
register struct uba_ctlr
*um
;
register struct rkdevice
*rkaddr
= (struct rkdevice
*)um
->um_addr
;
um
->um_tab
.b_active
= 2; /* should now be 2 */
rkaddr
->rkba
= um
->um_ubinfo
;
rkaddr
->rkcs1
= um
->um_cmd
|((um
->um_ubinfo
>>8)&0x300);
register struct uba_ctlr
*um
= rkminfo
[rk11
];
register struct uba_device
*ui
;
register struct rkdevice
*rkaddr
= (struct rkdevice
*)um
->um_addr
;
register struct buf
*bp
, *dp
;
struct rk_softc
*sc
= &rk_softc
[um
->um_ctlr
];
int as
= (rkaddr
->rkatt
>> 8) | sc
->sc_softas
;
if (um
->um_tab
.b_active
== 2 || sc
->sc_recal
) {
ui
= rkdinfo
[dkunit(bp
)];
dk_busy
&= ~(1 << ui
->ui_dk
);
if (rkaddr
->rkcs1
& RK_CERR
) {
u_short ds
= rkaddr
->rkds
;
u_short cs2
= rkaddr
->rkcs2
;
u_short er
= rkaddr
->rker
;
printf("cs2=%b ds=%b er=%b\n",
RKDS_BITS
, er
, RKER_BITS
);
printf("rk%d: write locked\n", dkunit(bp
));
} else if (++um
->um_tab
.b_errcnt
> 28 ||
ds
&RKDS_HARD
|| er
&RKER_HARD
|| cs2
&RKCS2_HARD
) {
printf("cs2=%b ds=%b er=%b\n",
RKDS_BITS
, er
, RKER_BITS
);
} else if (er
& RKER_BSE
) {
if ((er
& (RKER_DCK
|RKER_ECH
)) == RKER_DCK
) {
rkaddr
->rkcs2
= RKCS2_SCLR
;
if (ds
&RKDS_DROT
|| er
&(RKER_OPI
|RKER_SKI
|RKER_UNS
) ||
(um
->um_tab
.b_errcnt
&07) == 4)
rkaddr
->rkcs2
= ui
->ui_slave
;
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_DCLR
|RK_GO
;
if (recal
&& um
->um_tab
.b_active
== 0) {
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_IE
|RK_RECAL
|RK_GO
;
rkaddr
->rkcyl
= bp
->b_cylin
;
rkcyl
[ui
->ui_unit
] = bp
->b_cylin
;
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_IE
|RK_SEEK
|RK_GO
;
if (um
->um_tab
.b_errcnt
< 16 ||
(bp
->b_flags
&B_READ
) == 0)
rkaddr
->rkatt
= rk_offset
[um
->um_tab
.b_errcnt
& 017];
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_IE
|RK_OFFSET
|RK_GO
;
if (um
->um_tab
.b_active
) {
um
->um_tab
.b_actf
= dp
->b_forw
;
dp
->b_actf
= bp
->av_forw
;
bp
->b_resid
= -rkaddr
->rkwc
* sizeof(short);
as
&= ~(1<<ui
->ui_slave
);
for (unit
= 0; as
; as
>>= 1, unit
++)
rkustart(rkip
[rk11
][unit
]);
rkaddr
->rkcs1
= RK_DCLR
|RK_GO
;
if (um
->um_tab
.b_actf
&& um
->um_tab
.b_active
== 0)
if (((rkaddr
->rkcs1
) & RK_IE
) == 0)
register struct rkdevice
*addr
;
while ((addr
->rkcs1
& RK_CRDY
) == 0)
register int unit
= minor(dev
) >> 3;
return (physio(rkstrategy
, &rrkbuf
[unit
], dev
, B_READ
, minphys
, uio
));
register int unit
= minor(dev
) >> 3;
return (physio(rkstrategy
, &rrkbuf
[unit
], dev
, B_WRITE
, minphys
, uio
));
register struct uba_device
*ui
;
register struct rkdevice
*rk
= (struct rkdevice
*)ui
->ui_addr
;
register struct buf
*bp
= rkutab
[ui
->ui_unit
].b_actf
;
register struct uba_ctlr
*um
= ui
->ui_mi
;
register struct rkst
*st
;
struct uba_regs
*ubp
= ui
->ui_hd
->uh_uba
;
int reg
, npf
, o
, cmd
, ubaddr
;
npf
= btop((rk
->rkwc
* sizeof(short)) + bp
->b_bcount
);
reg
= btop(um
->um_ubinfo
&0x3ffff) + npf
;
o
= (int)bp
->b_un
.b_addr
& PGOFSET
;
printf("rk%d%c: soft ecc sn%d\n", dkunit(bp
),
'a'+(minor(bp
->b_dev
)&07), bp
->b_blkno
+ npf
);
i
= rk
->rkec1
- 1; /* -1 makes 0 origin */
while (i
< 512 && (int)ptob(npf
)+i
< bp
->b_bcount
&& bit
> -11) {
addr
= ptob(ubp
->uba_map
[reg
+btop(byte
)].pg_pfnum
)+
putmemc(addr
, getmemc(addr
)^(mask
<<bit
));
printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn
, cn
, tn
, sn
);
if ((bn
= isbad(&rkbad
[ui
->ui_unit
], cn
, tn
, sn
)) < 0)
bn
= st
->ncyl
*st
->nspc
- st
->nsect
- 1 - bn
;
printf("revector to cn %d tn %d sn %d\n", cn
, tn
, sn
);
rk
->rkwc
= -(512 / sizeof (short));
printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn
,cn
,tn
,sn
);
rk
->rkwc
= -((bp
->b_bcount
- (int)ptob(npf
)) / sizeof (short));
rk
->rkcs2
= ui
->ui_slave
;
rk
->rkcs1
= rktypes
[ui
->ui_type
]|RK_DCLR
|RK_GO
;
rk
->rkda
= (tn
<< 8) | sn
;
ubaddr
= (int)ptob(reg
) + o
;
cmd
= (bp
->b_flags
&B_READ
? RK_READ
: RK_WRITE
)|RK_IE
|RK_GO
;
cmd
|= (ubaddr
>> 8) & 0x300;
cmd
|= rktypes
[ui
->ui_type
];
um
->um_tab
.b_active
= 2; /* continuing */
um
->um_tab
.b_errcnt
= 0; /* error has been corrected */
register struct uba_ctlr
*um
;
register struct uba_device
*ui
;
for (rk11
= 0; rk11
< NHK
; rk11
++) {
if ((um
= rkminfo
[rk11
]) == 0 || um
->um_ubanum
!= uban
||
um
->um_tab
.b_actf
= um
->um_tab
.b_actl
= 0;
rk_softc
[um
->um_ctlr
].sc_recal
= 0;
rk_softc
[um
->um_ctlr
].sc_wticks
= 0;
printf("<%d>", (um
->um_ubinfo
>>28)&0xf);
for (unit
= 0; unit
< NRK
; unit
++) {
if ((ui
= rkdinfo
[unit
]) == 0)
if (ui
->ui_alive
== 0 || ui
->ui_mi
!= um
)
rkutab
[unit
].b_active
= 0;
register struct uba_ctlr
*um
;
register struct rk_softc
*sc
;
timeout(rkwatch
, (caddr_t
)0, hz
);
for (rk11
= 0; rk11
< NHK
; rk11
++) {
if (um
== 0 || um
->um_alive
== 0)
if (um
->um_tab
.b_active
== 0) {
for (unit
= 0; unit
< NRK
; unit
++)
if (rkutab
[unit
].b_active
&&
rkdinfo
[unit
]->ui_mi
== um
)
if (sc
->sc_wticks
>= 20) {
printf("hk%d: lost interrupt\n", rk11
);
register struct uba_regs
*uba
;
register struct uba_device
*ui
;
#define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
ui
= phys(struct uba_device
*, rkdinfo
[unit
]);
uba
= phys(struct uba_hd
*, ui
->ui_hd
)->uh_physuba
;
rkaddr
= (struct rkdevice
*)ui
->ui_physaddr
;
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_DCLR
|RK_GO
;
if ((rkaddr
->rkds
& RKDS_VV
) == 0) {
rkaddr
->rkcs1
= rktypes
[ui
->ui_type
]|RK_IE
|RK_PACK
|RK_GO
;
sizes
= phys(struct size
*, st
->sizes
);
if (dumplo
< 0 || dumplo
+ num
>= sizes
[minor(dev
)&07].nblocks
)
blk
= num
> DBSIZE
? DBSIZE
: num
;
for (i
= 0; i
< blk
; i
++)
*(int *)io
++ = (btop(start
)+i
) | (1<<21) | UBAMR_MRV
;
bn
= dumplo
+ btop(start
);
cn
= bn
/st
->nspc
+ sizes
[minor(dev
)&07].cyloff
;
rp
= (short *) &rkaddr
->rkda
;
*--rp
= -blk
*NBPG
/ sizeof (short);
*--rp
= rktypes
[ui
->ui_type
]|RK_GO
|RK_WRITE
;
if (rkaddr
->rkcs1
& RK_CERR
)
int unit
= minor(dev
) >> 3;
if (unit
>= NRK
|| (ui
= rkdinfo
[unit
]) == 0 || ui
->ui_alive
== 0)
return (st
->sizes
[minor(dev
) & 07].nblocks
);