z80: split the IDE driver __DISCARD up and remove the feature
authorAlan Cox <alan@linux.intel.com>
Thu, 12 Feb 2015 01:54:47 +0000 (01:54 +0000)
committerAlan Cox <alan@linux.intel.com>
Thu, 12 Feb 2015 01:54:47 +0000 (01:54 +0000)
We can't have multiple banked and unbanked segments in one object file as
we then have no way to make the banked linker and binmunge fix them up. The
common piece is ok as it doesn't call out to other segments in the same file
likewise calls to common code is ok. Calls betweem banks however don't end
well.

Kernel/cpu-z80/cpu.h
Kernel/dev/devide.c
Kernel/dev/devide.h
Kernel/dev/devide_discard.c [new file with mode: 0644]
Kernel/platform-zx128/Makefile
Kernel/platform-zx128/fuzix.lnk

index 38a76fc..77c3893 100644 (file)
@@ -68,7 +68,6 @@ typedef union {            /* this structure is endian dependent */
 #define cpu_to_le32(x) (x)
 #define le32_to_cpu(x) (x)
 
-#define DISCARDABLE     static void DISCARDSEG(void) __naked { __asm .area _DISCARD __endasm; }
 /* Do not use COMMON_MEMORY except for __asm code blocks. The SDCC helpers are not
    loaded into common */
 #define COMMON_MEMORY   static void COMMONSEG(void)  __naked { __asm .area _COMMONMEM __endasm; }
index e83784c..c07b148 100644 (file)
@@ -7,6 +7,8 @@
 /* 2015-01-25 WRS updated to newer blkdev API                            */
 /*-----------------------------------------------------------------------*/
 
+#define _IDE_PRIVATE
+
 #include <kernel.h>
 #include <kdata.h>
 #include <printf.h>
 #include <devide.h>
 #include <blkdev.h>
 
-#define DRIVE_COUNT 2           /* at most 2 drives without adjusting DRIVE_NR_MASK */
-
-/* we use the bits in the driver_data field of blkdev_t as follows: */
-#define DRIVE_NR_MASK    0x01   /* low bit used to select the drive number -- extend if more required */
-#define FLAG_CACHE_DIRTY 0x40
-#define FLAG_WRITE_CACHE 0x80
-
-#ifdef IDE_REG_ALTSTATUS
-__sfr __at IDE_REG_ALTSTATUS ide_reg_altstatus;
-#endif
-#ifdef IDE_REG_CONTROL
-__sfr __at IDE_REG_CONTROL   ide_reg_control;
-#endif
-__sfr __at IDE_REG_COMMAND   ide_reg_command;
-__sfr __at IDE_REG_DATA      ide_reg_data;
-__sfr __at IDE_REG_DEVHEAD   ide_reg_devhead;
-__sfr __at IDE_REG_ERROR     ide_reg_error;
-__sfr __at IDE_REG_FEATURES  ide_reg_features;
-__sfr __at IDE_REG_LBA_0     ide_reg_lba_0;
-__sfr __at IDE_REG_LBA_1     ide_reg_lba_1;
-__sfr __at IDE_REG_LBA_2     ide_reg_lba_2;
-__sfr __at IDE_REG_LBA_3     ide_reg_lba_3;
-__sfr __at IDE_REG_SEC_COUNT ide_reg_sec_count;
-__sfr __at IDE_REG_STATUS    ide_reg_status;
-
-static void devide_read_data(void);
 static void devide_write_data(void);
 
-static bool devide_wait(uint8_t bits)
+bool devide_wait(uint8_t bits)
 {
     uint8_t status;
     timer_t timeout;
@@ -65,10 +41,10 @@ static bool devide_wait(uint8_t bits)
             kprintf("ide timeout, status=%x\n", status);
             return false;
         }
-    };
+    }
 }
 
-static uint8_t devide_transfer_sector(void)
+uint8_t devide_transfer_sector(void)
 {
     uint8_t drive;
 #if defined(__SDCC_z80) || defined(__SDCC_z180) || defined(__SDCC_gbz80) || defined(__SDCC_r2k) || defined(__SDCC_r3k)
@@ -112,7 +88,7 @@ static uint8_t devide_transfer_sector(void)
     return 1;
 }
 
