diff mbox

sparc esp dma endianness [patch-rfc]

Message ID fb8d4f70908311348p4b63220bqb661705b8c3d3f3b@mail.gmail.com
State Superseded
Headers show

Commit Message

Artyom Tarasenko Aug. 31, 2009, 8:48 p.m. UTC
Trying to find out what could be the mysterious scsi commands 60, 80,
c0 and e0, I found out that OBP during dma exchange has problems with
endianness.
OBP sends commands like this:
12 20 00 00 05 00 or this 12 80 00 00 05 00, but esp.c expects
that the second byte is the command and the first one is the target.

The following patch solves the problem, but breaks OpenBIOS. The
question is where do we have wrong endianness? It's not necessarily
esp, it may be something on the way like dma or mmu. Any ideas?


with the patch probing looks like this:

ok probe-scsi
Target 0
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 0   Disk
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 1   Disk
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 2   Disk
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 3   Disk
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 4   Disk
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 5   Disk
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 6   Disk
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 7   Disk
Target 2
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 0   Removable Read Only device
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 1   Removable Read Only device
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 2   Removable Read Only device
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 3   Removable Read Only device
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 4   Removable Read Only device
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 5   Removable Read Only device
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 6   Removable Read Only device
scsi-disk: Error: Inquiry (STANDARD) buffer size 5 is less than 36
(TODO: only 5 required)
  Unit 7   Removable Read Only device
ok

without patch it looks like this:

ok probe-scsi
Target 0
scsi-disk: Unsupported command length, command 60
scsi-disk: Unsupported command length, command 60
scsi-disk: Unsupported command length, command c0
scsi-disk: Unsupported command length, command c0
scsi-disk: Unsupported command length, command e0
scsi-disk: Unsupported command length, command e0
Target 2
scsi-disk: Unsupported command length, command 60
scsi-disk: Unsupported command length, command 60
scsi-disk: Unsupported command length, command c0
scsi-disk: Unsupported command length, command c0
scsi-disk: Unsupported command length, command e0
scsi-disk: Unsupported command length, command e0
ok

Comments

Blue Swirl Sept. 1, 2009, 3:54 p.m. UTC | #1
On Mon, Aug 31, 2009 at 11:48 PM, Artyom
Tarasenko<atar4qemu@googlemail.com> wrote:
> Trying to find out what could be the mysterious scsi commands 60, 80,
> c0 and e0, I found out that OBP during dma exchange has problems with
> endianness.
> OBP sends commands like this:
> 12 20 00 00 05 00 or this 12 80 00 00 05 00, but esp.c expects
> that the second byte is the command and the first one is the target.
>
> The following patch solves the problem, but breaks OpenBIOS. The
> question is where do we have wrong endianness? It's not necessarily
> esp, it may be something on the way like dma or mmu. Any ideas?

In addition to OpenBIOS, I'd also think Linux, NetBSD and OpenBSD
should break. Lance needs similar operation, but there the bus is
little endian and one bit configures byte swapping for some of data.

Usually the first byte is bus id. What if you changed (as a hack) here:
    DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
    lun = buf[0] & 7;
    datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun);
&buf[1] to &buf[0]?
Artyom Tarasenko Sept. 1, 2009, 5:08 p.m. UTC | #2
2009/9/1 Blue Swirl <blauwirbel@gmail.com>:
> Usually the first byte is bus id. What if you changed (as a hack) here:
>    DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
>    lun = buf[0] & 7;
>    datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun);
> &buf[1] to &buf[0]?

Yep, figured that out too, but did a little more complex hack:

lun = buf[1] >>5;
datalen = s->current_dev->send_command(s->current_dev, 0, &buf[0], lun);

with this hack OBP checks proper LUNs.

So, the problem is not endianness, but the missing bus id. But how the
bus id should get into the dma buffer?
It should be generated by esp, right?
Blue Swirl Sept. 1, 2009, 5:11 p.m. UTC | #3
On Tue, Sep 1, 2009 at 8:08 PM, Artyom
Tarasenko<atar4qemu@googlemail.com> wrote:
> 2009/9/1 Blue Swirl <blauwirbel@gmail.com>:
>> Usually the first byte is bus id. What if you changed (as a hack) here:
>>    DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
>>    lun = buf[0] & 7;
>>    datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun);
>> &buf[1] to &buf[0]?
>
> Yep, figured that out too, but did a little more complex hack:
>
> lun = buf[1] >>5;
> datalen = s->current_dev->send_command(s->current_dev, 0, &buf[0], lun);
>
> with this hack OBP checks proper LUNs.
>
> So, the problem is not endianness, but the missing bus id. But how the
> bus id should get into the dma buffer?
> It should be generated by esp, right?
>

It could be pushed into FIFO with PIO.
diff mbox

Patch

diff --git a/hw/esp.c b/hw/esp.c
index aad547e..aceee48 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -169,11 +169,17 @@  static uint32_t get_cmd(ESPState *s, uint8_t *buf)
 {
     uint32_t dmalen;
     int target;
-
-    target = s->wregs[ESP_WBUSID] & BUSID_DID;
-    if (s->dma) {
-        dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
-        s->dma_memory_read(s->dma_opaque, buf, dmalen);
+    uint8_t tmp,i;
+
+    target = s->wregs[ESP_WBUSID] & BUSID_DID;
+     if (s->dma) {
+         dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
+         s->dma_memory_read(s->dma_opaque, buf, dmalen);
+         for(i=0;i<dmalen;i+=2) {
+             tmp=buf[i];
+             buf[i]=buf[i+1];
+             buf[i+1]=tmp;
+         }
     } else {
         dmalen = s->ti_size;
         memcpy(buf, s->ti_buf, dmalen);