#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; }
/* 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;
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)
return 1;
}
-static int devide_flush_cache(void)
+int devide_flush_cache(void)
{
uint8_t drive;
/****************************************************************************/
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
__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);
-}
#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
--- /dev/null
+/*-----------------------------------------------------------------------*/
+/* 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);
+}
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/
$(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) $<
rm -f $(OBJS) $(JUNK) core *~
image:
- ../tools/bintomdv ../fuzix.tmp fuzix.cart fuzixboot.mdv
+ ( cd ..; tools/bin2sna fuzix.sna )
-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
devsys.rel
platform-zx128/devtty.rel
platform-zx128/devide.rel
+platform-zx128/devide_discard.rel
platform-zx128/mbr.rel
platform-zx128/blkdev.rel
-e