atarist: Start filling in the drivers
authorAlan Cox <alan@linux.intel.com>
Sat, 23 Mar 2019 20:55:18 +0000 (20:55 +0000)
committerAlan Cox <alan@linux.intel.com>
Sat, 23 Mar 2019 20:55:18 +0000 (20:55 +0000)
Floppy and ACSI to begin with, along with the IDE adapters often added.

12 files changed:
Kernel/platform-atarist/Makefile
Kernel/platform-atarist/acsi.h [new file with mode: 0644]
Kernel/platform-atarist/config.h
Kernel/platform-atarist/devacsi.c [new file with mode: 0644]
Kernel/platform-atarist/devfd.c
Kernel/platform-atarist/devices.c
Kernel/platform-atarist/dma.c [new file with mode: 0644]
Kernel/platform-atarist/dma.h
Kernel/platform-atarist/loader.S [new file with mode: 0644]
Kernel/platform-atarist/machine.h [new file with mode: 0644]
Kernel/platform-atarist/main.c
Kernel/platform-atarist/platform_ide.h [new file with mode: 0644]

index 9e9e723..342075f 100644 (file)
@@ -1,5 +1,5 @@
 
-CSRCS = devlpr.c devtty.c devfd.c
+CSRCS = devlpr.c devtty.c dma.c devfd.c devacsi.c
 CSRCS += devices.c main.c libc.c
 
 ASRCS = p68000.S crt0.S
@@ -8,7 +8,8 @@ ASRCS += tricks.S
 LSRCS = ../lib/68000exception.c
 LOBJS = $(patsubst ../lib/%.c,%.o, $(LSRCS))
 
-DSRCS = ../dev/mbr.c ../dev/blkdev.c
+DSRCS = ../dev/mbr.c ../dev/blkdev.c ../dev/devide.c ../dev/devide_discard.c
+DSRCS += ../dev/ahdi.c
 DOBJS = $(patsubst ../dev/%.c,%.o, $(DSRCS))
 
 COBJS = $(CSRCS:.c=$(BINEXT))
@@ -49,7 +50,7 @@ image:        loader fuzix.ld
        ../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o \
        ../syscall_fs3.o ../syscall_exec32.o \
        ../usermem_std-68000.o devlpr.o devtty.o libc.o ../vt.o ../malloc.o \
-       blkdev.o mbr.o \
+       blkdev.o mbr.o devide.o devide_discard.o devacsi.o dma.o \
        ../font8x8.o >../fuzix.map
        m68k-uclinux-objcopy fuzix.elf -O binary ../fuzix.bin
        # And now make a bootable floppy
diff --git a/Kernel/platform-atarist/acsi.h b/Kernel/platform-atarist/acsi.h
new file mode 100644 (file)
index 0000000..f4b081e
--- /dev/null
@@ -0,0 +1 @@
+extern void acsi_init(void);
index 463b037..9e99600 100644 (file)
@@ -42,6 +42,8 @@
 #define NBUFS    10       /* Number of block buffers */
 #define NMOUNTS         4        /* Number of mounts at a time */
 
+#define CONFIG_IDE
+
 #define MAX_BLKDEV     4
 
 /* TODO tty scan rows/cols etc */
