devide: Support for IDE controllers which do not expose the IDE
authorWill Sowerbutts <will@sowerbutts.com>
Fri, 24 Apr 2015 19:45:25 +0000 (20:45 +0100)
committerWill Sowerbutts <will@sowerbutts.com>
Fri, 24 Apr 2015 19:50:38 +0000 (20:50 +0100)
registers directly on the CPU bus

Kernel/dev/devide.c
Kernel/dev/devide.h
Kernel/dev/devide_discard.c

index c07b148..8bcbbd2 100644 (file)
@@ -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
index 16bda31..7cbea80 100644 (file)
@@ -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
index 8bf65a1..8f0852b 100644 (file)
@@ -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();