* cleanup messages on errors
* see how many rewind interrups we get if we kick when not at BOT
* fixup rle error on block tape code
{ MBDT_TM03
, MBDT_TE16
, MBDT_TU45
, MBDT_TU77
, 0 };
struct mba_device
*htinfo
[NHT
];
int htattach(), htslave(), htustart(), htndtint(), htdtint();
struct mba_driver htdriver
=
{ htattach
, htslave
, htustart
, 0, htdtint
, htndtint
,
httypes
, "ht", "tu", htinfo
};
#define MASKREG(r) ((r) & 0xffff)
/* bits in minor device */
#define TUUNIT(dev) (minor(dev)&03)
#define HTUNIT(dev) (tutoht[TUUNIT(dev)])
#define INF (daddr_t)1000000L /* a block number that wont exist */
struct mba_device
*sc_mi
;
#define H_WRITTEN 1 /* last operation was a write */
#define H_ERASED 2 /* last write retry was an erase gap */
#define H_REWIND 4 /* last unit start was a rewind */
char hter_bits
[] = HTER_BITS
;
char htds_bits
[] = HTDS_BITS
;
register struct tu_softc
*sc
= &tu_softc
[ms
->ms_unit
];
register struct htdevice
*htaddr
= (struct htdevice
*)mi
->mi_drv
;
htaddr
->httc
= ms
->ms_slave
;
if (htaddr
->htdt
& HTDT_SPR
) {
sc
->sc_slave
= ms
->ms_slave
;
tutoht
[ms
->ms_unit
] = mi
->mi_unit
;
register struct mba_device
*mi
;
register struct tu_softc
*sc
;
if (tuunit
>= NTU
|| (sc
= &tu_softc
[tuunit
])->sc_openf
||
(mi
= htinfo
[HTUNIT(dev
)]) == 0 || mi
->mi_alive
== 0) {
((minor(dev
)&H_1600BPI
)?HTTC_1600BPI
:HTTC_800BPI
)|
htcommand(dev
, HT_SENSE
, 1);
if ((sc
->sc_dsreg
& HTDS_MOL
) == 0) {
uprintf("tu%d: not online\n", tuunit
);
if ((flag
&FWRITE
) && (sc
->sc_dsreg
&HTDS_WRL
)) {
uprintf("tu%d: no write ring\n", tuunit
);
if ((sc
->sc_dsreg
& HTDS_BOT
) == 0 && (flag
&FWRITE
) &&
uprintf("tu%d: can't change density in mid-tape\n", tuunit
);
sc
->sc_blkno
= (daddr_t
)0;
register struct tu_softc
*sc
= &tu_softc
[TUUNIT(dev
)];
if (flag
== FWRITE
|| ((flag
&FWRITE
) && (sc
->sc_flags
&H_WRITTEN
))) {
htcommand(dev
, HT_WEOF
, 1);
htcommand(dev
, HT_WEOF
, 1);
htcommand(dev
, HT_SREV
, 1);
if ((minor(dev
)&H_NOREWIND
) == 0)
htcommand(dev
, HT_REW
, 0);
htcommand(dev
, com
, count
)
bp
= &chtbuf
[HTUNIT(dev
)];
while (bp
->b_flags
&B_BUSY
) {
if(bp
->b_repcnt
== 0 && (bp
->b_flags
&B_DONE
))
sleep((caddr_t
)bp
, PRIBIO
);
bp
->b_flags
= B_BUSY
|B_READ
;
if (bp
->b_flags
&B_WANTED
)
register struct mba_device
*mi
= htinfo
[HTUNIT(bp
->b_dev
)];
dp
->b_actl
->av_forw
= bp
;
register struct mba_device
*mi
;
register struct htdevice
*htaddr
=
(struct htdevice
*)mi
->mi_drv
;
register struct buf
*bp
= mi
->mi_tab
.b_actf
;
register struct tu_softc
*sc
= &tu_softc
[TUUNIT(bp
->b_dev
)];
htaddr
->httc
= sc
->sc_dens
;
if (bp
== &chtbuf
[HTUNIT(bp
->b_dev
)] && bp
->b_command
== HT_SENSE
) {
htaddr
->htcs1
= HT_SENSE
|HT_GO
;
sc
->sc_dsreg
= htaddr
->htds
;
sc
->sc_erreg
= htaddr
->hter
;
sc
->sc_resid
= htaddr
->htfc
;
sc
->sc_flags
&= ~(H_WRITTEN
|H_REWIND
);
if ((htaddr
->htdt
& HTDT_SPR
) == 0 || (htaddr
->htds
& HTDS_MOL
) == 0)
if (bp
!= &chtbuf
[HTUNIT(bp
->b_dev
)]) {
if (dbtofsb(bp
->b_blkno
) > sc
->sc_nxrec
) {
if (dbtofsb(bp
->b_blkno
) == sc
->sc_nxrec
&&
bp
->b_resid
= bp
->b_bcount
;
if ((bp
->b_flags
&B_READ
)==0)
sc
->sc_nxrec
= dbtofsb(bp
->b_blkno
) + 1;
if (bp
->b_command
== HT_SENSE
)
if (bp
->b_command
== HT_REW
)
sc
->sc_flags
|= H_REWIND
;
htaddr
->htfc
= -bp
->b_bcount
;
htaddr
->htcs1
= bp
->b_command
|HT_GO
;
if ((blkno
= sc
->sc_blkno
) == dbtofsb(bp
->b_blkno
)) {
htaddr
->htfc
= -bp
->b_bcount
;
if ((bp
->b_flags
&B_READ
) == 0) {
if (mi
->mi_tab
.b_errcnt
) {
if ((sc
->sc_flags
& H_ERASED
) == 0) {
sc
->sc_flags
|= H_ERASED
;
htaddr
->htcs1
= HT_ERASE
| HT_GO
;
sc
->sc_flags
&= ~H_ERASED
;
if (htaddr
->htds
& HTDS_EOT
) {
bp
->b_resid
= bp
->b_bcount
;
if (blkno
< dbtofsb(bp
->b_blkno
)) {
htaddr
->htfc
= blkno
- dbtofsb(bp
->b_blkno
);
htaddr
->htcs1
= HT_SFORW
|HT_GO
;
htaddr
->htfc
= dbtofsb(bp
->b_blkno
) - blkno
;
htaddr
->htcs1
= HT_SREV
|HT_GO
;
register struct mba_device
*mi
;
register struct htdevice
*htaddr
= (struct htdevice
*)mi
->mi_drv
;
register struct buf
*bp
= mi
->mi_tab
.b_actf
;
register struct tu_softc
*sc
;
sc
= &tu_softc
[TUUNIT(bp
->b_dev
)];
ds
= sc
->sc_dsreg
= MASKREG(htaddr
->htds
);
er
= sc
->sc_erreg
= MASKREG(htaddr
->hter
);
sc
->sc_resid
= MASKREG(htaddr
->htfc
);
if((bp
->b_flags
& B_READ
) == 0)
sc
->sc_flags
|= H_WRITTEN
;
if ((ds
&(HTDS_ERR
|HTDS_MOL
)) != HTDS_MOL
|| mbs
& MBSR_EBITS
) {
htaddr
->htcs1
= HT_DCLR
|HT_GO
;
if (bp
== &rhtbuf
[HTUNIT(bp
->b_dev
)]) {
mbs
&= ~(MBSR_DTABT
|MBSR_MBEXC
);
if (bp
->b_flags
& B_READ
&& ds
& HTDS_PES
)
er
&= ~(HTER_CSITM
|HTER_CORCRC
);
if (er
&HTER_HARD
|| mbs
&MBSR_EBITS
|| (ds
&HTDS_MOL
) == 0 ||
er
&& ++mi
->mi_tab
.b_errcnt
>= 7) {
if ((ds
& HTDS_MOL
) == 0 && sc
->sc_openf
> 0)
if ((er
&HTER_HARD
) == HTER_FCE
&&
(mbs
&MBSR_EBITS
) == (MBSR_DTABT
|MBSR_MBEXC
) &&
printf("tu%d: hard error bn%d mbsr=%b er=%b ds=%b\n",
TUUNIT(bp
->b_dev
), bp
->b_blkno
,
sc
->sc_dsreg
, htds_bits
);
if (bp
->b_flags
& B_READ
)
if (ds
&HTDS_TM
) { /* must be a read, right? */
bp
->b_resid
= bp
->b_bcount
;
sc
->sc_nxrec
= dbtofsb(bp
->b_blkno
);
} else if(bp
->b_bcount
> MASKREG(htaddr
->htfc
))
bp
->b_resid
= bp
->b_bcount
- MASKREG(htaddr
->htfc
);
register struct mba_device
*mi
;
register struct htdevice
*htaddr
= (struct htdevice
*)mi
->mi_drv
;
register struct buf
*bp
= mi
->mi_tab
.b_actf
;
register struct tu_softc
*sc
;
ds
= MASKREG(htaddr
->htds
);
er
= MASKREG(htaddr
->hter
);
fc
= MASKREG(htaddr
->htfc
);
htaddr
->htcs1
= HT_DCLR
|HT_GO
;
sc
= &tu_softc
[TUUNIT(bp
->b_dev
)];
if (bp
== &chtbuf
[HTUNIT(bp
->b_dev
)]) {
/* offline is on purpose; don't do anything special */
/* if backspace file hit bot, its not an error */
if (er
== (HTER_NEF
|HTER_FCE
) && ds
&HTDS_BOT
&&
if ((ds
& (HTDS_ERR
|HTDS_MOL
)) != HTDS_MOL
) {
if ((ds
& HTDS_MOL
) == 0 && sc
->sc_openf
> 0)
printf("tu%d: hard error bn%d er=%b ds=%b\n",
TUUNIT(bp
->b_dev
), bp
->b_blkno
,
sc
->sc_erreg
, hter_bits
, sc
->sc_dsreg
, htds_bits
);
if (bp
== &chtbuf
[HTUNIT(bp
->b_dev
)]) {
if (sc
->sc_flags
& H_REWIND
)
return (ds
& HTDS_BOT
? MBN_DONE
: MBN_RETRY
);
bp
->b_resid
= -sc
->sc_resid
;
if (sc
->sc_blkno
> dbtofsb(bp
->b_blkno
)) {
sc
->sc_nxrec
= dbtofsb(bp
->b_blkno
) - fc
;
sc
->sc_blkno
= sc
->sc_nxrec
;
sc
->sc_blkno
= dbtofsb(bp
->b_blkno
) + fc
;
sc
->sc_nxrec
= sc
->sc_blkno
- 1;
sc
->sc_blkno
= dbtofsb(bp
->b_blkno
);
physio(htstrategy
, &rhtbuf
[HTUNIT(dev
)], dev
, B_READ
, minphys
);
physio(htstrategy
, &rhtbuf
[HTUNIT(dev
)], dev
, B_WRITE
, minphys
);
register struct tu_softc
*sc
;
register struct mba_device
*mi
;
if (htunit
>= NHT
|| (mi
= htinfo
[htunit
]) == 0 || mi
->mi_alive
== 0) {
sc
= &tu_softc
[TUUNIT(dev
)];
sc
->sc_blkno
= dbtofsb(a
);
sc
->sc_nxrec
= dbtofsb(a
)+1;
htioctl(dev
, cmd
, addr
, flag
)
register struct tu_softc
*sc
= &tu_softc
[TUUNIT(dev
)];
register struct buf
*bp
= &chtbuf
[HTUNIT(dev
)];
/* we depend of the values and order of the MT codes here */
{HT_WEOF
,HT_SFORW
,HT_SREV
,HT_SFORW
,HT_SREV
,HT_REW
,HT_REWOFFL
,HT_SENSE
};
case MTIOCTOP
: /* tape operation */
if (copyin((caddr_t
)addr
, (caddr_t
)&mtop
, sizeof(mtop
))) {
callcount
= mtop
.mt_count
;
callcount
= mtop
.mt_count
;
if (callcount
<= 0 || fcount
<= 0) {
while (--callcount
>= 0) {
htcommand(dev
, htops
[mtop
.mt_op
], fcount
);
if ((mtop
.mt_op
== MTFSR
|| mtop
.mt_op
== MTBSR
) &&
if ((bp
->b_flags
&B_ERROR
) || sc
->sc_dsreg
&HTDS_BOT
)
mtget
.mt_dsreg
= sc
->sc_dsreg
;
mtget
.mt_erreg
= sc
->sc_erreg
;
mtget
.mt_resid
= sc
->sc_resid
;
if (copyout((caddr_t
)&mtget
, addr
, sizeof(mtget
)))
register struct mba_device
*mi
;
register struct mba_regs
*mp
;
register struct htdevice
*htaddr
;
#define phys(a,b) ((b)((int)(a)&0x7fffffff))
mi
= phys(htinfo
[0], struct mba_device
*);
mp
= phys(mi
->mi_hd
, struct mba_hd
*)->mh_physmba
;
htaddr
= (struct htdevice
*)&mp
->mba_drv
[mi
->mi_drive
];
htaddr
->httc
= HTTC_PDP11
|HTTC_1600BPI
;
htaddr
->htcs1
= HT_DCLR
|HT_GO
;
blk
= num
> DBSIZE
? DBSIZE
: num
;
htdwrite(start
, blk
, htaddr
, mp
);
if (htaddr
->htds
&HTDS_ERR
)
htaddr
->htcs1
= HT_REW
|HT_GO
;
htdwrite(dbuf
, num
, htaddr
, mp
)
register struct htdevice
*htaddr
;
for (i
= 0; i
< num
; i
++)
*(int *)io
++ = dbuf
++ | PG_V
;
htaddr
->htfc
= -(num
*NBPG
);
mp
->mba_bcr
= -(num
*NBPG
);
htaddr
->htcs1
= HT_WCOM
|HT_GO
;
while ((s
& HTDS_DRY
) == 0);
htaddr
->htcs1
= HT_WEOF
|HT_GO
;