diff --git a/Kernel/platform-atarist/devacsi.c b/Kernel/platform-atarist/devacsi.c
new file mode 100644 (file)
index 0000000..4cbc758
--- /dev/null
@@ -0,0 +1,241 @@
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <timer.h>
+#include <devscsi.h>
+#include <blkdev.h>
+#include <dma.h>
+#include <acsi.h>
+
+/*
+ *     ACSI Hard disk interface. Based upon EmuTOS
+ *
+ *     ACSI is a SASI/SCSI like interface. The drives only speak SASI style
+ *     6 byte commands but we are at least blessed with a DMA interface for
+ *     this even if it's a bit of a pain to drive except for block I/O.
+ *
+ *     There is a hack (not implemented yet) where full SCSI commands can
+ *     be sent to some drive convertors by proceeding the longer commands
+ *     with 0x1F.
+ */
+
+
+union acsidma {
+       volatile uint32_t datacontrol;
+       struct {
+               volatile uint16_t data;
+               volatile uint16_t control;
+       } s;
+};
+
+#define ACSIDMA ((union acsidma *) 0xFF8604)
+
+static timer_t acsi_next;
+
+#define ACSI_CMDWAIT   TICKSPERSEC/100
+#define ACSI_CMDBYTE   TICKSPERSEC/10
+#define ACSI_OP                TICKSPERSEC
+
+
+void acsi_select(void)
+{
+       /* We are not allowed to issue the next command too soon */
+       while (!timer_expired(acsi_next))
+               platform_idle();
+
+       /* Claim the DMA */
+       dma_lock();
+}
+
+void acsi_clear(void)
+{
+       /* Hand back the DMAC */
+       ACSIDMA->s.control = DMA_FDC;
+       dma_unlock();
+
+       /* Remember when we can next issue a command */
+       acsi_next = set_timer_duration(ACSI_CMDWAIT);
+}
+
+/* Send byte and *next* control */
+static void dma_send_byte(uint8_t c, uint16_t control)
+{
+       ACSIDMA->datacontrol = ((uint32_t) c) << 16 | control;
+}
+
+static void delay(void)
+{
+       /* Wait 15us : FIXME */
+}
+
+/* Flush FIFO and set control */
+static void hdc_start_dma(uint16_t control)
+{
+       control |= DMA_SCREG;
+       ACSIDMA->s.control = control ^ DMA_WRBIT;
+       delay();
+       ACSIDMA->s.control = control;
+       delay();
+}
+
+/*
+ *     The SCSI midlayer wishes to send a command out
+ */
+uint8_t acsi_execute(uint8_t * cmd, uint8_t cmdlen, uint16_t len)
+{
+       uint8_t repeat = 0;
+       uint8_t st;
+       uint8_t control;
+       int i;
+
+       /* FIXME: add ICD hacks */
+
+       if (len && !blk_op.is_read)
+               /* Flush cache */ ;
+
+       /* No banking complexities for us. Some day we may have to address non DMA
+          memory on big machines however FIXME */
+       if (len)
+               set_dma_addr(blk_op.addr);
+       control = DMA_FDC | DMA_HDC;
+       if (!blk_op.is_read)
+               control |= DMA_WRBIT;
+       hdc_start_dma(control);
+       ACSIDMA->s.data = (len + 511) >> 9;
+
+       /* Repeat if neeed to drive through fifo.. ick */
+       if (len & 511) {
+               /* FIXME: add correct logic here */
+               repeat = 1;
+       }
+
+       do {
+               uint8_t *p = cmd;
+
+               /* We are not allowed to issue the next command too soon */
+               while (!timer_expired(acsi_next))
+                       platform_idle();
+
+               /* Write the command */
+               ACSIDMA->s.control = control;   /* SCSI control */
+               control |= DMA_A0;      /* Remaining bytes need this */
+               for (i = 0; i < cmdlen - 1; i++) {
+                       dma_send_byte(*p++, control);
+                       /* Allow 100ms */
+                       if (dma_wait(ACSI_CMDBYTE))
+                               return -1;
+               }
+               /* Command final byte */
+               dma_send_byte(*p, control & 0xFF00);
+
+               /* Now wait for command to run - can take a second worst case */
+               st = dma_wait(ACSI_OP);
+               /* Remember when we can issue the next command */
+               acsi_next = set_timer_duration(ACSI_CMDWAIT);
+               if (st)
+                       return -1;
+               /* Command issued */
+               ACSIDMA->s.control = control & ~DMA_WRBIT;
+               st = ACSIDMA->s.data & 0xff;
+               if (st)
+                       break;
+               control &= ~DMA_A0;
+       } while (repeat--);
+       /* And done */
+       if (len && blk_op.is_read)
+               /* Flush cache */ ;
+       return 0;
+}
+
+uint8_t acsi_transfer(void)
+{
+       uint8_t cmd[11];
+       unsigned short cmdlen;
+       unsigned short count;
+       unsigned short dev;
+       uint8_t blocks = blk_op.nblock;
+
+       if (blk_op.nblock > 255)
+               blocks = 255;
+
+       /* FIXME: lun handling */
+       dev = blk_op.blkdev->driver_data & DRIVE_NR_MASK;
+       /* When we can we issue ACSI commands. When we are out of range we try
+          SCSI. All ACSI devices are small enough only ACSI will hit them */
+       if (blk_op.lba < 0x200000) {
+               cmd[0] = blk_op.is_read ? 0x08 : 0x0A;
+               cmd[1] = (blk_op.lba >> 16) & 0x1f;
+               cmd[2] = blk_op.lba >> 8;
+               cmd[3] = blk_op.lba;
+               cmd[4] = blocks;
+               cmd[5] = 0x00;
+               cmdlen = 6;
+       } else {
+               /* Framed SCSI READ_10/WRITE_10 */
+               cmd[0] = 0x1F;  /* SCSI follows, lun bits also go here */
+               cmd[1] = blk_op.is_read ? 0x28 : 0x2A;
+               cmd[2] = 0x00;  /* LUN */
+               cmd[3] = blk_op.lba >> 24;
+               cmd[4] = blk_op.lba >> 16;
+               cmd[5] = blk_op.lba >> 8;
+               cmd[6] = blk_op.lba;
+               cmd[7] = 0x00;
+               cmd[8] = 0x00;  /* Blocks upper 8. Need to fix blkdev.c before */
+               cmd[9] = blocks;        /* we can do > 255 blocks per I/O */
+               cmd[10] = 0x00;
+               cmdlen = 11;
+       }
+
+       acsi_select();
+       /* Should we drop back to single block commands on an error and try to
+          do them all one by one ? */
+       for (count = 0; count < 5; count++) {
+               if (acsi_execute(cmd, cmdlen, blocks << 9) == 0) {
+                       acsi_clear();
+                       return blocks;
+               }
+       }
+       acsi_clear();
+       kprintf("acsi: device %d failed command %x for block %lx\n", dev, cmd[0], blk_op.lba);
+       return 0;
+}
+
+static unsigned int acsi_probe(uint8_t dev, uint8_t lun)
+{
+       static uint8_t cdb[6];  /* all zeros is TUR */
+       unsigned int st;
+       blkdev_t *blk;
+
+       acsi_select();
+       st = acsi_execute(cdb, 6, 0);
+       acsi_clear();
+
+       if (st)
+               return st;
+
+       /* TODO: do we need to check type and sector size etc on ACSI - prob not */
+
+       /* Add it */
+       blk = blkdev_alloc();
+       blk->transfer = acsi_transfer;
+       //blk->flush = acsi_flush;
+       blk->driver_data = dev; /* FIXME lun */
+       //blk->drive_lba_count = acsi_capcity(dev, lun);
+       blkdev_scan(blk, SWAPSCAN);
+       return st;
+}
+
+void acsi_init(void)
+{
+       unsigned int dev, lun;
+
+       acsi_next = set_timer_duration(0);
+       for (dev = 0; dev < 8; dev++) {
+               for (lun = 0; lun < 8; lun++) {
+                       if (acsi_probe(dev, lun) == 0) {
+                       } else if (lun == 0)
+                               break;
+               }
+       }
+}
index c6a59f3..72c150a 100644 (file)
@@ -18,7 +18,6 @@ static uint8_t dsided[MAX_FD] = { 1, 1 };     /* For now FIXME */
 static uint8_t step[MAX_FD] = { 3, 3 };        /* 3ms happens to be the value 3 */
 
 static uint8_t deselected = 1;