-static int devide_flush_cache(void)
+int devide_flush_cache(void)
 {
     uint8_t drive;
 
@@ -148,7 +124,7 @@ static int devide_flush_cache(void)
 /****************************************************************************/
 COMMON_MEMORY
 
-static void devide_read_data(void) __naked
+void devide_read_data(void) __naked
 {
     __asm
             ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET) ; blkparam.is_user
@@ -184,116 +160,3 @@ gowrite:    otir                                    ; transfer first 256 bytes
     __endasm;
 }
 
-/****************************************************************************/
-/* Code below this point used only once, at startup, so we want it to live  */
-/* in the DISCARD segment. sdcc only allows us to specify one segment for   */
-/* each source file. This "solution" is a bit (well, very) hacky ...        */
-/****************************************************************************/
-DISCARDABLE
-
-static void devide_delay(void)
-{
-    timer_t timeout;
-
-    timeout = set_timer_ms(25);
-
-    while(!timer_expired(timeout))
-        platform_idle();
-}
-
-static void devide_init_drive(uint8_t drive)
-{
-    blkdev_t *blk;
-    uint8_t *buffer, select;
-
-    switch(drive){
-       case 0: select = 0xE0; break;
-       case 1: select = 0xF0; break;
-        default: return;
-    }
-
-    kprintf("IDE drive %d: ", drive);
-
-    /* Reset depends upon the presence of alt control, which is optional */
-#ifdef IDE_REG_CONTROL
-    /* reset the drive */
-    ide_reg_devhead = select;
-    ide_reg_control = 0x06; /* assert reset, no interrupts */
-    devide_delay();
-    ide_reg_control = 0x02; /* release reset, no interrupts */
-    devide_delay();
-    if(!devide_wait(IDE_STATUS_READY))
-        return;
-#endif
-
-#ifdef IDE_8BIT_ONLY
-    /* set 8-bit mode -- mostly only supported by CF cards */
-    ide_reg_devhead = select;
-    if(!devide_wait(IDE_STATUS_READY))
-        return;
-    ide_reg_features = 0x01;
-    ide_reg_command = IDE_CMD_SET_FEATURES;
-#endif
-
-    /* confirm drive has LBA support */
-    if(!devide_wait(IDE_STATUS_READY))
-        return;
-
-    /* send identify command */
-    ide_reg_devhead = select;
-    ide_reg_command = IDE_CMD_IDENTIFY;
-
-    /* allocate temporary sector buffer memory */
-    buffer = (uint8_t *)tmpbuf();
-
-    if(!devide_wait(IDE_STATUS_DATAREQUEST))
-       goto failout;
-
-    blk_op.is_user = false;
-    blk_op.addr = buffer;
-    blk_op.nblock = 1;
-    devide_read_data();
-
-    if(!(buffer[99] & 0x02)){
-        kputs("LBA unsupported.\n");
-        goto failout;
-    }
-
-    blk = blkdev_alloc();
-    if(!blk)
-       goto failout;
-
-    blk->transfer = devide_transfer_sector;
-    blk->flush = devide_flush_cache;
-    blk->driver_data = drive & DRIVE_NR_MASK;
-
-    if( !(((uint16_t*)buffer)[82] == 0x0000 && ((uint16_t*)buffer)[83] == 0x0000) ||
-         (((uint16_t*)buffer)[82] == 0xFFFF && ((uint16_t*)buffer)[83] == 0xFFFF) ){
-       /* command set notification is supported */
-       if(buffer[164] & 0x20){
-           /* write cache is supported */
-            blk->driver_data |= FLAG_WRITE_CACHE;
-       }
-    }
-
-    /* read out the drive's sector count */
-    blk->drive_lba_count = le32_to_cpu(*((uint32_t*)&buffer[120]));
-
-    /* done with our temporary memory */
-    brelse((bufptr)buffer);
-
-    /* scan partitions */
-    blkdev_scan(blk, SWAPSCAN);
-
-    return;
-failout:
-    brelse((bufptr)buffer);
-}
-
-void devide_init(void)
-{
-    uint8_t d;
-
-    for(d=0; d<DRIVE_COUNT; d++)
-        devide_init_drive(d);
-}
index 2129bca..16bda31 100644 (file)
@@ -68,4 +68,38 @@ void devide_init(void);
 #define IDE_CMD_IDENTIFY        0xEC
 #define IDE_CMD_SET_FEATURES    0xEF
 
