zeta-v2: Add support for PPIDE storage
authorWill Sowerbutts <will@sowerbutts.com>
Fri, 24 Apr 2015 19:47:01 +0000 (20:47 +0100)
committerWill Sowerbutts <will@sowerbutts.com>
Fri, 24 Apr 2015 19:50:43 +0000 (20:50 +0100)
Kernel/platform-zeta-v2/Makefile
Kernel/platform-zeta-v2/config.h
Kernel/platform-zeta-v2/devices.c
Kernel/platform-zeta-v2/discard.c
Kernel/platform-zeta-v2/fuzix.lnk
Kernel/platform-zeta-v2/ppide.c [new file with mode: 0644]

index 718b662..1a168a2 100644 (file)
@@ -1,10 +1,10 @@
 ASRCS = crt0.s tricks.s commonmem.s zeta-v2.s monitor.s
 ASRCS += ds1302-n8vem.s devrd_hw.s
-CSRCS = devices.c main.c devtty.c devrd.c
+CSRCS = devices.c main.c devtty.c devrd.c ppide.c
 DISCARD_CSRCS = discard.c devtty_discard.c
-DISCARD_DSRCS = ../dev/ds1302_discard.c
+DISCARD_DSRCS = ../dev/ds1302_discard.c ../dev/devide_discard.c
 DSRCS = ../dev/devfd.c ../dev/devsd.c ../dev/mbr.c ../dev/blkdev.c
-DSRCS += ../dev/ds1302.c
+DSRCS += ../dev/ds1302.c ../dev/devide.c
 DASRCS = ../dev/devfd_hw.s
 
 AOBJS = $(ASRCS:.s=.rel)
@@ -47,4 +47,4 @@ image:
        sdasz80 -o bootrom.s
        sdldz80 -m -i bootrom.rel
        makebin -s 256 bootrom.ihx > bootrom.bin
-       cat bootrom.bin ../fuzix.bin > ../fuzix.rom
+       cat bootrom.bin ../fuzix.bin > fuzix.rom
index 4253422..22e808c 100644 (file)
@@ -35,7 +35,7 @@
 
 /* We need a tidier way to do this from the loader */
 #define CMDLINE        NULL  /* Location of root dev name */
-#define BOOTDEVICENAMES "fd,rd"
+#define BOOTDEVICENAMES "hd#,fd,,rd"
 
 //#define SWAPDEV  (256 + 1)  /* Device for swapping */
 #define NBUFS    10       /* Number of block buffers */
 #define CONFIG_RTC_INTERVAL 30 /* deciseconds between reading RTC seconds counter */
 
 /* Floppy support */
-#define CONFIG_FLOPPY          /* # define CONFIG_FLOPPY to enable floppy */
+#define CONFIG_FLOPPY          /* #define CONFIG_FLOPPY to enable floppy */
+
+/* PPIDE support */
+#define CONFIG_PPIDE           /* #define CONFIG_PPIDE to enable IDE on 8255A */
+#ifdef CONFIG_PPIDE
+#define PPIDE_BASE 0x60         /* Base address of 8255A */
+#define IDE_REG_INDIRECT        /* IDE registers are not directly connected to the CPU bus */
+
+/* IDE control signal to 8255 port C mapping */
+#define PPIDE_A0_LINE           0x01 // Direct from 8255 to IDE interface
+#define PPIDE_A1_LINE           0x02 // Direct from 8255 to IDE interface
+#define PPIDE_A2_LINE           0x04 // Direct from 8255 to IDE interface
+#define PPIDE_CS0_LINE          0x08 // Inverter between 8255 and IDE interface
+#define PPIDE_CS1_LINE          0x10 // Inverter between 8255 and IDE interface
+#define PPIDE_WR_LINE           0x20 // Inverter between 8255 and IDE interface
+#define PPIDE_WR_BIT            5    // (1 << PPIDE_WR_BIT) = PPIDE_WR_LINE
+#define PPIDE_RD_LINE           0x40 // Inverter between 8255 and IDE interface
+#define PPIDE_RD_BIT            6    // (1 << PPIDE_RD_BIT) = PPIDE_RD_LINE
+#define PPIDE_RST_LINE          0x80 // Inverter between 8255 and IDE interface
+
+/* 8255 configuration */
+#define PPIDE_PPI_BUS_READ      0x92
+#define PPIDE_PPI_BUS_WRITE     0x80
+
+/* IDE register addresses */
+#define ide_reg_data      (PPIDE_CS0_LINE)
+#define ide_reg_error     (PPIDE_CS0_LINE | PPIDE_A0_LINE)
+#define ide_reg_features  (PPIDE_CS0_LINE | PPIDE_A0_LINE)
+#define ide_reg_sec_count (PPIDE_CS0_LINE | PPIDE_A1_LINE)
+#define ide_reg_lba_0     (PPIDE_CS0_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE)
+#define ide_reg_lba_1     (PPIDE_CS0_LINE | PPIDE_A2_LINE)
+#define ide_reg_lba_2     (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A0_LINE)
+#define ide_reg_lba_3     (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE)
+#define ide_reg_devhead   (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE)
+#define ide_reg_command   (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE)
+#define ide_reg_status    (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE)
+#define ide_reg_altstatus (PPIDE_CS1_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE)
+#define ide_reg_control   (PPIDE_CS1_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE)
+#endif /* CONFIG_PPIDE */
 
 /* Optional ParPortProp board connected to PPI */
 //#define CONFIG_PPP           /* #define CONFIG_PPP to enable as tty3 */
 
 /* Device parameters */