-static uint8_t locked;
 
 #define FDC_CS (DMA_FDC)
 #define FDC_TR  (DMA_FDC | DMA_A0)
@@ -64,29 +63,6 @@ static void flush_cache_range(void *p, size_t len)
        /* TODO */
 }
 
-/*
- *     Report how the DMA did
- */
-static uint16_t get_dma_status(void)
-{
-       DMA->control = 0x90;
-       return DMA->control;
-}
-
-/*
- *     Set the 24bit DMA address for a transfer. The transfer is not
- *     cache coherent and must be word aigned
- */
-static void set_dma_addr(uint8_t * ptr)
-{
-       uint32_t p = (uint32_t) ptr;
-       if (p & 1)
-               panic("odd dma");
-       DMA->addr_low = p;
-       DMA->addr_med = p >> 8;
-       DMA->addr_high = p >> 16;
-}
-
 /*
  *     Read an fd register
  */
@@ -138,16 +114,10 @@ static void fd_start_dma_write(uint16_t count)
  *     Wait for the floppy controller to respond and show up on the MFP
  *     GPIO.
  */
+
 static int fd_wait(void)
 {
-       timer_t x = set_timer_duration(3 * TICKSPERSEC);
-       while (!timer_expired(x)) {
-               uint8_t status = *(volatile uint8_t *)0xFFFA01;
-               if (!(status & 0x20))
-                       return 0;
-               platform_idle();
-       }
-       return -1;
+       return dma_wait(3 * TICKSPERSEC);
 }
 
 /*
@@ -158,7 +128,7 @@ void fd_event(void)
        irqflags_t irq;
        uint16_t status;
 
-       if (deselected || locked)
+       if (deselected || dma_is_locked())
                return;
        status = fd_get_reg(FDC_CS);
        if (status & FDC_MOTORON)
@@ -254,12 +224,12 @@ static int fd_xfer_sector(uint8_t minor, uint8_t is_read)
                track >>= 1;
        }
 
-       locked = 1;
+       dma_lock();
 
        /* Get into position */
        fd_set_side(minor, side);
        if (fd_set_track(minor, track)) {
-               locked = 0;
+               dma_unlock();
                return -1;
        }
 
