Patchwork ahci: enhance usable port count to 4

login
register
mail settings
Submitter Sebastian Herbszt
Date May 13, 2010, 3:34 p.m.
Message ID <1273764864$2723@local>
Download mbox | patch
Permalink /patch/52489/
State New
Headers show

Comments

Sebastian Herbszt - May 13, 2010, 3:34 p.m.
Make all 4 SATA ports usable.

Signed-off-by: Sebastian Herbszt <herbszt@gmx.de>
Alexander Graf - May 13, 2010, 11:01 p.m.
On 13.05.2010, at 17:34, Sebastian Herbszt wrote:

> Make all 4 SATA ports usable.

Please CC qemu-ahci-devel@lists.sourceforge.net for ahci patches stacking on the ahci branch. That way I don't need to fiddle them out manually from qemu-devel.

Alex

Patch

diff --git a/hw/ahci.c b/hw/ahci.c
index 6f7b807..a343839 100644
--- a/hw/ahci.c
+++ b/hw/ahci.c
@@ -17,7 +17,6 @@ 
  *
  * TODO:
  *  o ahci cd support should use ide,but now ide 's bmdma prdt is different from ahci's prdt.
- *  make ahci use multi-devices at the same time
  *  make code to reuse ide's code
  */
 #include "hw.h"
@@ -266,7 +265,7 @@  typedef struct AHCIState{
 	uint32_t port_state[SATA_PORTS];
 	int mem;
 	QEMUTimer *timer;
-	IDEBus *ide;
+	IDEBus *ide[SATA_PORTS];
 	ahci_sg *prdt_buf;
 	qemu_irq irq;
 } AHCIState;
@@ -291,7 +290,7 @@  static uint32_t  ahci_port_read(AHCIState *s,int port,int offset)
 	switch(offset)
 	{
 		case PORT_SCR:
-			if(s->ide && port==0)
+			if(s->ide[port])
 				val= 3 /* DET */ | (1 << 4) /* SPD */ | (1 << 8) /* IPM */;
 			else
 				val=0;
@@ -489,7 +488,7 @@  static void ahci_reg_init(AHCIState *s)
 	int i;
 	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.impl = 15; /* Ports 0-3 implemented */
 	s->control_regs.version = 0x10000;
 	for(i=0;i<SATA_PORTS;i++)
     s->port_state[i]=STATE_RUN;
@@ -736,13 +735,13 @@  static inline int media_is_cd(IDEState *s)
 {
     return (media_present(s) && s->nb_sectors <= CD_MAX_SECTORS);
 }
-static void ide_atapi_cmd(AHCIState *s,int prdt_num)
+static void ide_atapi_cmd(AHCIState *s,int prdt_num, int port)
 {
     const uint8_t *packet;
     uint8_t *buf;
     int max_len;
 	IDEState *ide_state;
-	ide_state=&s->ide->ifs[0];
+	ide_state=&s->ide[port]->ifs[0];
 
     packet = ide_state->io_buffer;
     buf = ide_state->io_buffer;
@@ -1055,8 +1054,8 @@  static void handle_cmd(AHCIState *s,int port,int slot)
 		case STATE_RESET:
 			if(!(fis[15]&ATA_SRST))
 			{ 
-				if(!s->ide)hw_error("no ahci sata disk now\n");
-				ide_state=&s->ide->ifs[0];
+				if(!s->ide[port])hw_error("no ahci sata disk now\n");
+				ide_state=&s->ide[port]->ifs[0];
 				s->port_state[port]=STATE_RUN;
 				if(bdrv_get_type_hint(ide_state->bs)==BDRV_TYPE_CDROM)
 					s->port_regs[port].sig=0xeb14<<16;
@@ -1067,8 +1066,8 @@  static void handle_cmd(AHCIState *s,int port,int slot)
 
 	if(fis[1]==(1<<7))
 	{
-		if(!s->ide)hw_error("no ahci sata disk now\n");
-		ide_state=&s->ide->ifs[0];
+		if(!s->ide[port])hw_error("no ahci sata disk now\n");
+		ide_state=&s->ide[port]->ifs[0];
 		switch(fis[2])
 		{
 			case WIN_PIDENTIFY:
@@ -1094,7 +1093,7 @@  static void handle_cmd(AHCIState *s,int port,int slot)
 				ide_state->atapi_dma = 1;
 				ide_state->nsector = 1;
 				memcpy(ide_state->io_buffer,acmd,32);
-				ide_atapi_cmd(s,prdt_num);
+				ide_atapi_cmd(s,prdt_num,port);
 				pr->irq_stat |= (1<<2);
 				break;
 			case WIN_STANDBYNOW1:
@@ -1151,20 +1150,26 @@  static void ahci_timer_function(void *opaque)
 
 static AHCIState *ahci_new(void)
 {
+	int i;
 	DriveInfo *dinfo;
-	IDEBus  *bus = qemu_mallocz(sizeof(IDEBus));
-	BMDMAState *bmdma=qemu_mallocz(sizeof(BMDMAState));
+	IDEBus  *bus[SATA_PORTS];
+	BMDMAState *bmdma[SATA_PORTS];
+	for (i = 0; i < SATA_PORTS; i++) {
+		bus[i] = qemu_mallocz(sizeof(IDEBus));
+		bmdma[i] = qemu_mallocz(sizeof(BMDMAState));
+	}
 	AHCIState *s = qemu_mallocz(sizeof(AHCIState));
 	ahci_reg_init(s);
 	s->mem = cpu_register_io_memory(ahci_readfn, ahci_writefn, s);
 	s->timer = qemu_new_timer(vm_clock, ahci_timer_function, s);
 	s->prdt_buf = qemu_malloc(65535*32);
 
-	if ((dinfo = drive_get(IF_SATA, 0, 0)) != NULL)
-	{
-		ide_init2(bus, dinfo, NULL,0);
-		s->ide=bus;
-		s->ide->bmdma=bmdma;
+	for (i = 0; i < SATA_PORTS; i++) {
+		if ((dinfo = drive_get(IF_SATA, 0, i)) != NULL) {
+			ide_init2(bus[i], dinfo, NULL,0);
+			s->ide[i]=bus[i];
+			s->ide[i]->bmdma=bmdma[i];
+		}
 	}
 	return s;
 }