+#define CONFIG_RAMDISK          /* enable memory-backed disk driver */
 #define NUM_DEV_RD 1
 #define DEV_RD_PAGES 16                /* size of the RAM disk in pages */
 #define DEV_RD_START 48                /* first page used by the RAM disk */
index 1e4af90..63bbb7d 100644 (file)
 struct devsw dev_tab[] =  /* The device driver switch table */
 {
 /*   open          close       read            write           ioctl */
-  /* 0: /dev/fd - Floppy disk block devices */
+  /* 0: /dev/hd - block device interface */
+#ifdef CONFIG_PPIDE
+  {  blkdev_open,   no_close,   blkdev_read,    blkdev_write,  blkdev_ioctl},
+#else
+  {  no_open,      no_close,   no_rdwr,        no_rdwr,        no_ioctl},
+#endif
+  /* 1: /dev/fd - Floppy disk block devices */
+#ifdef CONFIG_FLOPPY
   {  fd_open,      fd_close,   fd_read,        fd_write,       no_ioctl},
-  /* 1: /dev/hd - RAM disk interface */
-  {  rd_open,      no_close,   rd_read,        rd_write,       no_ioctl},
+#else
+  {  no_open,      no_close,   no_rdwr,        no_rdwr,        no_ioctl},
+#endif
   /* 2: /dev/tty -- serial ports */
   {  tty_open,     tty_close,  tty_read,       tty_write,      tty_ioctl},
-  /* 3: unused slot */
+  /* 3: RAM disk */
+#ifdef CONFIG_RAMDISK
+  {  rd_open,      no_close,   rd_read,        rd_write,       no_ioctl},
+#else
   {  no_open,      no_close,   no_rdwr,        no_rdwr,        no_ioctl},
+#endif
   /* 4: /dev/mem etc      System devices (one offs) */
   {  no_open,      no_close,   sys_read,       sys_write,      sys_ioctl},
 };
index 1a14456..4081d80 100644 (file)
@@ -5,6 +5,12 @@
 #include <ds1302.h>
 #include "config.h"
 