@@ -289,7 +259,7 @@ static int fd_xfer_sector(uint8_t minor, uint8_t is_read)
 
                status = fd_get_reg(FDC_SR);
                if (!is_read && (status & FDC_WRI_PRO)) {
-                       locked = 0;
+                       dma_unlock();
                        udata.u_error = EROFS;
                        return -1;
                }
@@ -298,12 +268,12 @@ static int fd_xfer_sector(uint8_t minor, uint8_t is_read)
                        continue;
                }
                /* Whoopeee it worked */
-               locked = 0;
+               dma_unlock();
                if (is_read)
                        flush_cache_range(udata.u_dptr, 512);
                return 0;
        }
-       locked = 0;
+       dma_unlock();
        udata.u_error = EIO;
        return -1;
 }
@@ -380,7 +350,7 @@ static int fd_probe_drive(int unit)
        fd_set_reg(FDC_CS, FDC_RESTORE | FDC_HBIT | step[unit]);
        if (fd_wait() == 0) {
                if (fd_get_reg(FDC_CS) & FDC_TRACK0) {
-                       locked = 0;
+                       dma_unlock();
                        /* The Falcon might have HD but we'll deal with that in the far future! */
                        kprintf("fd%d: double density.\n", unit);
                        present[unit] = 1;
@@ -393,8 +363,8 @@ static int fd_probe_drive(int unit)
 void fd_probe(void)
 {
        /* Do we need to deal with waiting for motor off here ? */
-       locked = 1;
+       dma_lock();
        fd_probe_drive(0);
        fd_probe_drive(1);
-       locked = 0;
+       dma_unlock();
 }
index e1d8402..b4ae988 100644 (file)
@@ -7,6 +7,9 @@
 #include <devlpr.h>
 #include <tty.h>
 #include <vt.h>
+#include <machine.h>
+#include <devide.h>
+#include <acsi.h>
 
 struct devsw dev_tab[] =  /* The device driver switch table */
 {
@@ -27,15 +30,35 @@ struct devsw dev_tab[] =  /* The device driver switch table */
 
 bool validdev(uint16_t dev)
 {
-    /* This is a bit uglier than needed but the right hand side is
-       a constant this way */
-    if(dev > ((sizeof(dev_tab)/sizeof(struct devsw)) << 8) - 1)
-       return false;
-    else
-        return true;
+       /* This is a bit uglier than needed but the right hand side is
+          a constant this way */
+       if(dev > ((sizeof(dev_tab)/sizeof(struct devsw)) << 8) - 1)
+               return false;
+       else
+               return true;
 }
 void device_init(void)
 {
-    fd_probe();
+       fd_probe();
+       if (features & FEATURE_IDE)
+               devide_init();
+       acsi_init();
 }
 
+/* Very simple routines because we have a flat memory space and MMIO */
+
+void devide_read_data(void)
+{
+       uint16_t ct = 256;
+       uint16_t *p = (uint16_t *)blk_op.addr;
+       while(ct--)
+               *p++ = *ide_data16;
+}
+
+void devide_write_data(void)
+{
+       uint16_t ct = 256;
+       uint16_t *p = (uint16_t *)blk_op.addr;
+       while(ct--)
+               *ide_data16 = *p++;
+}
\ No newline at end of file
diff --git a/Kernel/platform-atarist/dma.c b/Kernel/platform-atarist/dma.c
new file mode 100644 (file)
index 0000000..39cf904
--- /dev/null
@@ -0,0 +1,58 @@
+#include <kernel.h>
+#include <timer.h>
+#include <dma.h>
+
+static uint8_t locked;
+
+/*
+ *     Set the 24bit DMA address for a transfer. The transfer is not
+ *     cache coherent and must be word aigned
+ */
+void set_dma_addr(uint8_t *ptr)
+{
+       uint32_t p = (uint32_t) ptr;
+       if (p & 1)
+               panic("odd dma");
+       DMA->addr_low = p;
+       DMA->addr_med = p >> 8;
+       DMA->addr_high = p >> 16;
+}
+
+/*
+ *     Report how the DMA did
+ */
+uint16_t get_dma_status(void)
+{
+       DMA->control = 0x90;
+       return DMA->control;
+}
+
+/*
+ *     Wait for a DMA devices to complete by watching a GPIO
+ */
+int dma_wait(uint16_t wait)
+{
+       timer_t x = set_timer_duration(wait);
+       while (!timer_expired(x)) {
+               uint8_t status = *(volatile uint8_t *)0xFFFA01;
+               if (!(status & 0x20))
+                       return 0;
+               platform_idle();
+       }
+       return -1;
+}
+
+void dma_lock(void)
+{
+       locked = 1;
+}
+
+void dma_unlock(void)
+{
+       locked = 0;
+}
+
+uint8_t dma_is_locked(void)
+{
+       return locked;
+}
index 39e30b7..496c356 100644 (file)
@@ -34,4 +34,12 @@ struct dma {
 #define        DMA_SCNOT0      0x0002
 #define DMA_DATREQ     0x0004
 
+extern void dma_lock(void);
+extern void dma_unlock(void);
+extern uint8_t dma_is_locked(void);
+
+extern void set_dma_addr(uint8_t *ptr);
+extern uint16_t get_dma_status(void);
+extern int dma_wait(uint16_t wait);
+
 #endif
diff --git a/Kernel/platform-atarist/loader.S b/Kernel/platform-atarist/loader.S
new file mode 100644 (file)
index 0000000..2fed676
--- /dev/null
@@ -0,0 +1,93 @@
+.mri 1
+
+;
+;      The boot loader fits in sector 0/0/1.
+;
+start:
+       bra.s   boot            ; requred first 2 bytes
+       ascii "Loader"
+       word 0
+       word 0                  ; DWord for the serial
+       word 2                  ; BPB not used (512 bytes/sec)
+       byte 2                  ; 2 sec/cluster
+       word $100               ; 1 sector reserved (intel format)
+       byte 1                  ; 1 extra FAT
+       word $100               ; entries in root directory
+       word $400B              ; sectors on disk (intel format)
+       byte $0                 ; more BPB crap we don't need
+       word $0
+       byte $9                 ; 9 spt
+       word $100               ; claim single sided
+       word $200               ; hidden sectors
+
+       word $0                 ; execflag
+       word $0                 ; load mode
+       word $0                 ; logical sector
+       word $0                 ; setcnt
+       word $0                 ; ldaaddr
+       word $0                 ; fatbuf
+
+       word $0                 ; fname
+       word $0
+       word $0
+       word $0
+       word $0
+       byte $0
+
+       word $0
+
+;
+;      We are located somewhere at random. We need to relocate ourself out
+;      of the way. For simplicity we locate ourselves up at 192K out of the
+;      way of the image we load above us. We always have at least 512K so
+;      that is fine.
+;
+;      The screen may be at $10000-$1FFFF.
+;
+;      We are only guaranteed that rwabs _floprd and getbpb exist there is
+;      nothing else definitely in the ROM
+;
+boot:
+       lea.l run(pc),a0
+       move.l #$30000,a1
+       move.l a1,a2
+       move.w #128,d0
+copy:
+       move.l (a0)+,(a1)+
+       dbra d0,copy
+       jmp (a2)
+
+run:
+       lea.l   $30000,sp
+load:
+       clr.w   -(sp)           ; Drive A: (FIXME - should work off boot)
+       move.w #1,-(sp)         ; From sector 1
+       move.w #$256,-(sp)      ; 256 sectors
+       move.l #$40000,-(sp)    ; read address
+       move.w #2,-(sp)         ; read, ignore media change
+       move.w #4,-(sp)         ; rwabs
+       trap #13
+
+       ; Now run our code
+       ; All interrupts off while we eat TOS alive
+       or.w #$0700,sr
+
+       ; Skip the vectors and first 512 bytes of TOS variables in case
+       ; they are useful
+       move.w #$600,a0
+       move.l #$40000,a1
+       ; Relocate 128K
+       move.w #$7FFF,d0
+install:
+       move.l (a1)+,(a0)+
+       dbra d0,install
+
+       jmp $600
+
+       ; Never returns
+
+
+;
+;      And the checksum goes at $1FE (entire sector summed in motorola
+;      word format should be $1234
+;
diff --git a/Kernel/platform-atarist/machine.h b/Kernel/platform-atarist/machine.h
new file mode 100644 (file)
index 0000000..b928f10
--- /dev/null
@@ -0,0 +1,34 @@
+
+extern uint16_t features;
+
+/* One of these is set for machine type */
+#define FEATURE_FALCON 0x8000          /* Falcon */
+/* 68030 16MHz, 68881/2, 56001DSP, VIDEL video, blitter, DMA audio, crossbar,
+   2.5" IDE, 1.4MB FDC, SCSI, 2xRS232, enhanced joysticks, RS422 */
+#define FEATURE_TT     0x4000          /* Atari TT */
+/* 68030 32MHz, new graphics, extra MFP, VME, VGA, SCSI, no blitter, 1.44MB FDC,
+fast RAM that isn't DMA capable, 3xRS232, RS422 */
+#define FEATURE_STE    0x2000          /* Atari STe */
+/* 68000 8MHz, blitter, PCM audio, extra joystick features, more colours */
+#define FEATURE_MSTE   0x1000          /* Mega STe */
+/* 68000 + 68881/2FPU, VME, 3xRS232, RS422, 1.44MB FDC, 3 button mouse 8/16MHz
+   extra joystick features, ACSI/SCSI, blitter, more colours */
+#define FEATURE_ST     0x0000          /* ST STF STFM Mega ST */
+/* 68000 8MHz, 720K floppy (360 on earliest), blitter on some MegaST */
+/* FIXME: can we tell MegaST by the RTC ? */
+
+/* TODO: Stacy and STBook */
+
+#define MACHINE_TYPE (features & 0xFF00)       
+
+/* Device features */
+#define FEATURE_IDE    0x0080          /* IDE controller - inbuilt or add in */
+#define FEATURE_VME    0x0040          /* Has VME bus */
+#define FEATURE_RTC    0x0020          /* Add in RTC */
+#define FEATURE_BLITTER        0x0010          /* Has a Blitter */
+#define FEATURE_TTRTC  0x0008          /* TT style MC146818A */
+
+/* Various other things could be tested for but they are basically machine
+   tied anyway. One exceptio we need to tidy up somewhere is 1.44MB floppy */
+
+/* TODO: FPU detect */
\ No newline at end of file
index 3811848..8c95e8e 100644 (file)
@@ -3,13 +3,15 @@
 #include <kdata.h>
 #include <printf.h>
 #include <devtty.h>
+#include <machine.h>
+
+uint8_t need_resched;
+uint16_t features;
 
 void platform_idle(void)
 {
 }
 
-uint8_t need_resched;
-
 uint8_t platform_param(char *p)
 {
        return 0;
@@ -33,8 +35,43 @@ void do_beep(void)
 {
 }
 
+struct probe_bits {
+       const char *name;
+       uint16_t bits;
+       uint32_t addr;
+};
+
+struct probe_bits probes[] = {
+       { "falcon ", FEATURE_FALCON, 0xFF8007 },
+       { "tt ", FEATURE_TT, 0xFF8260 },
+       { "ste", FEATURE_STE, 0xFF8093 },
+
+       { "vme ", FEATURE_VME, 0xFF8E01 },
+       { "rtc ", FEATURE_RTC, 0xFFFC21 },
+       { "tt-rtc ", FEATURE_TTRTC, 0xFF8961 },
+       { "blitter ", FEATURE_BLITTER, 0xFF8A00 },
+       { "ide ", FEATURE_IDE, 0xF00009 },
+       { NULL, 0, 0 }
+};
+
 void map_init(void)
 {
+       struct probe_bits *p = probes;
+       /* Useful spot for hardware set up and reporting */
+
+       kputs("Features: ");
+       while(p->name) {
+               if (probe_memory((uint8_t *)p->addr) == 0) {
+                       features |= p->bits;
+                       kputs(p->name);
+               }
+               p++;
+       }
+       if ((features & (FEATURE_VME|FEATURE_TT)) == FEATURE_VME) {
+               features |= FEATURE_MSTE;
+               kputs("mste");
+        }
+        kputchar('\n');
 }
 
 u_block uarea_block[PTABSIZE];
@@ -45,7 +82,6 @@ uint16_t fdseek;
 uint16_t cputype;
 uint32_t screenbase;
 
-
 void pagemap_init(void)
 {
        extern uint8_t _end;
diff --git a/Kernel/platform-atarist/platform_ide.h b/Kernel/platform-atarist/platform_ide.h
new file mode 100644 (file)
index 0000000..1f0158b
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *     Normal Atari Falcon, STBook and add in card IDE
+ *
+ *     Beware - if there is no IDE present it will bus error
+ *     Beware #2 - don't probe it using F00000 or you might be fooled by
+ *     an Adspeed interface and put the machine into 16Mhz mode instead. Probe
+ *     one of the others.
+ */
+
+#define IDE_IS_MMIO
+
+#define IDE_REG_DATA           0xF00001        /* 16bit at 0000/0001 */
+#define IDE_REG_ERROR          0xF00005
+#define IDE_REG_FEATURES       0xF00009
+#define IDE_REG_SEC_COUNT      0xF00009
+#define IDE_REG_LBA_0          0xF0000D
+#define IDE_REG_LBA_1          0xF00011
+#define IDE_REG_LBA_2          0xF00015
+#define IDE_REG_LBA_3          0xF00019
+#define IDE_REG_DEVHEAD                0xF00019
+#define IDE_REG_COMMAND                0xF0001D
+#define IDE_REG_STATUS         0xF0001D
+
+#define IDE_REG_CONTROL                0xF00039
+#define IDE_REG_ALTSTATUS      0xF00039
+
+/* Only one controller */
+#define ide_select(dev)
+#define ide_deselect()
+
+#define ide_data16             ((volatile uint16_t *)0xF00000)