#define b_repcnt b_bcount
#define b_command b_resid
/* bits in minor device */
#define INF (daddr_t)1000000L
* Really only handle one tape drive... if you have more than one,
* you can make all these arrays and change the obvious things, but
* it is not clear what happens when some drives are transferring while
* others rewind, so we don't pretend that this driver handles multiple
#define SOFT (CRE|PAE|BGL|RLE|TMBTE|NXM)
#define SSEEK 1 /* seeking */
#define SIO 2 /* doing seq i/o */
#define SCOM 3 /* sending control command */
#define LASTIOW 1 /* last op was a write */
#define WAITREW 2 /* someone is waiting for a rewind */
if (unit
>= NTM
|| t_openf
) {
u
.u_error
= ENXIO
; /* out of range or open */
if ((t_erreg
&SELR
) == 0) {
u
.u_error
= EIO
; /* offline */
tmwaitrws(dev
); /* wait for rewind complete */
tcommand(dev
, NOP
, 1); /* await settle down */
((flag
&(FREAD
|FWRITE
)) == FWRITE
&& (t_erreg
&WRL
))) {
u
.u_error
= EIO
; /* offline or write protect */
if ((TMADDR
->tmer
&RWS
) == 0) {
spl0(); /* rewind complete */
sleep((caddr_t
)&t_flags
, PRIBIO
);
if (flag
== FWRITE
|| ((flag
&FWRITE
) && (t_flags
&LASTIOW
))) {
if ((minor(dev
)&T_NOREWIND
) == 0)
tcommand(dev
, com
, count
)
while (bp
->b_flags
&B_BUSY
) {
sleep((caddr_t
)bp
, PRIBIO
);
bp
->b_flags
= B_BUSY
|B_READ
;
if (bp
->b_flags
&B_WANTED
)
if (dbtofsb(bp
->b_blkno
) > *p
) {
bp
->b_error
= ENXIO
; /* past EOF */
} else if (dbtofsb(bp
->b_blkno
) == *p
&& bp
->b_flags
&B_READ
) {
bp
->b_resid
= bp
->b_bcount
;
} else if ((bp
->b_flags
&B_READ
) == 0)
*p
= dbtofsb(bp
->b_blkno
) + 1; /* write sets EOF */
if (tmtab
.b_actf
== NULL
)
tmtab
.b_actl
->av_forw
= bp
;
if ((bp
= tmtab
.b_actf
) == 0)
if (t_openf
< 0 || (TMADDR
->tmcs
&CUR
) == 0) {
bp
->b_flags
|= B_ERROR
; /* hard error'ed or !SELR */
if ((minor(bp
->b_dev
) & T_1600BPI
) == 0)
if (bp
->b_command
== NOP
)
goto next
; /* just get status */
if (bp
->b_command
== SFORW
|| bp
->b_command
== SREV
)
TMADDR
->tmbc
= bp
->b_repcnt
;
if ((blkno
= t_blkno
) == dbtofsb(bp
->b_blkno
)) {
TMADDR
->tmbc
= -bp
->b_bcount
;
tm_ubinfo
= ubasetup(bp
,1);
if ((bp
->b_flags
&B_READ
) == 0) {
cmd
|= (tm_ubinfo
>> 12) & 0x30;
TMADDR
->tmba
= tm_ubinfo
;
if (blkno
< dbtofsb(bp
->b_blkno
)) {
TMADDR
->tmbc
= blkno
- dbtofsb(bp
->b_blkno
);
TMADDR
->tmbc
= dbtofsb(bp
->b_blkno
) - blkno
;
tmtab
.b_actf
= bp
->av_forw
;
if (t_flags
&WAITREW
&& (TMADDR
->tmer
&RWS
) == 0) {
wakeup((caddr_t
)&t_flags
);
if ((bp
= tmtab
.b_actf
) == NULL
)
if ((bp
->b_flags
& B_READ
) == 0)
if (TMADDR
->tmcs
&ERROR
) {
while(TMADDR
->tmer
& SDWN
)
; /* await settle down */
tmseteof(bp
); /* set blkno and nxrec */
TMADDR
->tmbc
= -bp
->b_bcount
;
if ((bp
->b_flags
&B_READ
) && (TMADDR
->tmer
&(HARD
|SOFT
)) == RLE
)
if ((TMADDR
->tmer
&HARD
)==0 && state
==SIO
) {
if (++tmtab
.b_errcnt
< 7) {
if((TMADDR
->tmer
&SOFT
) == NXM
)
printf("TM UBA late error\n");
t_blkno
+= 2; /* ???????? */
} else if (t_openf
>0 && bp
!= &rtmbuf
)
deverror(bp
, t_erreg
, t_dsreg
);
if (++bp
->b_repcnt
< 0) {
tmstart(); /* continue */
tmtab
.b_actf
= bp
->av_forw
;
bp
->b_resid
= -TMADDR
->tmbc
;
t_blkno
= dbtofsb(bp
->b_blkno
);
if (t_blkno
> dbtofsb(bp
->b_blkno
)) {
t_nxrec
= dbtofsb(bp
->b_blkno
) - TMADDR
->tmbc
;
t_blkno
= dbtofsb(bp
->b_blkno
) + TMADDR
->tmbc
;
t_nxrec
= dbtofsb(bp
->b_blkno
);
physio(tmstrategy
, &rtmbuf
, dev
, B_READ
, minphys
);
physio(tmstrategy
, &rtmbuf
, dev
, B_WRITE
, minphys
);
a
= dbtofsb(u
.u_offset
>> 9);
tmioctl(dev
, cmd
, addr
, flag
)
/* we depend of the values and order of the MT codes here */
static tmops
[] = {WEOF
, SFORW
, SREV
, SFORW
, SREV
, REW
, OFFL
};
case MTIOCTOP
: /* tape operation */
if (copyin((caddr_t
)addr
, (caddr_t
)&mtop
, sizeof(mtop
))) {
case MTWEOF
: case MTFSF
: case MTBSF
:
callcount
= mtop
.mt_count
;
if (callcount
<= 0 || fcount
<= 0)
else while (--callcount
>= 0) {
tcommand(dev
, tmops
[mtop
.mt_op
], fcount
);
if ((mtop
.mt_op
== MTFSR
|| mtop
.mt_op
== MTBSR
) &&
if ((ctmbuf
.b_flags
&B_ERROR
) || t_erreg
&BOT
)
mtget
.mt_dsreg
= t_dsreg
;
mtget
.mt_erreg
= t_erreg
;
mtget
.mt_resid
= t_resid
;
if (copyout((caddr_t
)&mtget
, addr
, sizeof(mtget
)))
register struct uba_regs
*up
= (struct uba_regs
*)PHYSUBA0
;
TMPHYS
->tmcs
= DCLR
| GO
;
up
->uba_cr
= IFS
|BRIE
|USEFIE
|SUEFIE
;
while ((up
->uba_cnfgr
& UBIC
) == 0)
blk
= num
> DBSIZE
? DBSIZE
: num
;
bdp
= 1; /* crud to fool c compiler */
((struct uba_regs
*)PHYSUBA0
)->uba_dpr
[bdp
] |= BNE
;
bdp
= 1; /* more dastardly tricks on pcc */
((struct uba_regs
*)PHYSUBA0
)->uba_dpr
[bdp
] |= BNE
;
io
= (int *)((struct uba_regs
*)PHYSUBA0
)->uba_map
;
*io
++ = (int)(buf
++ | (1<<21) | MRV
);
TMPHYS
->tmbc
= -(num
*NBPG
);
TMPHYS
->tmcs
= WCOM
| GO
| D800
;
TMPHYS
->tmcs
= WEOF
| GO
| D800
;