+#ifdef _IDE_PRIVATE
+
+#define DRIVE_COUNT 2           /* at most 2 drives without adjusting DRIVE_NR_MASK */
+
+/* we use the bits in the driver_data field of blkdev_t as follows: */
+#define DRIVE_NR_MASK    0x01   /* low bit used to select the drive number -- extend if more required */
+#define FLAG_CACHE_DIRTY 0x40
+#define FLAG_WRITE_CACHE 0x80
+
+
+extern bool devide_wait(uint8_t bits);
+extern void devide_read_data(void);
+extern uint8_t devide_transfer_sector(void);
+extern int devide_flush_cache(void);
+
+#ifdef IDE_REG_ALTSTATUS
+__sfr __at IDE_REG_ALTSTATUS ide_reg_altstatus;
+#endif
+#ifdef IDE_REG_CONTROL
+__sfr __at IDE_REG_CONTROL   ide_reg_control;
+#endif
+__sfr __at IDE_REG_COMMAND   ide_reg_command;
+__sfr __at IDE_REG_DATA      ide_reg_data;
+__sfr __at IDE_REG_DEVHEAD   ide_reg_devhead;
+__sfr __at IDE_REG_ERROR     ide_reg_error;
+__sfr __at IDE_REG_FEATURES  ide_reg_features;
+__sfr __at IDE_REG_LBA_0     ide_reg_lba_0;
+__sfr __at IDE_REG_LBA_1     ide_reg_lba_1;
+__sfr __at IDE_REG_LBA_2     ide_reg_lba_2;
+__sfr __at IDE_REG_LBA_3     ide_reg_lba_3;
+__sfr __at IDE_REG_SEC_COUNT ide_reg_sec_count;
+__sfr __at IDE_REG_STATUS    ide_reg_status;
+#endif
+
 #endif
diff --git a/Kernel/dev/devide_discard.c b/Kernel/dev/devide_discard.c
new file mode 100644 (file)
index 0000000..735691a
--- /dev/null
@@ -0,0 +1,133 @@
+/*-----------------------------------------------------------------------*/
+/* IDE interface driver                                                  */
+/* 2014-11-02 Will Sowerbutts (unreleased UZI-mark4)                     */
+/* 2014-12-22 WRS ported to Fuzix                                        */
+/* 2014-12-25 WRS updated to also support P112 GIDE                      */
+/* 2015-01-04 WRS updated to new blkdev API                              */
+/* 2015-01-25 WRS updated to newer blkdev API                            */
+/*-----------------------------------------------------------------------*/
+
+#define _IDE_PRIVATE
+
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <timer.h>
+#include <devide.h>
+#include <blkdev.h>
+
+/****************************************************************************/
+/* Code below this point used only once, at startup, so we want it to live  */
+/* in the DISCARD segment. sdcc only allows us to specify one segment for   */
+/* each source file. This "solution" is a bit (well, very) hacky ...        */
+/****************************************************************************/
+
+static void devide_delay(void)
+{
+    timer_t timeout;
+
+    timeout = set_timer_ms(25);
+
+    while(!timer_expired(timeout))
+       platform_idle();
+}
+
+void devide_init_drive(uint8_t drive)
+{
+    blkdev_t *blk;
+    uint8_t *buffer, select;
+
+    switch(drive){
+       case 0: select = 0xE0; break;
+       case 1: select = 0xF0; break;
+        default: return;
+    }
+
+    kprintf("IDE drive %d: ", drive);
+
+    /* Reset depends upon the presence of alt control, which is optional */
+#ifdef IDE_REG_CONTROL
+    /* reset the drive */
+    ide_reg_devhead = select;
+    ide_reg_control = 0x06; /* assert reset, no interrupts */
+    devide_delay();
+    ide_reg_control = 0x02; /* release reset, no interrupts */
+    devide_delay();
+    if(!devide_wait(IDE_STATUS_READY))
+        return;
+#endif
+
+#ifdef IDE_8BIT_ONLY
+    /* set 8-bit mode -- mostly only supported by CF cards */
+    ide_reg_devhead = select;
+    if(!devide_wait(IDE_STATUS_READY))
+        return;
+    ide_reg_features = 0x01;
+    ide_reg_command = IDE_CMD_SET_FEATURES;
+#endif
+
+    /* confirm drive has LBA support */
+    if(!devide_wait(IDE_STATUS_READY))
+        return;
+
+    /* send identify command */
+    ide_reg_devhead = select;
+    ide_reg_command = IDE_CMD_IDENTIFY;
+
+    /* allocate temporary sector buffer memory */
+    buffer = (uint8_t *)tmpbuf();
+
+    if(!devide_wait(IDE_STATUS_DATAREQUEST))
+       goto failout;
+
+    blk_op.is_user = false;
+    blk_op.addr = buffer;
+    blk_op.nblock = 1;
+    devide_read_data();
+
+    if(!(buffer[99] & 0x02)){
+        kputs("LBA unsupported.\n");
+        goto failout;
+    }
+
+    blk = blkdev_alloc();
+    if(!blk)
+       goto failout;
+
+    kputs("BAL");
+    blk->transfer = devide_transfer_sector;
+    blk->flush = devide_flush_cache;
+    blk->driver_data = drive & DRIVE_NR_MASK;
+
+    if( !(((uint16_t*)buffer)[82] == 0x0000 && ((uint16_t*)buffer)[83] == 0x0000) ||
+         (((uint16_t*)buffer)[82] == 0xFFFF && ((uint16_t*)buffer)[83] == 0xFFFF) ){
+       /* command set notification is supported */
+       if(buffer[164] & 0x20){
+           /* write cache is supported */
+            blk->driver_data |= FLAG_WRITE_CACHE;
+       }
+    }
+
+    /* read out the drive's sector count */
+    blk->drive_lba_count = le32_to_cpu(*((uint32_t*)&buffer[120]));
+
+    /* done with our temporary memory */
+    brelse((bufptr)buffer);
+
+    /* scan partitions */
+    blkdev_scan(blk, SWAPSCAN);
+
+    return;
+failout:
+    brelse((bufptr)buffer);
+    return;
+}
+
+void devide_init(void)
+{
+    uint8_t d;
+
+    for(d=0; d<DRIVE_COUNT; d++)
+        devide_init_drive(d);
+}
index d4cfa7a..8ef7ed4 100644 (file)
@@ -1,13 +1,14 @@
 CSRCS = devtty.c bankzx128.c devices.c main.c devmdv.c
 DSRCS = ../dev/devide.c ../dev/mbr.c ../dev/blkdev.c
