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
--- /dev/null
+#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
.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
* 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
#include <kdata.h>
#include <printf.h>
#include <devhd.h>
+#include <apple.h>
extern uint8_t hd_map;
uint8_t rw_cmd[7];
{
uint16_t dptr, nb;
uint8_t err;
+ uint8_t slotbit = 1 << (minor >> 5);
/* FIXME: swap support */
if(rawflag == 1 && d_blkoff(9))
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);
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;
}
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 */
+ }
}
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__ */
/* 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;
#include <printf.h>
#include <devtty.h>
#include <devhd.h>
+#include <apple.h>
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)
{
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 */
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;
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;