+#ifdef CONFIG_PPIDE
+#include <devide.h>
+
+void ppide_init(void);
+#endif
+
 void pagemap_init(void)
 {
        int i;
@@ -26,8 +32,13 @@ void map_init(void)
 {
 }
 
+
 void device_init(void)
 {
        ds1302_init();
        uart0_init();
+#ifdef CONFIG_PPIDE
+       ppide_init();
+       devide_init();
+#endif
 }
index a6fdec8..885f22f 100644 (file)
@@ -38,6 +38,9 @@ usermem_std-z80.rel
 platform-zeta-v2/discard.rel
 platform-zeta-v2/devtty.rel
 platform-zeta-v2/devtty_discard.rel
+platform-zeta-v2/ppide.rel
+platform-zeta-v2/devide.rel
+platform-zeta-v2/devide_discard.rel
 platform-zeta-v2/mbr.rel
 platform-zeta-v2/blkdev.rel
 platform-zeta-v2/ds1302.rel
diff --git a/Kernel/platform-zeta-v2/ppide.c b/Kernel/platform-zeta-v2/ppide.c
new file mode 100644 (file)
index 0000000..2e5d053
--- /dev/null
@@ -0,0 +1,123 @@
+/* 2015-04-24 WRS: devide glue functions for PPIDE */
+
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <timer.h>
+#include <devide.h>
+#include <blkdev.h>
+
+__sfr __at (PPIDE_BASE + 0x00) ppi_port_a;   /* IDE bus LSB */
+__sfr __at (PPIDE_BASE + 0x01) ppi_port_b;   /* IDE bus MSB */
+__sfr __at (PPIDE_BASE + 0x02) ppi_port_c;   /* IDE bus control signals */
+__sfr __at (PPIDE_BASE + 0x03) ppi_control;  /* 8255 command register */
+
+void ppide_init(void)
+{
+    ppi_control = PPIDE_PPI_BUS_READ;
+    ppi_port_c = ide_reg_status;
+}
+
+uint8_t devide_readb(uint8_t regaddr)
+{
+    uint8_t r;
+
+    /* note: ppi_control should contain PPIDE_PPI_BUS_READ already */
+    ppi_port_c = regaddr;
+    ppi_control = 1 | (PPIDE_RD_BIT << 1); /* begin /RD pulse */
+    r = ppi_port_a;
+    ppi_control = 0 | (PPIDE_RD_BIT << 1); /* end /RD pulse */
+    return r;
+}
+
+void devide_writeb(uint8_t regaddr, uint8_t value)
+{
+    ppi_control = PPIDE_PPI_BUS_WRITE;
+    ppi_port_c = regaddr;
+    ppi_port_a = value;
+    ppi_port_b = 0;
+    ppi_control = 1 | (PPIDE_WR_BIT << 1); /* begin /WR pulse */
+    ppi_control = 0 | (PPIDE_WR_BIT << 1); /* end /WR pulse */
+    ppi_control = PPIDE_PPI_BUS_READ;
+}
+
+/****************************************************************************/
+/* The innermost part of the transfer routines has to live in common memory */
+/* since it must be able to bank switch to the user memory bank.            */
+/****************************************************************************/
+COMMON_MEMORY
+
+void devide_read_data(void) __naked
+{
+    __asm
+            ld a, #ide_reg_data
+            ld c, #PPIDE_BASE+2                     ; select control lines
+            out (c), a                              ; select IDE data register
+            ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
+            ld d, #ide_reg_data                     ; register address
+            ld e, #ide_reg_data | PPIDE_RD_LINE     ; register address with /RD asserted
+            ld b, #0                                ; setup count
+            ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET) ; blkparam.is_user
+            or a                                    ; test is_user
+            push af                                 ; save flags
+            ld a, #PPIDE_BASE+0                     ; I will be needing this later
+            jr z, goread                            ; just start the transfer if kernel memory
+            call map_process_always                 ; else map user memory first
+goread:     ; now we do the transfer
+            out (c), e                              ; assert /RD
+            ld c, a                                 ; PPIDE_BASE
+            ini                                     ; read byte from LSB
+            inc c                                   ; up to MSB
+            ini                                     ; read byte from MSB
+            inc c                                   ; control lines
+            out (c), d                              ; de-assert /RD
+            inc b                                   ; (delay) counteract second ini instruction
+            jr nz, goread                           ; (delay) next word
+            ; read completed
+            pop af                                  ; recover is_user test result
+            ret z                                   ; done if kernel memory transfer
+            jp map_kernel                           ; else map kernel then return
+    __endasm;
+}
+
+void devide_write_data(void) __naked
+{
+    __asm
+            ld c, #PPIDE_BASE+2                     ; select control lines
+            ld a, #ide_reg_data
+            out (c), a                              ; select data register
+            ld a, #PPIDE_PPI_BUS_WRITE
+            inc c                                   ; up to 8255A command register
+            out (c), a                              ; 8255A ports A, B to output mode
+            dec c                                   ; back down to the control lines
+            ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
+            ld d, #ide_reg_data                     ; register address
+            ld e, #ide_reg_data | PPIDE_WR_LINE     ; register address with /WR asserted
+            ld b, #0                                ; setup count
+            ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET) ; blkparam.is_user
+            or a                                    ; test is_user
+            push af                                 ; save flags
+            ld a, #PPIDE_BASE+0                     ; I will be needing this later
+            jr z, gowrite                           ; just start the transfer if kernel memory
+            call map_process_always                 ; else map user memory first
+gowrite:    ; now we do the transfer
+            out (c), d                              ; de-assert /WR
+            ld c, a                                 ; PPIDE_BASE
+            outi                                    ; write byte to LSB
+            inc c                                   ; up to MSB
+            outi                                    ; write byte to MSB
+            inc c                                   ; up to control lines
+            out (c), e                              ; assert /WR
+            inc b                                   ; (delay) offset to counteract second outi instruction
+            jr nz, gowrite                          ; (delay) next word
+            ; write completed
+            out (c), d                              ; de-assert /WR
+            ld a, #PPIDE_PPI_BUS_READ
+            inc c                                   ; up to 8255A command register
+            out (c), a                              ; 8255A ports A, B to read mode
+            pop af                                  ; recover is_user test result
+            ret z                                   ; done if kernel memory transfer
+            jp map_kernel                           ; else map kernel then return
+    __endasm;
+}