-
+DDSRCS = ../dev/devide_discard.c
 ASRCS = crt0.s zx128.s zxvideo.s microdrive.s
 ASRCS += tricks.s commonmem.s
 
 COBJS = $(CSRCS:.c=.rel)
 AOBJS = $(ASRCS:.s=.rel)
 DOBJS = $(patsubst ../dev/%.c,%.rel, $(DSRCS))
-OBJS  = $(COBJS) $(AOBJS) $(DOBJS)
+DDOBJS = $(patsubst ../dev/%.c,%.rel, $(DDSRCS))
+OBJS  = $(COBJS) $(AOBJS) $(DOBJS) $(DDOBJS)
 
 CROSS_CCOPTS += -I../dev/
 
@@ -23,6 +24,9 @@ $(COBJS): %.rel: %.c
 $(DOBJS): %.rel: ../dev/%.c
        $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEG3) -c $<
 
+$(DDOBJS): %.rel: ../dev/%.c
+       $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $<
+
 $(AOBJS): %.rel: %.s
        $(CROSS_AS) $(ASOPTS) $<
 
@@ -30,4 +34,4 @@ clean:
        rm -f $(OBJS) $(JUNK)  core *~ 
 
 image:
-       ../tools/bintomdv ../fuzix.tmp fuzix.cart fuzixboot.mdv
+       ( cd ..; tools/bin2sna fuzix.sna )
index 2ad58f4..0d3d2b6 100644 (file)
@@ -1,12 +1,11 @@
 -mwxuy
 -r
 -i fuzix.ihx
--b _COMMONMEM=0x4000
+-b _COMMONDATA=0x4000
 -b _CODE=0xC000
 -b _CODE2=0xC000
 -b _CODE3=0xDB00
 -b _DISCARD=0x8000
--l z80
 platform-zx128/crt0.rel
 platform-zx128/commonmem.rel
 platform-zx128/zx128.rel
@@ -41,6 +40,7 @@ swap.rel
 devsys.rel
 platform-zx128/devtty.rel
 platform-zx128/devide.rel
+platform-zx128/devide_discard.rel
 platform-zx128/mbr.rel
 platform-zx128/blkdev.rel
 -e