* Stringy tape wrapper. Note that the asm code uses the ROM which
* also uses some values in 0x40xx (40B1 and 401A in particular)
*/
-static uint8_t fileid = 255;
+static uint8_t fileid = 1;
static uint8_t mode;
static uint8_t inpos = 0; /* in position */
static uint8_t inio = 0;
+static uint8_t curtape = 255;
static int busy = 0;
uint8_t tape_err;
/* EOF on read */
if (a & 0x80)
return 0;
+ /* Write protected */
+ if (a & 0x01)
+ udata.u_error = EROFS;
/* BREAK */
if (a & 0x02)
udata.u_error = EINTR;
else
udata.u_error = EIO;
kprintf("tape: error %x\n", a);
+ inpos = inio = 0;
return -1;
}
int tape_open(uint8_t minor, uint16_t flag)
{
minor; flag;
+ uint8_t unit;
/* Check for the floppy tape ROM */
if (*((uint16_t *)0x3034) != 0x3C3C) {
return -1;
}
- if (minor > 15 || tape_op(minor & 0x07, TAPE_SELECT)) {
+ unit = minor & 7;
+
+ if (unit != curtape && tape_op(unit, TAPE_SELECT)) {
udata.u_error = ENODEV;
return -1;
}
+
/* Can't open for mixed read/write at the same time */
if (O_ACCMODE(flag) == O_RDWR) {
udata.u_error = EINVAL;
}
mode = O_ACCMODE(flag);
- if ((minor & 0x08) || fileid == 255)
+ if (minor & 0x08)
if (tape_rewind())
return -1;
/* Only one drive can be used at a time */
busy = 1;
- inio = 0;
- tape_err = 0;
+ if (unit != curtape) {
+ inio = 0;
+ tape_err = 0;
+ fileid = 1;
+ curtape = unit;
+ }
return 0;
}
int tape_close(uint8_t minor)
{
minor;
+ busy = 0;
+ inio = 0;
if (mode == O_WRONLY)
if (tape_op(fileid, TAPE_CLOSEW))
return tape_error();
+ if (fileid < 99)
+ fileid++;
return 0;
}
static int tape_rw(uint8_t op)
{
+ uint8_t pos = fileid;
+
if (!inpos) {
- if (tape_op(fileid, TAPE_FIND) == 0)
- inpos = 1;
- else
- return tape_error();
-
+ pos--;
+ kprintf("find %d\n", pos);
+ if (!pos && tape_rewind() == 0)
+ inpos = 1;
+ else if (pos && tape_op(pos, TAPE_FIND) == 0)
+ inpos = 1;
+ else
+ return tape_error();
}
+ kprintf("do tapeop %d %d\n", fileid, op);
inio = 1;
udata.u_done = tape_op(fileid, op);
+ kprintf("read %d\n", udata.u_done);
if (tape_err)
return tape_error();
return udata.u_done;
static struct mtstatus tapei = {
MT_TYPE_EXATRON,
0,
- ~0
+ ~0UL
};
int tape_ioctl(uint8_t minor, uarg_t op, char *ptr)
if (inpos)
tapei.mt_file = fileid;
else
- tapei.mt_file = ~0;
+ tapei.mt_file = 0xFFFF;
return uput(&tapei, ptr, sizeof(tapei));
}
/* Now calls we can only make when not mid stream */
udata.u_error = EINVAL;
return -1;
}
+
+void tape_init(void)
+{
+ *(uint16_t*)0x40b1 = 0x4000; /* Somewhere to put the tape variables */
+}
.globl go_slow
.globl go_fast
+ .globl map_process_always
+ .globl map_kernel_restore
+
_tape_op:
call go_slow
- pop bc
- pop de
- push de ; file ID in D op in E
- push bc
- ld hl,(U_DATA__U_BASE)
- ld bc,(U_DATA__U_COUNT)
+ call map_process_always
+ call do_tape_op
+ push af
+ call map_kernel_restore
+ call go_fast
+ pop af
+ ret
+
+do_tape_op:
xor a
ld (_tape_err),a
- ld a,e
+
+ ld hl,#6 ; SP + 6
+ add hl,sp
+ ld d,(hl)
+ inc hl
+ ld a,(hl)
+
+ ld hl,(U_DATA__U_BASE)
+ ld bc,(U_DATA__U_COUNT)
or a
jr z, write_op
dec a
dec a
jr z, erase_op
ld hl,#0xFFFF
- call go_fast
ret
find_op:
ld a,d
ld a,d
call 0x300F ; find file A
tape_error:
- push af
- call go_fast
- pop af
ld hl,#0 ; return 0 if good or -1 if bad and save err
ret z
dec hl
jr tape_error ; file 0 itself)
read_op:
call 0x3003
- push af
- call go_fast
- pop af
ld h,b
ld l,c ; actual bytes fetched
ret z
ret
write_op:
call 0x3006
- push af
- call go_fast
- pop af
ld hl,(U_DATA__U_COUNT)
ret z
jr rwerr