From 2ea3d48eaae7ad8fdffcb9160f512ce39f7fbbd1 Mon Sep 17 00:00:00 2001 From: Will Sowerbutts Date: Fri, 24 Apr 2015 20:45:25 +0100 Subject: [PATCH] devide: Support for IDE controllers which do not expose the IDE registers directly on the CPU bus --- Kernel/dev/devide.c | 29 ++++++++++++------------ Kernel/dev/devide.h | 44 +++++++++++++++++++++++++++---------- Kernel/dev/devide_discard.c | 16 +++++++------- 3 files changed, 55 insertions(+), 34 deletions(-) diff --git a/Kernel/dev/devide.c b/Kernel/dev/devide.c index c07b148f..8bcbbd26 100644 --- a/Kernel/dev/devide.c +++ b/Kernel/dev/devide.c @@ -27,7 +27,7 @@ bool devide_wait(uint8_t bits) timeout = set_timer_ms(500); while(true){ - status = ide_reg_status; + status = devide_readb(ide_reg_status); if((status & (IDE_STATUS_BUSY | IDE_STATUS_ERROR | bits)) == bits) return true; @@ -56,22 +56,22 @@ uint8_t devide_transfer_sector(void) #if defined(__SDCC_z80) || defined(__SDCC_z180) || defined(__SDCC_gbz80) || defined(__SDCC_r2k) || defined(__SDCC_r3k) /* sdcc sadly unable to figure this out for itself yet */ p = ((uint8_t *)&blk_op.lba)+3; - ide_reg_lba_3 = (*(p--) & 0x0F) | ((drive == 0) ? 0xE0 : 0xF0); // select drive, start loading LBA - ide_reg_lba_2 = *(p--); - ide_reg_lba_1 = *(p--); - ide_reg_lba_0 = *p; + devide_writeb(ide_reg_lba_3, (*(p--) & 0x0F) | ((drive == 0) ? 0xE0 : 0xF0)); // select drive, start loading LBA + devide_writeb(ide_reg_lba_2, *(p--)); + devide_writeb(ide_reg_lba_1, *(p--)); + devide_writeb(ide_reg_lba_0, *p); #else - ide_reg_lba_3 = ((blk_op.lba >> 24) & 0xF) | ((drive == 0) ? 0xE0 : 0xF0); // select drive, start loading LBA - ide_reg_lba_2 = (blk_op.lba >> 16); - ide_reg_lba_1 = (blk_op.lba >> 8); - ide_reg_lba_0 = blk_op.lba; + devide_writeb(ide_reg_lba_3, ((blk_op.lba >> 24) & 0xF) | ((drive == 0) ? 0xE0 : 0xF0)); // select drive, start loading LBA + devide_writeb(ide_reg_lba_2, (blk_op.lba >> 16)); + devide_writeb(ide_reg_lba_1, (blk_op.lba >> 8)); + devide_writeb(ide_reg_lba_0, blk_op.lba); #endif if(!devide_wait(IDE_STATUS_READY)) return 0; - ide_reg_sec_count = 1; - ide_reg_command = blk_op.is_read ? IDE_CMD_READ_SECTOR : IDE_CMD_WRITE_SECTOR; + devide_writeb(ide_reg_sec_count, 1); + devide_writeb(ide_reg_command, blk_op.is_read ? IDE_CMD_READ_SECTOR : IDE_CMD_WRITE_SECTOR); if(!devide_wait(IDE_STATUS_DATAREQUEST)) return 0; @@ -97,14 +97,14 @@ int devide_flush_cache(void) /* check drive has a cache and was written to since the last flush */ if(blk_op.blkdev->driver_data & (FLAG_WRITE_CACHE | FLAG_CACHE_DIRTY) == (FLAG_WRITE_CACHE | FLAG_CACHE_DIRTY)){ - ide_reg_lba_3 = ((drive == 0) ? 0xE0 : 0xF0); // select drive + devide_writeb(ide_reg_lba_3, ((drive == 0) ? 0xE0 : 0xF0)); // select drive if(!devide_wait(IDE_STATUS_READY)){ udata.u_error = EIO; return -1; } - ide_reg_command = IDE_CMD_FLUSH_CACHE; + devide_writeb(ide_reg_command, IDE_CMD_FLUSH_CACHE); if(!devide_wait(IDE_STATUS_READY)){ udata.u_error = EIO; @@ -122,6 +122,7 @@ int devide_flush_cache(void) /* 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. */ /****************************************************************************/ +#ifndef IDE_REG_INDIRECT COMMON_MEMORY void devide_read_data(void) __naked @@ -159,4 +160,4 @@ gowrite: otir ; transfer first 256 bytes jp map_kernel ; else map kernel then return __endasm; } - +#endif diff --git a/Kernel/dev/devide.h b/Kernel/dev/devide.h index 16bda313..7cbea80e 100644 --- a/Kernel/dev/devide.h +++ b/Kernel/dev/devide.h @@ -8,20 +8,36 @@ Define DEVICE_IDE if IDE hardware is present on your platform. Define IDE_8BIT_ONLY if the system implements only half of the 16-bit data - bus (eg N8VEM Mark IV). - - If the IDE registers appear in one contiguous block then define IDE_REG_BASE - and either IDE_REG_CS0_FIRST or IDE_REG_CS1_FIRST. - - If the IDE registers appear in two non-contiguous blocks then define both - IDE_REG_CS0_BASE and IDE_REG_CS1_BASE. - - If neither of these is suitable just define the address of each register - ie IDE_REG_DATA, IDE_REG_ERROR, etc. + bus (eg n8vem-mark4). + + Define IDE_REG_INDIRECT if the IDE registers are not directly addressable on + your platform. If you do not define IDE_REG_INDIRECT then IDE registers + should be directly addressable by CPU I/O operations. + + If IDE_REG_INDIRECT is defined you will need to provide devide_readb() and + devide_writeb() to access the IDE registers. You will need to define + suitable values for each register (ide_reg_data, ide_reg_error etc) to be + passed to these functions. You will also need to provide devide_read_data() + and devide_write_data() to transfer sectors. See zeta-v2's PPIDE device code + for an example of how to do this. + + If IDE_REG_INDIRECT is not defined: If the IDE registers appear in one + contiguous block then define IDE_REG_BASE and either IDE_REG_CS0_FIRST or + IDE_REG_CS1_FIRST. If the IDE registers appear in two non-contiguous blocks + then define both IDE_REG_CS0_BASE and IDE_REG_CS1_BASE. If neither of these + is suitable just define the address of each register ie IDE_REG_DATA, + IDE_REG_ERROR, etc. */ void devide_init(void); +#ifdef IDE_REG_INDIRECT +uint8_t devide_readb(uint8_t regaddr); +void devide_writeb(uint8_t regaddr, uint8_t value); +#else /* not IDE_REG_INDIRECT */ +#define devide_readb(r) (r) +#define devide_writeb(r,v) do { r = v; } while(0) + #ifdef IDE_REG_BASE #ifdef IDE_REG_CS0_FIRST #define IDE_REG_CS0_BASE (IDE_REG_BASE+0x00) @@ -31,12 +47,13 @@ void devide_init(void); #define IDE_REG_CS0_BASE (IDE_REG_BASE+0x08) #define IDE_REG_CS1_BASE (IDE_REG_BASE+0x00) #endif -#endif +#endif /* IDE_REG_BASE */ #ifdef IDE_REG_CS0_BASE #define IDE_REG_ALTSTATUS (IDE_REG_CS0_BASE + 0x06) #define IDE_REG_CONTROL (IDE_REG_CS0_BASE + 0x06) #endif + #ifdef IDE_REG_CS1_BASE #define IDE_REG_DATA (IDE_REG_CS1_BASE + 0x00) #define IDE_REG_ERROR (IDE_REG_CS1_BASE + 0x01) @@ -51,6 +68,8 @@ void devide_init(void); #define IDE_REG_COMMAND (IDE_REG_CS1_BASE + 0x07) #endif +#endif /* IDE_REG_INDIRECT */ + /* IDE status register bits */ #define IDE_STATUS_BUSY 0x80 #define IDE_STATUS_READY 0x40 @@ -77,12 +96,12 @@ void devide_init(void); #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); +#ifndef IDE_REG_INDIRECT #ifdef IDE_REG_ALTSTATUS __sfr __at IDE_REG_ALTSTATUS ide_reg_altstatus; #endif @@ -101,5 +120,6 @@ __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 /* IDE_REG_INDIRECT */ #endif diff --git a/Kernel/dev/devide_discard.c b/Kernel/dev/devide_discard.c index 8bf65a14..8f0852b8 100644 --- a/Kernel/dev/devide_discard.c +++ b/Kernel/dev/devide_discard.c @@ -40,11 +40,11 @@ void devide_reset(void) kputs("IDE reset\n"); /* reset both drives */ - ide_reg_devhead = 0xE0; /* select master */ - ide_reg_control = 0x06; /* assert reset, no interrupts */ + devide_writeb(ide_reg_devhead, 0xE0); /* select master */ + devide_writeb(ide_reg_control, 0x06); /* assert reset, no interrupts */ devide_delay(); - ide_reg_control = 0x02; /* release reset, no interrupts */ + devide_writeb(ide_reg_control, 0x02); /* release reset, no interrupts */ devide_delay(); } #endif @@ -64,12 +64,12 @@ void devide_init_drive(uint8_t drive) #ifdef IDE_8BIT_ONLY /* set 8-bit mode -- mostly only supported by CF cards */ - ide_reg_devhead = select; + devide_writeb(ide_reg_devhead, select); if(!devide_wait(IDE_STATUS_READY)) return; - ide_reg_features = 0x01; /* Enable 8-bit PIO transfer mode (CFA feature set only) */ - ide_reg_command = IDE_CMD_SET_FEATURES; + devide_writeb(ide_reg_features, 0x01); /* Enable 8-bit PIO transfer mode (CFA feature set only) */ + devide_writeb(ide_reg_command, IDE_CMD_SET_FEATURES); #endif /* confirm drive has LBA support */ @@ -77,8 +77,8 @@ void devide_init_drive(uint8_t drive) return; /* send identify command */ - ide_reg_devhead = select; - ide_reg_command = IDE_CMD_IDENTIFY; + devide_writeb(ide_reg_devhead, select); + devide_writeb(ide_reg_command, IDE_CMD_IDENTIFY); /* allocate temporary sector buffer memory */ buffer = (uint8_t *)tmpbuf(); -- 2.34.1