dragon-nx-32: wire up the probing and mpi logic
authorAlan Cox <alan@linux.intel.com>
Fri, 9 Oct 2015 13:23:11 +0000 (14:23 +0100)
committerAlan Cox <alan@linux.intel.com>
Fri, 9 Oct 2015 13:23:11 +0000 (14:23 +0100)
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)

Kernel/dev/devide.c
Kernel/dev/devide.h
Kernel/dev/devide_discard.c
Kernel/platform-dragon-nx32/config.h
Kernel/platform-dragon-nx32/device.h
Kernel/platform-dragon-nx32/devices.c

index 54e5f9c..6383357 100644 (file)
@@ -49,8 +49,11 @@ uint8_t devide_transfer_sector(void)
     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;
@@ -65,25 +68,30 @@ uint8_t devide_transfer_sector(void)
     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)
@@ -92,28 +100,31 @@ 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;
 }
 
 /****************************************************************************/
index c4c2f43..101b5cb 100644 (file)
@@ -2,6 +2,7 @@
 #define __DEVIDE_DOT_H__
 
 #include "config.h"
+#include "platform_ide.h"
 
 /* IDE Drive Configuration (in config.h)
  
@@ -89,20 +90,26 @@ void devide_writeb(uint8_t regaddr, uint8_t value);
 
 #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
index 8f0852b..271870a 100644 (file)
@@ -54,7 +54,7 @@ void devide_init_drive(uint8_t drive)
     blkdev_t *blk;
     uint8_t *buffer, select;
 
-    switch(drive){
+    switch(drive & 1){
        case 0: select = 0xE0; break;
        case 1: select = 0xF0; break;
         default: return;
@@ -62,19 +62,21 @@ void devide_init_drive(uint8_t drive)
 
     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);
@@ -83,7 +85,7 @@ void devide_init_drive(uint8_t drive)
     /* 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;
@@ -91,7 +93,7 @@ void devide_init_drive(uint8_t drive)
     blk_op.nblock = 1;
     devide_read_data();
 
-    if(!(buffer[99] & 0x02)){
+    if(!(buffer[99] & 0x02)) {
         kputs("LBA unsupported.\n");
         goto failout;
     }
@@ -119,12 +121,18 @@ void devide_init_drive(uint8_t drive)
     /* 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;
 }
 
@@ -136,6 +144,6 @@ void devide_init(void)
     devide_reset();
 #endif
 
-    for(d=0; d<DRIVE_COUNT; d++)
+    for(d=0; d < DRIVE_COUNT; d++)
         devide_init_drive(d);
 }
index 424434d..4331c81 100644 (file)
@@ -28,8 +28,6 @@
 #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
index 9c6231d..b75404e 100644 (file)
@@ -11,6 +11,9 @@ extern uint16_t hdb_port;
 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__ */
index b8671d3..3907e35 100644 (file)
@@ -13,6 +13,7 @@
 #include <devide.h>
 #include <devsd.h>
 #include <device.h>
+#include <carts.h>
 
 struct devsw dev_tab[] =  /* The device driver switch table */
 {
@@ -46,9 +47,35 @@ bool validdev(uint16_t dev)
         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();
 }