From: Alan Cox Date: Mon, 22 Jan 2018 21:46:40 +0000 (+0000) Subject: appleiie: more sketching out of the platform code X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=3643a69ab78f17c167ebd12d835a509cc50461a2;p=FUZIX.git appleiie: more sketching out of the platform code --- diff --git a/Kernel/platform-appleiie/README b/Kernel/platform-appleiie/README index 022e2dae..f5e93f1b 100644 --- a/Kernel/platform-appleiie/README +++ b/Kernel/platform-appleiie/README @@ -66,6 +66,8 @@ Our planned memory mapping looks like this BF00-BFFF ProDOS leaves us info here before we kill it off C000-CFFF I/O D000-FFFF Kernel (with a 4K extra overlay if we need it) + (and we might want to leave some ProDOS driver code from F800 up or + so to drive the 140K floppies) And in alt banks diff --git a/Kernel/platform-appleiie/apple.h b/Kernel/platform-appleiie/apple.h new file mode 100644 index 00000000..452d2e89 --- /dev/null +++ b/Kernel/platform-appleiie/apple.h @@ -0,0 +1,18 @@ +#ifndef _APPLE_H +#define _APPLE_H + +extern uint8_t kernel_flag; +extern uint8_t cols; +extern uint8_t card_present; +extern uint8_t prodos_slot; +extern uint8_t pascal_slot; +extern uint8_t model; + +#define APPLE_UNKNOWN 0 +#define APPLE_IIE 1 +#define APPLE_IIC 2 + +extern uint8_t pascal_status(uint8_t, uint8_t); +extern uint8_t statusdata[]; + +#endif diff --git a/Kernel/platform-appleiie/appleii.s b/Kernel/platform-appleiie/appleii.s index b2a572cd..c8fe3731 100644 --- a/Kernel/platform-appleiie/appleii.s +++ b/Kernel/platform-appleiie/appleii.s @@ -534,12 +534,20 @@ _platform_interrupt_i: .segment "COMMONDATA" + .export _statusdata _hd_map: .res 1 +_statusdata: + .res 8 .code ; Dummy stubs for now - .export _block_rw + .export _block_rw_pascal + .export _block_rw_prodos + .export _pascal_status +_block_rw_pascal: +_block_rw_prodos: + rts -_block_rw: +_pascal_status: rts diff --git a/Kernel/platform-appleiie/devhd.c b/Kernel/platform-appleiie/devhd.c index 4d0839da..dfc7b7cd 100644 --- a/Kernel/platform-appleiie/devhd.c +++ b/Kernel/platform-appleiie/devhd.c @@ -11,7 +11,6 @@ * smartport devices. * * TODO: - * PASCAL or ProDOS entry points ? * if it reports removable ensure we flush buffers on close * if it reports formatting add an ioctl * if it doesn't report interruptible ensure the asm cli's it @@ -22,6 +21,7 @@ #include #include #include +#include extern uint8_t hd_map; uint8_t rw_cmd[7]; @@ -32,6 +32,7 @@ static int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) { uint16_t dptr, nb; uint8_t err; + uint8_t slotbit = 1 << (minor >> 5); /* FIXME: swap support */ if(rawflag == 1 && d_blkoff(9)) @@ -45,27 +46,30 @@ static int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) while (udata.u_nblock--) { /* Fill in the protocol convertor information */ /* Note hd_map will be fun to handle */ -#ifdef CONFIG_PASCAL - rw_cmd[0] = is_read ? 0x03 : 0x04; - rw_cmd[1] = minor & 0x1F; + rw_cmd[2] = dptr; rw_cmd[3] = dptr >> 8; rw_cmd[4] = udata.u_block; rw_cmd[5] = udata.u_block >> 8; rw_cmd[6] = 0; /* If we do big disks this will be 16-23 */ -#else - /* DOS mode only allows 2 devices/slot */ - rw_cmd[0] = is_read ? 1 : 2; - /* FIXME: check these are correct shifts */ - rw_cmd[1] = ((minor & 0xE0) >> 2); - rw_cmd[1] |= (minor & 3) << 6; - rw_cmd[2] = dptr; - rw_cmd[3] = dptr >> 8; - rw_cmd[4] = udata.u_block; - rw_cmd[5] = udata.u_block >> 8; -#endif - err = block_rw(); + if (pascal_slot & slotbit) { + rw_cmd[0] = is_read ? 0x03 : 0x04; + rw_cmd[1] = minor & 0x1F; + if (rawflag) + rw_cmd[6] = 0x80; /* Should select alt bank */ + err = block_rw_pascal(); + } else { + /* DOS mode only allows 2 devices/slot */ + /* TODO: No alt bank access */ + rw_cmd[0] = is_read ? 1 : 2; + /* FIXME: check these are correct shifts */ + rw_cmd[1] = ((minor & 0xE0) >> 2); + if (minor & 1) + rw_cmd[1] |= 0x80; + rw_cmd[1] |= (minor & 1) << 6; + err = block_rw_prodos(); + } if (err) { kprintf("hd%d: disk error %x\n", err); @@ -83,20 +87,36 @@ static int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) int hd_open(uint8_t minor, uint16_t flag) { uint8_t slot = minor >> 5; + uint8_t unit = minor & 31; used(flag); -#ifndef CONFIG_PASCAL - /* FIXME: may need a core tweak to match */ - if ((readonly & (1 << slot)) && O_ACCMODE(flag)) { - udata.u_error = EROFS; - return -1; - } -#endif /* Non block device slots have 0 here */ - if ((minor & 0x1F) >= block_units[slot]) { + if (unit >= block_units[slot]) { udata.u_error = ENXIO; return -1; } + if (pascal_slot & (1 << slot)) { + if (pascal_status(slot, unit) || (statusdata[0] & 0xA0) != 0xA0) { + udata.u_error = ENXIO; + return -1; + } + /* It's readable and block - good signs */ + if ((statusdata[0] & 4) || (O_ACCMODE(flag) && !(statusdata[0] & 0x40))) { + udata.u_error = EROFS; + return -1; + } + if (!(statusdata[0] & 0x10)) { + /* FIXME: better errno code */ + udata.u_error = ENXIO; + return -1; + } + } else { + if (( readonly & (1 << slot)) && O_ACCMODE(flag)) { + udata.u_error = EROFS; + return -1; + } + /* FIXME: ProDOS status wants doing here for media check */ + } return 0; } @@ -117,9 +137,19 @@ int hd_write(uint8_t minor, uint8_t rawflag, uint8_t flag) void hd_install(uint8_t slot) { uint8_t *p = (uint8_t *)0xC000 + (((uint16_t)slot) << 8); + uint8_t err; - if (!(p[254] & 4)) - readonly |= (1 << slot); - block_units[slot] = (p[254] >> 4) & 3 + 1; - /* And at this point we ought to scan it for a swap signature */ + if (pascal_slot & (1 << slot)) { + err = pascal_status(slot, 0); + if (err) { + kprintf("Slot %d device install failed: stat %d\n", slot, err); + return; + } + block_units[slot] = statusdata[0]; + } else { + if (!(p[254] & 4)) + readonly |= (1 << slot); + block_units[slot] = (p[254] >> 4) & 3 + 1; + /* And at this point we ought to scan it for a swap signature */ + } } diff --git a/Kernel/platform-appleiie/devhd.h b/Kernel/platform-appleiie/devhd.h index ed8a82e6..599dfa0c 100644 --- a/Kernel/platform-appleiie/devhd.h +++ b/Kernel/platform-appleiie/devhd.h @@ -8,7 +8,8 @@ int hd_open(uint8_t minor, uint16_t flag); void hd_install(uint8_t slot); extern uint8_t rw_cmd[7]; -extern uint8_t block_rw(void); +extern uint8_t block_rw_pascal(void); +extern uint8_t block_rw_prodos(void); extern uint8_t block_units[8]; #endif /* __DEVHD_DOT_H__ */ diff --git a/Kernel/platform-appleiie/devtty.c b/Kernel/platform-appleiie/devtty.c index 12cbbb2b..e885c794 100644 --- a/Kernel/platform-appleiie/devtty.c +++ b/Kernel/platform-appleiie/devtty.c @@ -9,11 +9,11 @@ /* Ignore super serial and friends for the moment */ -static volatile uint8_t *kbd_read = (volatile uint8_t *)0xC000; -static volatile uint8_t *kbd_strobe = (volatile uint8_t *)0xC010; +#define kbd_read ((volatile uint8_t *)0xC000) +#define kbd_strobe ((volatile uint8_t *)0xC010) /* Assume a //c for the moment */ -static volatile uint8_t *irq_check = (volatile uint8_t *)0xC041; -static volatile uint8_t *irq_reset = (volatile uint8_t *)0xC019; +#define irq_check ((volatile uint8_t *)0xC041) +#define irq_reset ((volatile uint8_t *)0xC019) static char tbuf1[TTYSIZ]; PTY_BUFFERS; diff --git a/Kernel/platform-appleiie/main.c b/Kernel/platform-appleiie/main.c index df71342c..fe7b69e2 100644 --- a/Kernel/platform-appleiie/main.c +++ b/Kernel/platform-appleiie/main.c @@ -4,14 +4,14 @@ #include #include #include +#include uint8_t kernel_flag = 1; uint8_t cols = 40; uint8_t card_present; +uint8_t prodos_slot; +uint8_t pascal_slot; uint8_t model; -#define APPLE_UNKNOWN 0 -#define APPLE_IIE 1 -#define APPLE_IIC 2 void platform_idle(void) { @@ -68,6 +68,66 @@ static void unsupported(void) kputs(" (unsupported) "); } +/* Make sure all the strings in this lot end up in discard */ +static const char *classid[] = { + "printer", + "joystick", + "serial/parallel", + "modem", + "sound/speech", + "clock", + "storage", + "80 column card", + "network/bus", + "special" +}; + +static void pascal_card(uint8_t slot, uint8_t cid) +{ + uint8_t class = cid >> 4; + if (class == 0 || class > 10) { + kputs("unknown"); + return; + } + kputs(classid[class - 1]); + switch(class) { +#if 0 + case 1: + printer_install(slot, cid); + break; + case 2: + joystick_install(slot, cid); + break; + case 3: + /* 31 is superserial etc */ + serial_install(slot, cid); + break; + case 4: + serial_install(slot, cid); + break; + case 5: + audio_install(slot, cid); + break; + case 6: + clock_install(slot, cid); + break; + case 8: + break; + case 9: + network_install(slot, cid); + break; + case 10: + special_install(slot, cid); + break; +#endif + case 7: + hd_install(slot); + break; + default: + unsupported(); + } +} + /* Slot detection on Apple is a bit magic. It started out as sneaky ROM peeking and evolved later into proper protocols */ @@ -82,20 +142,38 @@ void scan_slots(void) kputs("empty"); continue; } + /* Pascal and also Serial cards: from dumb to dumber if they don't + have the Pascal interface present */ + if (card[5] == 0x38 && card[7] == 0x18) { + if (card[11] == 0x01) { + /* This slot has a pascal (aka Protocol Convertor) attached. + In other words basically we've got device driver firmware + that does all the work for us, and we have a card id for + type/device */ + pascal_slot |= (1 << i); + pascal_card(i, card[12]); + } else { + kputs("serial"); + unsupported(); + } + continue; + } + /* This is how ProDOS finds disk driver interfaces. The ProDOS + interface isn't as nice as the Pascal one */ if (card[1] == 0x20 && card[3] == 0x00 && card[5] == 0x03) { /* storage */ - - /* Old ROM floppy drive: needs custom driver */ if (card[255] == 0xFF) { + /* Old ROM floppy drive: needs custom driver */ kputs("13 sector/track floppy"); unsupported(); - } - /* New ROM floppy drive: needs custom driver */ - else if (card[255] == 0x00) { + } else if (card[255] == 0x00) { + /* New ROM floppy drive: needs custom driver */ kputs("16 sector/track floppy"); unsupported(); - } else { /* We use the firmware interface */ + } else { + /* We use the firmware interface */ kputs("storage"); + prodos_slot |= (1 << i); hd_install(i); } continue; @@ -111,17 +189,8 @@ void scan_slots(void) kputs("mouse"); continue; } - /* Serial cards: from dumb to dumber */ - if (card[5] == 0x38 && card[7] == 0x18) { - if (card[11] == 0x01 && card[12] == 0x31) - kputs("super serial"); - else { - kputs("serial"); - unsupported(); - } - continue; - } - if (card[0] == 0x08 && card[2] == 0x28 && card[4] == 0x5B && + /* This is how ProDOS recognizes a clock card */ + if (card[0] == 0x08 && card[2] == 0x28 && card[4] == 0x58 && card[6] == 0x70) { kputs("clock"); continue;