Hi guys,
so far the ata-device emulation is rather complete but does not work
under Linux. The host-controller driver is missing.
But the generic-ata driver of Linux should work enabling PIO access. So
I have rewritten the code in order to allow Linux direct access to the
device.
The ata section in sim.cfg needs one additional parameter for this case
"init = 1". This tells the host controller to do some basic init
procedure normally done in software in order to allow to direct access
the ata device. So, the ATA host controller should still work without
problems if used.
I have also repaired the ata section as mentioned here
bugzilla.opencores.org/show_bug.cgi?id=23
All patches are in the attachment including one for the .dts file of the
Linux kernel. Additionally the Linux .config needs to be changed. I am
not sure if you want to enable this as standard in or1ksim-defconfig.
Basically you have to enable the block device, SCSI device, ATA device,
ATA for platform devices and some sort of filesystem.
CONFIG_BLOCK=y
CONFIG_SCSI=y
CONFIG_ATA=y
CONFIG_ATA_SFF=y
CONFIG_BLK_DEV_SD=y
CONFIG_PATA_PLATFORM=y
CONFIG_PATA_OF_PLATFORM=y
I have tested it with ext2 and also reduced the device waiting time a
bit that it behaves more like an SSD than a harddisk.
Sebastian Macke
[PATCH 1/3] Correct ata section. Standard empty 8MB harddisk
Signed-off-by: Sebastian Macke <[email protected]>
---
sim.cfg | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/sim.cfg b/sim.cfg
index 4dfbb03..d1238ea 100755
--- a/sim.cfg
+++ b/sim.cfg
@@ -448,11 +448,10 @@ section ata
enabled = 0
baseaddr = 0x9e000000
irq = 15
-
- device 0
+ device = 0
type = 1
- size = 1
- enddevice
+ size = 8
+ enddevice = 0
end
--
1.8.3.2
[PATCH 2/3] Enable direct access to ata devices
Signed-off-by: Sebastian Macke <[email protected]>
---
peripheral/atadevice-cmdi.c | 14 ++---
peripheral/atadevice.c | 1 +
peripheral/atahost.c | 142 +++++++++++++++++++++++++++++++++++---------
peripheral/atahost.h | 3 +
4 files changed, 125 insertions(+), 35 deletions(-)
diff --git a/peripheral/atadevice-cmdi.c b/peripheral/atadevice-cmdi.c
index 27fcfd0..ca84bef 100644
--- a/peripheral/atadevice-cmdi.c
+++ b/peripheral/atadevice-cmdi.c
@@ -138,7 +138,7 @@ ata_read_sect (struct ata_device *dev)
dev->internals.lba += BYTES_PER_SECTOR;
dev->internals.nr_sect--;
- SCHED_ADD (ata_cmd_complete, dev, 400000);
+ SCHED_ADD (ata_cmd_complete, dev, 4000);
}
/* Writes a sector to the device */
@@ -168,7 +168,7 @@ ata_write_sect (struct ata_device *dev)
if (!--dev->internals.nr_sect)
dev->regs.status = ATA_SR_DRDY | ATA_SR_DSC | ATA_SR_BSY;
- SCHED_ADD (ata_cmd_complete, dev, 40000);
+ SCHED_ADD (ata_cmd_complete, dev, 4000);
}
@@ -1081,12 +1081,12 @@ ata_device_execute_cmd (struct ata_device *device)
{
case DEVICE_RESET:
ata_device_reset_cmd (device);
- SCHED_ADD (ata_cmd_complete, device, 4000000);
+ SCHED_ADD (ata_cmd_complete, device, 400000);
return 0;
case EXECUTE_DEVICE_DIAGNOSTICS:
ata_execute_device_diagnostics_cmd (device);
- SCHED_ADD (ata_cmd_complete, device, 4000000);
+ SCHED_ADD (ata_cmd_complete, device, 400000);
return 0;
case IDENTIFY_DEVICE:
@@ -1108,17 +1108,17 @@ ata_device_execute_cmd (struct ata_device *device)
case READ_NATIVE_MAX_ADDRESS:
ata_read_native_max_addr (device);
- SCHED_ADD (ata_cmd_complete, device, 40000);
+ SCHED_ADD (ata_cmd_complete, device, 4000);
return 0;
case WRITE_SECTORS:
ata_write_sectors (device);
- SCHED_ADD (ata_cmd_complete, device, 40000);
+ SCHED_ADD (ata_cmd_complete, device, 4000);
return 0;
case SET_FEATURES:
ata_set_features (device);
- SCHED_ADD (ata_cmd_complete, device, 4000);
+ SCHED_ADD (ata_cmd_complete, device, 400);
return 0;
default:
diff --git a/peripheral/atadevice.c b/peripheral/atadevice.c
index 066c5b1..0a719fd 100644
--- a/peripheral/atadevice.c
+++ b/peripheral/atadevice.c
@@ -429,6 +429,7 @@ ata_devices_read (struct ata_devices * devices, char adr)
device->internals.dev)
{
device->sigs.intrq = 0;
+ ata_clear_int (device->internals.host);
return device->regs.status;
}
diff --git a/peripheral/atahost.c b/peripheral/atahost.c
index 5d9ae98..3345c7d 100644
--- a/peripheral/atahost.c
+++ b/peripheral/atahost.c
@@ -76,6 +76,13 @@ ata_reset (void *dat)
/* the reset bit in the control register 'ctrl' is set, reset connect
ata-devices */
ata_devices_hw_reset (&ata->devices, 1);
+
+ if (ata->init)
+ {
+ ata->regs.ctrl |= ATA_IDE_EN;
+ ata_devices_hw_reset (&ata->devices, 0);
+ }
+
}
/* ========================================================================= */
@@ -93,8 +100,70 @@ ata_int (void *dat)
}
}
+/* Clear interrupt */
+void
+ata_clear_int (void *dat)
+{
+ struct ata_host *ata = dat;
+
+ if (ata->regs.stat & ATA_IDEIS)
+ {
+ clear_interrupt (ata->irq);
+ ata->regs.stat &= ~ATA_IDEIS;
+ }
+}
+
+
/* ========================================================================= */
+ /* correct read/write delay timings */
+
+static void
+ata_correct_readwrite_delay(oraddr_t addr, void *dat)
+{
+ struct ata_host *ata = dat;
+// make sure simulator uses correct read/write delay timings
+ if (((addr & 0x7f) == ATA_DR) && (ata->dev_id > 1))
+ {
+ if (ata->dev_sel)
+ adjust_rw_delay (ata->mem, ata_pio_delay (ata->regs.pftr1),
+ ata_pio_delay (ata->regs.pftr1));
+ else
+ adjust_rw_delay (ata->mem, ata_pio_delay (ata->regs.pftr0),
+ ata_pio_delay (ata->regs.pftr0));
+ }
+ else
+ adjust_rw_delay (ata->mem, ata_pio_delay (ata->regs.pctr),
+ ata_pio_delay (ata->regs.pctr));
+}
+/* ========================================================================= */
+
+
+
+static uint8_t
+ata_read8 (oraddr_t addr, void *dat)
+{
+ struct ata_host *ata = dat;
+ if (ata->regs.ctrl & ATA_IDE_EN)
+ {
+ ata_correct_readwrite_delay (addr, dat);
+ return ata_devices_read (&ata->devices, addr & 0x7f);
+ }
+ return 0;
+}
+
+static uint16_t
+ata_read16 (oraddr_t addr, void *dat)
+{
+ struct ata_host *ata = dat;
+ if (ata->regs.ctrl & ATA_IDE_EN)
+ {
+ ata_correct_readwrite_delay (addr, dat);
+ return ata_devices_read (&ata->devices, addr & 0x7f);
+ }
+ return 0;
+}
+
/*
Read a register
@@ -144,20 +213,7 @@ ata_read32 (oraddr_t addr, void *dat)
/* check if the controller is enabled */
if (ata->regs.ctrl & ATA_IDE_EN)
{
- // make sure simulator uses correct read/write delay timings
- if (((addr & 0x7f) == ATA_DR) && ata->dev_id > 1)
- {
- if (ata->dev_sel)
- adjust_rw_delay (ata->mem, ata_pio_delay (ata->regs.pftr1),
- ata_pio_delay (ata->regs.pftr1));
- else
- adjust_rw_delay (ata->mem, ata_pio_delay (ata->regs.pftr0),
- ata_pio_delay (ata->regs.pftr0));
- }
- else
- adjust_rw_delay (ata->mem, ata_pio_delay (ata->regs.pctr),
- ata_pio_delay (ata->regs.pctr));
-
+ ata_correct_readwrite_delay (addr, dat);
return ata_devices_read (&ata->devices, addr & 0x7f);
}
return 0;
@@ -169,6 +225,30 @@ ata_read32 (oraddr_t addr, void *dat)
/*
Write a register
*/
+
+static void
+ata_write8 (oraddr_t addr, uint8_t value, void *dat)
+{
+ struct ata_host *ata = dat;
+ if (ata->regs.ctrl & ATA_IDE_EN)
+ {
+ ata_correct_readwrite_delay (addr, dat);
+ ata_devices_write (&ata->devices, addr & 0x7f, value);
+ }
+}
+
+static void
+ata_write16 (oraddr_t addr, uint16_t value, void *dat)
+{
+ struct ata_host *ata = dat;
+ if (ata->regs.ctrl & ATA_IDE_EN)
+ {
+ ata_correct_readwrite_delay (addr, dat);
+ ata_devices_write (&ata->devices, addr & 0x7f, value);
+ }
+}
+
+
static void
ata_write32 (oraddr_t addr, uint32_t value, void *dat)
{
@@ -241,20 +321,7 @@ ata_write32 (oraddr_t addr, uint32_t value, void *dat)
/* check if the controller is enabled */
if (ata->regs.ctrl & ATA_IDE_EN)
{
- // make sure simulator uses correct read/write delay timings
- if (((addr & 0x7f) == ATA_DR) && (ata->dev_id > 1))
- {
- if (ata->dev_sel)
- adjust_rw_delay (ata->mem, ata_pio_delay (ata->regs.pftr1),
- ata_pio_delay (ata->regs.pftr1));
- else
- adjust_rw_delay (ata->mem, ata_pio_delay (ata->regs.pftr0),
- ata_pio_delay (ata->regs.pftr0));
- }
- else
- adjust_rw_delay (ata->mem, ata_pio_delay (ata->regs.pctr),
- ata_pio_delay (ata->regs.pctr));
-
+ ata_correct_readwrite_delay (addr, dat);
if ((addr & 0x7f) == ATA_DHR)
ata->dev_sel = value & ATA_DHR_DEV;
@@ -519,6 +586,14 @@ ata_enabled (union param_val val, void *dat)
}
static void
+ata_init (union param_val val, void *dat)
+{
+ struct ata_host *ata = dat;
+ ata->init = val.int_val;
+}
+
+
+static void
ata_heads (union param_val val, void *dat)
{
struct ata_host *ata = dat;
@@ -631,6 +706,7 @@ ata_sec_start (void)
memset (new, 0, sizeof (struct ata_host));
new->enabled = 1;
+ new->init = 0;
new->baseaddr = 0;
new->irq = 0;
new->dev_id = 1;
@@ -691,8 +767,17 @@ ata_sec_end (void *dat)
ops.readfunc32 = ata_read32;
ops.read_dat32 = dat;
+ ops.readfunc16 = ata_read16;
+ ops.read_dat16 = dat;
+ ops.readfunc8 = ata_read8;
+ ops.read_dat8 = dat;
+
ops.writefunc32 = ata_write32;
ops.write_dat32 = dat;
+ ops.writefunc16 = ata_write16;
+ ops.write_dat16 = dat;
+ ops.writefunc8 = ata_write8;
+ ops.write_dat8 = dat;
/* Delays will be readjusted later */
ops.delayr = 2;
@@ -715,6 +800,7 @@ reg_ata_sec ()
reg_config_param (sec, "irq", PARAMT_INT, ata_irq);
reg_config_param (sec, "dev_id", PARAMT_INT, ata_dev_id);
reg_config_param (sec, "rev", PARAMT_INT, ata_rev);
+ reg_config_param (sec, "init", PARAMT_INT, ata_init);
reg_config_param (sec, "pio_mode0_t1", PARAMT_INT, ata_pio_mode0_t1);
reg_config_param (sec, "pio_mode0_t2", PARAMT_INT, ata_pio_mode0_t2);
diff --git a/peripheral/atahost.h b/peripheral/atahost.h
index 649cd52..a872a53 100755
--- a/peripheral/atahost.h
+++ b/peripheral/atahost.h
@@ -110,6 +110,9 @@ struct ata_host
/* Is peripheral enabled? */
int enabled;
+ /* Initialize device after hard reset? */
+ int init;
+
/* Base address in memory */
oraddr_t baseaddr;
--
1.8.3.2
[PATCH 3/3] Add comment about ata init option
Signed-off-by: Sebastian Macke <[email protected]>
---
sim.cfg | 1 +
1 file changed, 1 insertion(+)
diff --git a/sim.cfg b/sim.cfg
index d1238ea..87c8f7b 100755
--- a/sim.cfg
+++ b/sim.cfg
@@ -421,6 +421,7 @@ end
enabled = 0|1
baseaddr = <value> (default: 0)
irq = <value> (default: 0)
+ init = 0|1
dev_id = 1|2|3
rev = 0-15 (default: 1)
pio_mode0_t1 = 0-255 (default: 6)
--
1.8.3.2
Subject: [PATCH] Add generic ata device
Signed-off-by: Sebastian Macke <[email protected]>
---
arch/openrisc/boot/dts/or1ksim.dts | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/openrisc/boot/dts/or1ksim.dts
b/arch/openrisc/boot/dts/or1ksim.dts
index 5d4f902..c44563b 100644
--- a/arch/openrisc/boot/dts/or1ksim.dts
+++ b/arch/openrisc/boot/dts/or1ksim.dts
@@ -47,4 +47,14 @@
reg = <0x92000000 0x100>;
interrupts = <4>;
};
+
+ ata@9e000000 {
+ compatible = "ata-generic";
+ reg = <0x9e000040 0x30
+ 0x9e000078 0x10>;
+ pio-mode = <4>;
+ reg-shift = <2>;
+ interrupts = <15>;
+ };
+
};
--
1.8.3.2
_______________________________________________
OpenRISC mailing list
[email protected]
http://lists.openrisc.net/listinfo/openrisc