First cut at this.
We make the IDE base a variable
Allow for a platform private header for IDE (needed for stuff like ide_base)
Issue select/deselect commands passing the drive number
This in theory also gives us all that is needed for multiple IDE controllers,
while not paying a cost for them on simple platforms (they can define the
selectors into nothingness)
uint8_t *p;
#endif
+
drive = blk_op.blkdev->driver_data & DRIVE_NR_MASK;
+ ide_select(drive);
+
#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;
devide_writeb(ide_reg_lba_0, blk_op.lba);
#endif
- if(!devide_wait(IDE_STATUS_READY))
- return 0;
+ if (!devide_wait(IDE_STATUS_READY))
+ goto fail;
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;
+ goto fail;
- if(blk_op.is_read)
+ if (blk_op.is_read)
devide_read_data();
- else{
+ else {
devide_write_data();
if(!devide_wait(IDE_STATUS_READY))
- return 0;
+ goto fail;
blk_op.blkdev->driver_data |= FLAG_CACHE_DIRTY;
}
+ ide_deselect();
+
return 1;
+fail:
+ ide_deselect();
+ return 0;
}
int devide_flush_cache(void)
drive = blk_op.blkdev->driver_data & DRIVE_NR_MASK;
+ ide_select(drive);
+
/* 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)){
- devide_writeb(ide_reg_lba_3, ((drive == 0) ? 0xE0 : 0xF0)); // select drive
+ devide_writeb(ide_reg_lba_3, (((drive & 1) == 0) ? 0xE0 : 0xF0)); // select drive
- if(!devide_wait(IDE_STATUS_READY)){
- udata.u_error = EIO;
- return -1;
- }
+ if (!devide_wait(IDE_STATUS_READY))
+ goto fail;
devide_writeb(ide_reg_command, IDE_CMD_FLUSH_CACHE);
- if(!devide_wait(IDE_STATUS_READY)){
- udata.u_error = EIO;
- return -1;
- }
+ if (!devide_wait(IDE_STATUS_READY))
+ goto fail;
/* drive cache is now clean */
blk_op.blkdev->driver_data &= ~FLAG_CACHE_DIRTY;
}
-
+ ide_deselect();
return 0;
+
+fail:
+ udata.u_error = EIO;
+ ide_deselect();
+ return -1;
}
/****************************************************************************/
#define __DEVIDE_DOT_H__
#include "config.h"
+#include "platform_ide.h"
/* IDE Drive Configuration (in config.h)
#ifdef _IDE_PRIVATE
-#define DRIVE_COUNT 2 /* at most 2 drives without adjusting DRIVE_NR_MASK */
+#ifndef DRIVE_COUNT
+#define DRIVE_COUNT 2 /* at most 16 drives without adjusting DRIVE_NR_MASK */
+#endif
/* 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 DRIVE_NR_MASK 0x0F /* low bit used to select master/slave */
#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);
+/* Platform provided, or may be defaults */
extern void devide_write_data(void);
-extern void devde_read_data(void);
+extern void devide_read_data(void);
+
+/* Platform provided */
+extern void ide_select(uint8_t drive);
+extern void ide_deselect(void);
#ifndef IDE_REG_INDIRECT
#ifdef IDE_IS_MMIO
blkdev_t *blk;
uint8_t *buffer, select;
- switch(drive){
+ switch(drive & 1){
case 0: select = 0xE0; break;
case 1: select = 0xF0; break;
default: return;
kprintf("IDE drive %d: ", drive);
+ ide_select(drive);
+
#ifdef IDE_8BIT_ONLY
/* set 8-bit mode -- mostly only supported by CF cards */
devide_writeb(ide_reg_devhead, select);
- if(!devide_wait(IDE_STATUS_READY))
- return;
+ if (!devide_wait(IDE_STATUS_READY))
+ goto out;
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 */
- if(!devide_wait(IDE_STATUS_READY))
- return;
+ if (!devide_wait(IDE_STATUS_READY))
+ goto out;
/* send identify command */
devide_writeb(ide_reg_devhead, select);
/* allocate temporary sector buffer memory */
buffer = (uint8_t *)tmpbuf();
- if(!devide_wait(IDE_STATUS_DATAREQUEST))
+ if (!devide_wait(IDE_STATUS_DATAREQUEST))
goto failout;
blk_op.is_user = false;
blk_op.nblock = 1;
devide_read_data();
- if(!(buffer[99] & 0x02)){
+ if(!(buffer[99] & 0x02)) {
kputs("LBA unsupported.\n");
goto failout;
}
/* done with our temporary memory */
brelse((bufptr)buffer);
+ /* Deselect the IDE, as we will re-select it in the partition scan and
+ it may not recursively stack de-selections */
+ ide_deselect();
+
/* scan partitions */
blkdev_scan(blk, SWAPSCAN);
return;
failout:
brelse((bufptr)buffer);
+out:
+ ide_deselect();
return;
}
devide_reset();
#endif
- for(d=0; d<DRIVE_COUNT; d++)
+ for(d=0; d < DRIVE_COUNT; d++)
devide_init_drive(d);
}
#define MAX_BLKDEV 3 /* 2 IDE drives + 1 SPI */
#define SD_DRIVE_COUNT 1 /* Could be higher with multiple CS used */
#define DEVICE_IDE /* enable if IDE interface present */
-#define IDE_REG_CS1_BASE 0xFF50
-#define IDE_IS_MMIO 1 /* MMIO IDE */
/* Video terminal, not a serial tty */
#define CONFIG_VT
extern uint8_t hdb_timeout;
extern uint8_t hdb_id;
+extern uint16_t cartaddr[];
+extern uint8_t cartslots;
+
extern uint8_t spi_setup(void);
#endif /* __DEVICE_DOT_H__ */
#include <devide.h>
#include <devsd.h>
#include <device.h>
+#include <carts.h>
struct devsw dev_tab[] = /* The device driver switch table */
{
return true;
}
+uint16_t ide_base = 0xFF50;
+uint8_t ide_slot = 3; /* Disk in slot 3 by convention */
+
+static uint8_t old_slot;
+
+void ide_select(void)
+{
+ if (cartslots > 1)
+ old_slot = mpi_set_slot(ide_slot);
+}
+
+void ide_deselect(void)
+{
+ if (cartslots > 1)
+ mpi_set_slot(old_slot);
+}
+
+/* This can move to discard... */
+
void device_init(void)
{
+ int i;
+
if (spi_setup())
devsd_init();
+ i = cart_find(CART_IDE);
+ if (i >= 0) {
+ ide_base = cartaddr[i] ? cartaddr[i]: ide_base;
+ ide_slot = i;
+ }
devide_init();
}