* Cypher tape driver. Stand alone version.
#include "machine/mtpr.h"
#include "tahoevba/cyreg.h"
#include "tahoevba/vbaparam.h"
* NB: this driver assumes unit 0 throughout.
long cystd
[] = { 0xf4000, 0 };
#define CYADDR(i) (cystd[i] + (int)VBIOBASE)
struct cyscp
*cyscp
[] = { (struct cyscp
*)0xc06, (struct cyscp
*)0 };
#define CYSCP(i) (cyscp[i])
struct cytpb cycool
; /* tape parameter block to clear interrupts */
int cyblocksize
= 1024; /* foreign tape size as found in open routine */
int cybufsize
; /* controller buffer size */
long cyblock
; /* next block number for i/o */
register ctlradr
= CYADDR(0);
SCP
= CYSCP(0); /* absolute - for setup */
CY_RESET(ctlradr
); /* reset the controller */
* Initialize the system configuration pointer
SCP
->csp_buswidth
= 1; /* system width = 16 bits. */
/* initialize the pointer to the system configuration block */
cyldmba(SCP
->csp_scb
, (caddr_t
)&scb
);
* Initialize the system configuration block.
scb
.csb_fixed
= CSB_FIXED
; /* fixed value */
/* initialize the pointer to the channel control block */
cyldmba(scb
.csb_ccb
, (caddr_t
)&ccb
);
* Initialize the channel control block.
ccb
.cbcw
= CBCW_IE
; /* normal interrupts */
/* initialize the pointer to the tape parameter block */
cyldmba(ccb
.cbtpb
, (caddr_t
)&tpb
);
* set the command to be CY_NOP.
* TPB not used on first attention
tpb
.tpcontrol
= CYCW_LOCK
| CYCW_16BITS
;
ccb
.cbgate
= GATE_CLOSED
;
CY_GO(ctlradr
); /* execute! */
* set the command to be CY_CONFIGURE.
* NO interrupt on completion.
tpb
.tpcontrol
= CYCW_LOCK
| CYCW_16BITS
;
ccb
.cbgate
= GATE_CLOSED
;
CY_GO(ctlradr
); /* execute! */
if (tpb
.tpstatus
& CYS_ERR
) {
printf("Cypher initialization error!\n");
cy_print_error(tpb
.tpcmd
, tpb
.tpstatus
);
if (cycmd(io
, CY_REW
) == -1) {
printf("cy%d: Rewind failed!\n", io
->i_unit
);
for (skip
= io
->i_part
; skip
--;)
if (cycmd(io
, CY_FSF
) == -1) {
printf("cy%d: seek failure!\n", io
->i_unit
);
if (io
->i_flgs
& F_READ
) {
cyblocksize
= cycmd(io
, CY_READFORN
);
_stop("Read foreign tape failed\n");
cyblock
++; /* XXX force backspace record */
if (cycmd(io
, CY_SFORW
) == -1)
_stop("Backspace after read foreign failed\n");
if (io
->i_flgs
& F_WRITE
) { /* if writing, write file marks */
if (func
!= CY_SFORW
&& func
!= CY_REW
&& io
->i_bn
!= cyblock
) {
if (func
== READ
|| func
== WRITE
) {
register struct iob
*lio
= &liob
;
if ((count
= cycmd(lio
, func
)) == 0) {
printf("cy%d: I/O error bn %d\n",
printf("cy%d: I/O error bn %d\n", io
->i_unit
, io
->i_bn
);
register ctlradr
= CYADDR(0);
cywait(9000); /* shouldn't be needed */
#define PACKUNIT(unit) (((unit&1)<<11)|((unit&2)<<9)|((unit&4)>>2))
tpb
.tpcontrol
= CYCW_LOCK
| CYCW_16BITS
| PACKUNIT(io
->i_unit
);
cyldmba(ccb
.cbtpb
, (caddr_t
)&tpb
);
if (io
->i_cc
> cyblocksize
)
tpb
.tpsize
= htoms(cyblocksize
);
tpb
.tpsize
= htoms(io
->i_cc
);
cyldmba(tpb
.tpdata
, io
->i_ma
);
tpb
.tpsize
= htoms(io
->i_cc
);
cyldmba(tpb
.tpdata
, io
->i_ma
);
if ((j
= io
->i_bn
- cyblock
) < 0) {
tpb
.tpcontrol
|= CYCW_REV
;
ccb
.cbgate
= GATE_CLOSED
;
CY_GO(ctlradr
); /* execute! */
* First we clear the interrupt and close the gate.
ccb
.cbgate
= GATE_CLOSED
;
cyldmba(ccb
.cbtpb
, (caddr_t
)&cycool
);
cycool
.tpcontrol
= CYCW_LOCK
; /* No INTERRUPTS */
if ((err
= (tpb
.tpstatus
& CYS_ERR
)) &&
err
!= CYER_FM
&& (err
!= CYER_STROBE
|| tpb
.tpcmd
!= CY_RCOM
)) {
cy_print_error(tpb
.tpcmd
, tpb
.tpstatus
);
return ((int)htoms(tpb
.tpcount
));
cy_print_error(op
, status
)
if ((status
& CYS_ERR
) < NCYERROR
)
message
= cyerror
[status
& CYS_ERR
];
message
= "unknown error";
printf("cy0: cmd %x %s, status=%b.\n", op
, message
, status
, CYS_BITS
);
} while (ccb
.cbgate
!= GATE_OPEN
&& --timeout
> 0);
_stop("cy: Transfer timeout");
* Load a 20 bit pointer into a Tapemaster pointer.
register int v
= (int)value
;
*reg
= (v
&0xf0000) >> 12;