appleiie: more sketching out of the platform code
authorAlan Cox <alan@linux.intel.com>
Mon, 22 Jan 2018 21:46:40 +0000 (21:46 +0000)
committerAlan Cox <alan@linux.intel.com>
Mon, 22 Jan 2018 21:46:40 +0000 (21:46 +0000)
Kernel/platform-appleiie/README
Kernel/platform-appleiie/apple.h [new file with mode: 0644]
Kernel/platform-appleiie/appleii.s
Kernel/platform-appleiie/devhd.c
Kernel/platform-appleiie/devhd.h
Kernel/platform-appleiie/devtty.c
Kernel/platform-appleiie/main.c

index 022e2da..f5e93f1 100644 (file)
@@ -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 (file)
index 0000000..452d2e8
--- /dev/null
@@ -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
index b2a572c..c8fe373 100644 (file)
@@ -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
index 4d0839d..dfc7b7c 100644 (file)
@@ -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 <kdata.h>
 #include <printf.h>
 #include <devhd.h>
+#include <apple.h>
 
 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 */
+    }
 }
index ed8a82e..599dfa0 100644 (file)
@@ -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__ */
index 12cbbb2..e885c79 100644 (file)
@@ -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;
index df71342..fe7b69e 100644 (file)
@@ -4,14 +4,14 @@
 #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)
 {
@@ -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;