e73dd759bfcce7280275704e5e742a19ad0dd5b6
* Behavior in complex error situations is uncertain...
* add odd byte count kludge from VMS driver
struct mba_device
*mtinfo
[NMT
];
int mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint();
struct mba_driver mtdriver
=
{ mtattach
, mtslave
, mtustart
, mtstart
, mtdtint
, mtndtint
,
mttypes
, "mt", "mu", mtinfo
};
#define MASKREG(r) ((r) & 0xffff)
/* bits in minor device */
#define MUUNIT(dev) (minor(dev)&03)
#define MTUNIT(dev) (mutomt[MUUNIT(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 */
char mtds_bits
[] = MTDS_BITS
;
mtread(0, 0); mtwrite(0); mtioctl(0, 0, 0, 0);
register struct mu_softc
*sc
= &mu_softc
[ms
->ms_unit
];
register struct mtdevice
*mtaddr
= (struct mtdevice
*)mi
->mi_drv
;
mtaddr
->mtncs
[sn
] = MT_SENSE
|MT_GO
;
while (mtaddr
->mtas
== 0)
if ((mtaddr
->mtner
& MTER_INTCODE
) == MTER_DONE
&&
(mtaddr
->mtds
& MTDS_PRES
)) {
mutomt
[ms
->ms_unit
] = mi
->mi_unit
;
mtaddr
->mtas
= mtaddr
->mtas
;
register struct mba_device
*mi
;
register struct mu_softc
*sc
;
if (muunit
>= NMU
|| (sc
= &mu_softc
[muunit
])->sc_openf
||
(mi
= mtinfo
[MTUNIT(dev
)]) == 0 || mi
->mi_alive
== 0) {
dens
= sc
->sc_dens
= (minor(dev
)&H_6250BPI
) ? MT_GCR
: 0;
mtcommand(dev
, MT_SENSE
, 1);
if ((sc
->sc_dsreg
& MTDS_ONL
) == 0) {
uprintf("mu%d: not online\n", muunit
);
if ((flag
&FWRITE
) && (sc
->sc_dsreg
&MTDS_FPT
)) {
uprintf("mu%d: no write ring\n", muunit
);
if ((sc
->sc_dsreg
& MTDS_BOT
) == 0 && (flag
&FWRITE
) &&
uprintf("mu%d: can't change density in mid-tape\n", muunit
);
sc
->sc_blkno
= (daddr_t
)0;
register struct mu_softc
*sc
= &mu_softc
[MUUNIT(dev
)];
if (flag
== FWRITE
|| ((flag
&FWRITE
) && (sc
->sc_flags
&H_WRITTEN
)))
mtcommand(dev
, MT_CLS
|sc
->sc_dens
, 1);
if ((minor(dev
)&H_NOREWIND
) == 0)
mtcommand(dev
, MT_REW
, 0);
mtcommand(dev
, com
, count
)
bp
= &cmtbuf
[MTUNIT(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
= mtinfo
[MTUNIT(bp
->b_dev
)];
dp
->b_actl
->av_forw
= bp
;
register struct mba_device
*mi
;
register struct mtdevice
*mtaddr
=
(struct mtdevice
*)mi
->mi_drv
;
register struct buf
*bp
= mi
->mi_tab
.b_actf
;
register struct mu_softc
*sc
= &mu_softc
[MUUNIT(bp
->b_dev
)];
sc
->sc_flags
&= ~H_WRITTEN
;
if (bp
!= &cmtbuf
[MTUNIT(bp
->b_dev
)]) {
if (bdbtofsb(bp
->b_blkno
) > sc
->sc_nxrec
) {
if (bdbtofsb(bp
->b_blkno
) == sc
->sc_nxrec
&&
bp
->b_resid
= bp
->b_bcount
;
if ((bp
->b_flags
&B_READ
)==0)
sc
->sc_nxrec
= bdbtofsb(bp
->b_blkno
) + 1;
mtaddr
->mtncs
[MUUNIT(bp
->b_dev
)] =
(bp
->b_repcnt
<<8)|bp
->b_command
|MT_GO
;
if ((blkno
= sc
->sc_blkno
) == bdbtofsb(bp
->b_blkno
)) {
if (mi
->mi_tab
.b_errcnt
== 2) {
mtaddr
->mtca
= MUUNIT(bp
->b_dev
);
mtaddr
->mtbc
= bp
->b_bcount
;
mtaddr
->mtca
= (1<<2)|MUUNIT(bp
->b_dev
);
if (blkno
< bdbtofsb(bp
->b_blkno
))
mtaddr
->mtncs
[MUUNIT(bp
->b_dev
)] =
(min((unsigned)(bdbtofsb(bp
->b_blkno
) - blkno
), 0377) << 8) |
mtaddr
->mtncs
[MUUNIT(bp
->b_dev
)] =
(min((unsigned)(blkno
- bdbtofsb(bp
->b_blkno
)), 0377) << 8) |
register struct mba_device
*mi
;
register struct buf
*bp
= mi
->mi_tab
.b_actf
;
register struct mu_softc
*sc
= &mu_softc
[MUUNIT(bp
->b_dev
)];
if (bp
->b_flags
& B_READ
)
if (mi
->mi_tab
.b_errcnt
== 2)
return(MT_READREV
|MT_GO
);
return(MT_WRITE
|sc
->sc_dens
|MT_GO
);
register struct mba_device
*mi
;
register struct mtdevice
*mtaddr
= (struct mtdevice
*)mi
->mi_drv
;
register struct buf
*bp
= mi
->mi_tab
.b_actf
;
register struct mu_softc
*sc
;
/* I'M NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
if ((mtaddr
->mtca
&3) != MUUNIT(bp
->b_dev
)) {
printf("mt: wrong unit!\n");
mtaddr
->mtca
= MUUNIT(bp
->b_dev
);
sc
= &mu_softc
[MUUNIT(bp
->b_dev
)];
sc
->sc_erreg
= mtaddr
->mter
;
if((bp
->b_flags
& B_READ
) == 0)
sc
->sc_flags
|= H_WRITTEN
;
switch (sc
->sc_erreg
& MTER_INTCODE
) {
if (mi
->mi_tab
.b_errcnt
!= 2)
printf("mu%d: blank tape\n", MUUNIT(bp
->b_dev
));
bp
->b_resid
= bp
->b_bcount
;
sc
->sc_nxrec
= bdbtofsb(bp
->b_blkno
);
if (bp
!= &rmtbuf
[MTUNIT(bp
->b_dev
)])
if (mi
->mi_tab
.b_errcnt
== 2)
bp
->b_bcount
= bp
->b_resid
; /* restore saved value */
bp
->b_resid
= bp
->b_bcount
- mtaddr
->mtbc
;
mi
->mi_tab
.b_errcnt
= 2; /* indicate "read opposite" */
bp
->b_resid
= bp
->b_bcount
; /* save it */
bp
->b_bcount
= mtaddr
->mtbc
; /* use this instead */
mi
->mi_tab
.b_errcnt
= 1; /* indicate simple retry */
printf("mu%d: offline\n", MUUNIT(bp
->b_dev
));
printf("mu%d: no write ring\n", MUUNIT(bp
->b_dev
));
printf("mu%d: hard error bn%d mbsr=%b er=%x ds=%b\n",
MUUNIT(bp
->b_dev
), bp
->b_blkno
,
mbsr
, mbsr_bits
, sc
->sc_erreg
,
sc
->sc_dsreg
, mtds_bits
);
mtaddr
->mtid
= MTID_CLR
; /* reset the TM78 */
while ((mtaddr
->mtid
& MTID_RDY
) == 0) /* wait for it */
/* CHECK FOR MBA ERROR WHEN NO OTHER ERROR INDICATED? */
register struct mba_device
*mi
;
register struct mtdevice
*mtaddr
= (struct mtdevice
*)mi
->mi_drv
;
register struct buf
*bp
= mi
->mi_tab
.b_actf
;
register struct mu_softc
*sc
;
unit
= (mtaddr
->mtner
>> 8) & 3;
er
= MASKREG(mtaddr
->mtner
);
/* WILL THIS OCCUR IF ANOTHER DRIVE COMES ONLINE? */
if (bp
== 0 || unit
!= MUUNIT(bp
->b_dev
)) { /* consistency check */
if ((er
& MTER_INTCODE
) != MTER_ONLINE
)
printf("mt: unit %d random interrupt\n", unit
);
fc
= (mtaddr
->mtncs
[unit
] >> 8) & 0xff;
switch (er
& MTER_INTCODE
) {
if (bp
== &cmtbuf
[MTUNIT(bp
->b_dev
)]) {
if (bp
->b_command
== MT_SENSE
)
sc
->sc_dsreg
= MASKREG(mtaddr
->mtds
);
/* this is UGLY! (but is it correct?) */
if ((fc
= bdbtofsb(bp
->b_blkno
) - sc
->sc_blkno
) < 0)
sc
->sc_blkno
-= MIN(0377, -fc
);
sc
->sc_blkno
+= MIN(0377, fc
);
return (MBN_SKIP
); /* ignore "rewind started" interrupt */
printf("mu%d: blank tape\n", MUUNIT(bp
->b_dev
));
if (sc
->sc_blkno
> bdbtofsb(bp
->b_blkno
)) {
sc
->sc_nxrec
= bdbtofsb(bp
->b_blkno
) + fc
;
sc
->sc_blkno
= sc
->sc_nxrec
;
sc
->sc_blkno
= bdbtofsb(bp
->b_blkno
) - fc
;
sc
->sc_nxrec
= sc
->sc_blkno
- 1;
printf("mu%d: no write ring\n", MUUNIT(bp
->b_dev
));
printf("mu%d: offline\n", MUUNIT(bp
->b_dev
));
if (bp
== &cmtbuf
[MTUNIT(bp
->b_dev
)])
printf("mu%d: hard error bn%d er=%o ds=%b\n",
MUUNIT(bp
->b_dev
), bp
->b_blkno
,
sc
->sc_erreg
, sc
->sc_dsreg
, mtds_bits
);
mtaddr
->mtid
= MTID_CLR
; /* reset the TM78 */
while ((mtaddr
->mtid
& MTID_RDY
) == 0) /* wait for it */
u
.u_error
= mtphys(dev
, uio
);
physio(mtstrategy
, &rmtbuf
[MTUNIT(dev
)], dev
, B_READ
, minphys
, uio
);
u
.u_error
= mtphys(dev
, uio
);
physio(mtstrategy
, &rmtbuf
[MTUNIT(dev
)], dev
, B_WRITE
, minphys
, uio
);
register struct mu_softc
*sc
;
register struct mba_device
*mi
;
if (mtunit
>= NMT
|| (mi
= mtinfo
[mtunit
]) == 0 || mi
->mi_alive
== 0)
a
= uio
->uio_offset
>> 9;
sc
= &mu_softc
[MUUNIT(dev
)];
sc
->sc_blkno
= bdbtofsb(a
);
sc
->sc_nxrec
= bdbtofsb(a
)+1;
mtioctl(dev
, cmd
, data
, flag
)
register struct mu_softc
*sc
= &mu_softc
[MUUNIT(dev
)];
register struct buf
*bp
= &cmtbuf
[MTUNIT(dev
)];
/* we depend of the values and order of the MT codes here */
{MT_WTM
,MT_SFORWF
,MT_SREVF
,MT_SFORW
,MT_SREV
,MT_REW
,MT_UNLOAD
,MT_SENSE
};
case MTIOCTOP
: /* tape operation */
mtop
= (struct mtop
*)mtop
;
callcount
= mtop
->mt_count
;
callcount
= mtop
->mt_count
;
if (callcount
<= 0 || fcount
<= 0) {
while (--callcount
>= 0) {
if ((mtop
->mt_op
== MTFSR
|| mtop
->mt_op
== MTBSR
) &&
mtget
= (struct mtget
*)data
;
mtget
->mt_erreg
= sc
->sc_erreg
;
mtget
->mt_resid
= sc
->sc_resid
;
mtcommand(dev
, MT_SENSE
, 1); /* update drive status */
mtget
->mt_dsreg
= sc
->sc_dsreg
;
mtget
->mt_type
= MT_ISMT
;
register struct mba_device
*mi
;
register struct mba_regs
*mp
;
register struct mtdevice
*mtaddr
;
#define phys(a,b) ((b)((int)(a)&0x7fffffff))
mi
= phys(mtinfo
[0], struct mba_device
*);
mp
= phys(mi
->mi_hd
, struct mba_hd
*)->mh_physmba
;
blk
= blk
; num
= num
; start
= start
;
mtaddr
= (struct mtdevice
*)&mp
->mba_drv
[mi
->mi_drive
];
mtaddr
->mttc
= MTTC_PDP11
|MTTC_1600BPI
;
mtaddr
->mtcs1
= MT_DCLR
|MT_GO
;
blk
= num
> DBSIZE
? DBSIZE
: num
;
mtdwrite(start
, blk
, mtaddr
, mp
);
if (mtaddr
->mtds
&MTDS_ERR
)
mtaddr
->mtcs1
= MT_REW
|MT_GO
;
mtdwrite(dbuf
, num
, mtaddr
, mp
)
register struct mtdevice
*mtaddr
;
for (i
= 0; i
< num
; i
++)
*(int *)io
++ = dbuf
++ | PG_V
;
mtaddr
->mtfc
= -(num
*NBPG
);
mp
->mba_bcr
= -(num
*NBPG
);
mtaddr
->mtcs1
= MT_WCOM
|MT_GO
;
while ((s
& MTDS_DRY
) == 0);
mtaddr
->mtcs1
= MT_WEOF
|MT_GO
;