@@ -26,8 +26,15 @@
#include "dma.h"
#include "cpu-common.h"
#include <hw/ide/internal.h>
-#define DPRINTF(...)
+#define DEBUG_AHCI
+
+#ifdef DEBUG_AHCI
+#define DPRINTF(fmt, ...) \
+do { printf("ahci: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while(0)
+#endif
enum {
AHCI_PCI_BAR = 5,
@@ -203,6 +210,8 @@
uint32_t version;
} ahci_control_regs;
+#define SATA_PORTS 4
+
typedef struct ahci_port_regs {
uint32_t lst_addr;
uint32_t lst_addr_hi;
@@ -240,7 +249,7 @@
typedef struct AHCIState{
ahci_control_regs control_regs;
- ahci_port_regs port_regs[2];
+ ahci_port_regs port_regs[SATA_PORTS];
int mem;
QEMUTimer *timer;
IDEBus *ide;
@@ -268,8 +277,10 @@
switch(offset)
{
case PORT_SCR:
- if(s->ide && port==0) val=3;
- else val=0;
+ if(s->ide && port==0)
+ val= 3 /* DET */ | (1 << 4) /* SPD */ | (1 << 8) /* IPM */;
+ else
+ val=0;
break;
case PORT_IRQ_STAT:
val=pr->irq_stat;
@@ -291,6 +302,7 @@
val= p[offset>>2];
break;
}
+ DPRINTF("ahci_port_read: port: 0x%x offset: 0x%x val: 0x%x\n", port, offset, val);
return val;
}
@@ -299,7 +311,7 @@
{
ahci_port_regs *pr;
int i;
- for(i=0;i<2;i++)
+ for(i=0;i<SATA_PORTS;i++)
{
pr=&s->port_regs[i];
@@ -319,6 +331,7 @@
ahci_port_regs *pr=&s->port_regs[port];
uint32_t *p;
+ DPRINTF("ahci_port_write: port: 0x%x offset: 0x%x val: 0x%x\n", port, offset, val);
switch(offset)
{
case PORT_LST_ADDR:
@@ -396,7 +409,7 @@
val=p[addr>>2];
}
}
- else if(addr>=0x100 && addr<0x200)
+ else if(addr>=0x100 && addr<0x300)
{
val=ahci_port_read(s,(addr-0x100)>>7,addr&0x7f);
}
@@ -436,7 +449,7 @@
p=(uint32_t *)&s->control_regs;
}
}
- else if(addr>=0x100 && addr<0x200)
+ else if(addr>=0x100 && addr<0x300)
{
ahci_port_write(s,(addr-0x100)>>7,addr&0x7f,val);
}
@@ -459,10 +472,10 @@
static void ahci_reg_init(AHCIState *s)
{
- s->control_regs.cap=2|(0x1f<<8); /*2 ports,32 cmd slot*/
- s->control_regs.ghc=1<<31;
- s->control_regs.impl=1;/*2 ports*/
- s->control_regs.version=0x10100;
+ s->control_regs.cap = 3 | (0x1f << 8) | (1 << 20) ; /* 4 ports, 32 command slots, 1.5 Gb/s */
+ s->control_regs.ghc = 1 << 31; /* AHCI Enable */
+ s->control_regs.impl = 1; /* Port 0 implemented */
+ s->control_regs.version = 0x10000;
}
static void padstr(char *str, const char *src, int len)
@@ -619,19 +632,22 @@
prdt_num=cmd_hdr.opts>>16;
if(prdt_num) cpu_physical_memory_read(cmd_hdr.tbl_addr+0x80,(uint8_t *)s->prdt_buf,prdt_num*32);
-
+#ifdef DEBUG_AHCI
+ DPRINTF("fis:");
for(i=0;i<cmd_len;i++)
{
- if((i&0xf)==0)DPRINTF("\n%02x:",i);
- DPRINTF("%02x ",fis[i]);
+ if((i&0xf)==0) printf("\n%02x:",i);
+ printf("%02x ",fis[i]);
}
+ printf("\n");
+#endif
switch(fis[0])
{
case 0x27:
break;
default:
- hw_error("unkonow command fis[0]=%02x fis[1]=%02x fis[2]=%02x\n",fis[0],fis[1],fis[2]);break;
+ hw_error("unknown command fis[0]=%02x fis[1]=%02x fis[2]=%02x\n",fis[0],fis[1],fis[2]);break;
}
switch(fis[1])
@@ -641,7 +657,7 @@
case 0:
break;
default:
- hw_error("unkonow command fis[0]=%02x fis[1]=%02x fis[2]=%02x\n",fis[0],fis[1],fis[2]);break;
+ hw_error("unknown command fis[0]=%02x fis[1]=%02x fis[2]=%02x\n",fis[0],fis[1],fis[2]);break;
}
if(fis[1]==0)
@@ -684,7 +700,7 @@
pr->irq_stat |= (1<<2);
break;
default:
- hw_error("unkonow command fis[0]=%02x fis[1]=%02x fis[2]=%02x\n",fis[0],fis[1],fis[2]);break;
+ hw_error("unknown command fis[0]=%02x fis[1]=%02x fis[2]=%02x\n",fis[0],fis[1],fis[2]);break;
}
}
@@ -698,7 +714,7 @@
AHCIState *s = opaque;
ahci_port_regs *pr;
int i,j;
- for(i=0;i<2;i++)
+ for(i=0;i<SATA_PORTS;i++)
{
pr=&s->port_regs[i];
for(j=0;j<32 && pr->cmd_issue;j++)
@@ -741,23 +757,21 @@
#define PCI_VENDOR_MYDEVICE 0x8086
#define PCI_PRODUCT_MYDEVICE 0x2652
-#define PCI_CLASS_HEADERTYPE_00h 0x00
-
static int pci_ahci_init(PCIDevice *dev)
{
struct ahci_pci_state *d;
d = DO_UPCAST(struct ahci_pci_state, card, dev);
pci_config_set_vendor_id(d->card.config,PCI_VENDOR_MYDEVICE);
pci_config_set_device_id(d->card.config,PCI_PRODUCT_MYDEVICE);
- d->card.config[PCI_COMMAND] = 0x07; /* I/O + Memory */
+ d->card.config[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
d->card.config[PCI_CLASS_DEVICE] = 0;
d->card.config[0x0b] = 1;//storage
- d->card.config[0x0c] = 0x08; /* Cache line size */
- d->card.config[0x0d] = 0x40; /* Latency timer */
- d->card.config[0x0e] = PCI_CLASS_HEADERTYPE_00h;
- d->card.config[0x3d] = 1; /* interrupt pin 0 */
+ d->card.config[PCI_CACHE_LINE_SIZE] = 0x08; /* Cache line size */
+ d->card.config[PCI_LATENCY_TIMER] = 0x00; /* Latency timer */
+ d->card.config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
+ d->card.config[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */
- pci_register_bar(&d->card, 5, 0x200,
+ pci_register_bar(&d->card, 5, 0x400,
PCI_BASE_ADDRESS_SPACE_MEMORY, ahci_pci_map);
d->ahci=ahci_new();
d->ahci->irq = d->card.irq[0];
@@ -792,7 +806,7 @@
{
ahci_sysbus_state *d = FROM_SYSBUS(ahci_sysbus_state, dev);
d->ahci=ahci_new();
- sysbus_init_mmio(dev, 0x200, d->ahci->mem);
+ sysbus_init_mmio(dev, 0x400, d->ahci->mem);
sysbus_init_irq(dev, &d->ahci->irq);
return 0;
}