* Cypher tape driver. Stand alone version.
#include "../machine/pte.h"
#include "../machine/mtpr.h"
#include "../tahoevba/vbaparam.h"
long cystd
[] = { 0xf4000, 0 };
#define CYADDR(i) (cystd[i] + (int)VBIOBASE)
char sysbus
; /* width of system bus 0=8;1=16 */
char sysblk
[1]; /* 0x03 fixed value code */
char ccw
[1]; /* 0x11 normal; 0x09 clear non_vect interrupt */
char gate
[1]; /* This is "the" GATE */
long cmd
; /* COMMAND (input) */
char control
[2]; /* CONTROL (input) */
short count
; /* RETURN COUNT (output) */
short size
; /* BUFFER SIZE (input/output) */
short rec_over
; /* RECORDS/OVERRUN (input/output) */
char pt_data
[4]; /* pointer to ->SOURCE/DEST (input) */
char status
[2]; /* STATUS (output) */
struct tpb cycool
; /* tape parameter block to clear interrupts */
int cyblocksize
= 1024; /* foreign tape size as found in open routine */
long cyblock
; /* next block number for i/o */
register ctlradr
= CYADDR(0);
SCP
= (struct scp
*)0xc06; /* absolute - for setup */
TM_RESET(ctlradr
,0xff); /* reset the controller */
* Initialize the system configuration pointer
SCP
->sysbus
= 1; /* system width = 16 bits. */
/* initialize the pointer to the system configuration block */
set_pointer((long)&scb
.sysblk
[0],(char *)SCP
->pt_scb
);
* Initialize the system configuration block.
scb
.sysblk
[0] = 0x3; /* fixed value */
/* initialize the pointer to the channel control block */
set_pointer((long)&ccb
.ccw
[0],(char *)scb
.pt_ccb
);
* Initialize the channel control block.
ccb
.ccw
[0] = 0x11; /* normal interrupts */
/* initialize the pointer to the tape parameter block */
set_pointer((long)&tpb
,(char *)ccb
.pt_tpb
);
* set the command to be NO_OP.
tpb
.control
[0] = CW_BL
; /* TPB not used on first attention */
tpb
.control
[1] = CW_16bits
;
ccb
.gate
[0] = GATE_CLOSED
;
TM_ATTENTION(ctlradr
, 0xff); /* execute! */
* set the command to be CONFIGURE.
tpb
.control
[0] = CW_BL
; /* NO interrupt on completion */
tpb
.control
[1] = CW_16bits
;
tpb
.status
[0] = tpb
.status
[1] = 0;
ccb
.gate
[0] = GATE_CLOSED
;
TM_ATTENTION(ctlradr
, 0xff); /* execute! */
if (tpb
.status
[1] & CS_ERm
) {
printf("Cypher initialization error!\n");
(void) cy_decode_error(tpb
.status
[1]&CS_ERm
);
if (cycmd(io
, REWD_TA
) == -1)
_stop("Rewind failed!\n");
if (cycmd(io
, SRFM_FD
) == -1)
_stop("cy: seek failure!\n");
if (io
->i_flgs
& F_READ
) {
cyblocksize
= cycmd(io
, READ_FO
);
_stop("Read foreign tape failed\n");
cyblock
++; /* XXX force backspace record */
if (cycmd(io
, SPACE
) == -1)
_stop("Backspace after read foreign failed\n");
if (io
->i_flgs
& F_WRITE
) /* if writing, write file mark */
if (func
!= SPACE
&& func
!= REWD_TA
&& io
->i_bn
!= cyblock
) {
if (func
== READ
|| func
== WRITE
) {
register struct iob
*lio
= &liob
;
if ((count
= cycmd(lio
, func
)) == 0)
return (cycmd(io
, func
));
register ctlradr
= CYADDR(0);
tpb
.control
[1] = CW_16bits
;
tpb
.status
[0] = tpb
.status
[1] = 0;
set_pointer((long)&tpb
, (char *)ccb
.pt_tpb
);
if (io
->i_cc
> cyblocksize
)
tpb
.size
= TM_SHORT(cyblocksize
);
tpb
.size
= TM_SHORT(io
->i_cc
);
set_pointer((long)io
->i_ma
,(char *)tpb
.pt_data
);
tpb
.size
= TM_SHORT(io
->i_cc
);
set_pointer((long)io
->i_ma
, (char *)tpb
.pt_data
);
if ((j
= io
->i_bn
- cyblock
) < 0) {
tpb
.rec_over
= TM_SHORT(j
);
tpb
.rec_over
= TM_SHORT(1);
ccb
.gate
[0] = GATE_CLOSED
;
TM_ATTENTION(ctlradr
, 0xff); /* execute! */
* First we clear the interrupt and close the gate.
ccb
.gate
[0] = GATE_CLOSED
;
set_pointer((int)&cycool
, (char *)ccb
.pt_tpb
);
cycool
.cmd
= NO_OP
; /* no operation */
cycool
.control
[0] = CW_BL
; /* No INTERRUPTS */
TM_ATTENTION(ctlradr
, 0xff); /* cool it ! */
if (tpb
.status
[1] & CS_ERm
&& cy_decode_error(tpb
.status
[1]&CS_ERm
)) {
return ((int)TM_SHORT(tpb
.count
));
printf("cy0: %s.\n", message
);
cyprint_error("Drive timed out during transfer");
cyprint_error("Non-existant system memory reference");
cyprint_error("Controller micro diagnostics failed");
cyprint_error("Unrecoverable media error");
cyprint_error("Unsatisfactory media");
return (0); /* short read */
cyprint_error("Data transfer over run");
cyprint_error("Drive is not ready");
cyprint_error("Tape is write protected");
cyprint_error("Checksum error in controller proms");
cyprint_error("Unrecoverable tape parity error");
cyprint_error("Blank tape found where data was expected");
cyprint_error("Unrecoverable hardware error");
case ER_FMAR
: /* file mark */
printf("cy: unknown error: status %x.\n", status
);
} while (ccb
.gate
[0] != GATE_OPEN
&& --timeout
> 0);
_stop("cy: Transfer timeout");
* Set a TAPEMASTER pointer (first parameter), into the
* 4 bytes array pointed by the second parameter.
set_pointer(pointer
,dest
)
*dest
++ = pointer
& 0xff; /* low byte - offset */
*dest
++ = (pointer
>> 8) & 0xff; /* high byte - offset */
*dest
= (pointer
& 0xf0000) >> 12; /* base */