testers wanted: patch for Intel 31244 SATA controller

Jia-Shiun Li jiashiun at gmail.com
Thu Jun 2 06:03:54 GMT 2005


Hi all,

I have a patch to ata(4) to support Intel 31244 SATA disk controller .
Now it works fine on my computer. If anyone is interested in testing,
please apply the attached patch under /usr/src. Comments are welcome.

Thanks,
Jia-Shiun.
-------------- next part --------------
Index: sys/dev/ata/ata-chipset.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-chipset.c,v
retrieving revision 1.120
diff -u -r1.120 ata-chipset.c
--- sys/dev/ata/ata-chipset.c	16 May 2005 13:07:26 -0000	1.120
+++ sys/dev/ata/ata-chipset.c	2 Jun 2005 05:19:47 -0000
@@ -77,6 +77,10 @@
 static void ata_highpoint_intr(void *);
 static void ata_highpoint_setmode(device_t, int);
 static int ata_highpoint_check_80pin(device_t, int);
+static int ata_31244_chipinit(device_t);
+static void ata_31244_reset(device_t);
+static int ata_31244_allocate(device_t);
+static void ata_31244_intr(void *data);
 static int ata_intel_chipinit(device_t);
 static void ata_intel_intr(void *);
 static void ata_intel_reset(device_t);
@@ -1380,6 +1384,7 @@
      { ATA_I82801GB_R1, 0, 0, 0x00, ATA_SA150, "Intel ICH7" },
      { ATA_I82801GB_M,  0, 0, 0x00, ATA_SA150, "Intel ICH7" },
      { ATA_I82801GB_AH, 0, 0, 0x00, ATA_SA150, "Intel ICH7" },
+     { ATA_I31244,	0, 0, 0x00, ATA_SA150, "Intel 31244" },
      { 0, 0, 0, 0, 0, 0}};
     char buffer[64]; 
 
@@ -1389,8 +1394,155 @@
     sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
     device_set_desc_copy(dev, buffer);
     ctlr->chip = idx;
-    ctlr->chipinit = ata_intel_chipinit;
+    if (idx->chipid == ATA_I31244) {
+	if (pci_get_subclass(dev) == PCIS_STORAGE_IDE) {
+	    /* card set to PCI/IDE compatible mode */
+	    return ata_generic_ident(dev);
+	} else {
+	    /* card set to DPA mode */
+	    ctlr->chipinit = ata_31244_chipinit;
+	}
+    } else {
+	ctlr->chipinit = ata_intel_chipinit;
+    }
+    return 0;
+}
+
+static int ata_31244_chipinit(device_t dev)
+{
+    struct ata_pci_controller *ctlr = device_get_softc(dev);
+    int rid = ATA_IRQ_RID;
+
+    if (!(ctlr->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+					       RF_SHAREABLE | RF_ACTIVE))) {
+	device_printf(dev, "unable to map interrupt\n");
+	return ENXIO;
+    }
+    
+    if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
+		    ata_31244_intr, ctlr, &ctlr->handle))) {
+	device_printf(dev, "unable to setup interrupt\n");
+	return ENXIO;
+    }
+
+    /* allocate memory mapping */
+    ctlr->r_type1 = SYS_RES_MEMORY;
+    ctlr->r_rid1 = PCIR_BAR(0);
+    if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1,
+		    &ctlr->r_rid1, RF_ACTIVE)))
+	return ENXIO;
+
+    ctlr->allocate = ata_31244_allocate;
+    ctlr->setmode = ata_sata_setmode;
+    ctlr->reset = ata_31244_reset;
+    ctlr->channels = 4;
+
+    return 0;
+}
+
+static int
+ata_31244_allocate(device_t dev)
+{
+    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+    struct ata_channel *ch = device_get_softc(dev);
+    int i;
+    int ch_offset;
+
+    printf("%s\n", __FUNCTION__);
+    
+    ch_offset = 0x200 + ch->unit*0x200;
+
+    for (i = ATA_DATA; i < ATA_MAX_RES; i++) {
+	ch->r_io[i].res = ctlr->r_res1;
+	ch->r_io[i].offset = ch_offset + (i << 2) ;
+    }
+    ch->r_io[ATA_DATA].offset = ch_offset + 0x00;
+    ch->r_io[ATA_FEATURE].offset = ch_offset + 0x06;
+    ch->r_io[ATA_COUNT].offset = ch_offset + 0x08;
+    ch->r_io[ATA_SECTOR].offset = ch_offset + 0x0c;
+    ch->r_io[ATA_CYL_LSB].offset = ch_offset + 0x10;
+    ch->r_io[ATA_CYL_MSB].offset = ch_offset + 0x14;
+    ch->r_io[ATA_DRIVE].offset = ch_offset + 0x18;
+    ch->r_io[ATA_COMMAND].offset = ch_offset + 0x1d;
+    ch->r_io[ATA_ERROR].offset = ch_offset + 0x04;
+    ch->r_io[ATA_STATUS].offset = ch_offset + 0x1c;
+    ch->r_io[ATA_ALTSTAT].offset = ch_offset + 0x28;
+    ch->r_io[ATA_CONTROL].offset = ch_offset + 0x29;
+    ch->r_io[ATA_SSTATUS].offset = ch_offset + 0x100;
+    ch->r_io[ATA_SERROR].offset = ch_offset + 0x104;
+    ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x108;
+    ch->r_io[ATA_BMCMD_PORT].offset = ch_offset + 0x70;
+    ch->r_io[ATA_BMSTAT_PORT].offset = ch_offset + 0x72;
+    ch->r_io[ATA_BMDTP_PORT].offset = ch_offset + 0x74;
+
+    ch->flags |= ATA_NO_SLAVE;
+
+    ata_generic_hw(dev);
+
     return 0;
+}
+
+static void
+ata_31244_intr(void *data)
+{
+    struct ata_pci_controller *ctlr = data;
+    struct ata_channel *ch;
+    int unit;
+
+    /* implement this as a toggle instead to balance load XXX */
+    for (unit = 0; unit < ctlr->channels; unit++) {
+	if (!(ch = ctlr->interrupt[unit].argument))
+	    continue;
+
+	/* check for PHY related interrupts on SATA capable HW */
+	if (ctlr->chip->max_dma >= ATA_SA150) {
+	    u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS);
+	    u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR);
+	    struct ata_connect_task *tp;
+
+	    if (error) {
+		/* clear error bits/interrupt */
+		ATA_IDX_OUTL(ch, ATA_SERROR, error);
+
+		/* if we have a connection event deal with it */
+		if ((error & ATA_SE_PHY_CHANGED) &&
+		    (tp = (struct ata_connect_task *)
+			  malloc(sizeof(struct ata_connect_task),
+				 M_ATA, M_NOWAIT | M_ZERO))) {
+
+		    if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) {
+			device_printf(ch->dev, "CONNECT requested\n");
+			tp->action = ATA_C_ATTACH;
+		    }
+		    else {
+			device_printf(ch->dev, "DISCONNECT requested\n");
+			tp->action = ATA_C_DETACH;
+		    }
+		    tp->dev = ch->dev;
+		    TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
+		    taskqueue_enqueue(taskqueue_thread, &tp->task);
+		}
+	    }
+	}
+
+	/* any drive action to take care of ? */
+	if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
+	    int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
+
+	    if (!(bmstat & ATA_BMSTAT_INTERRUPT))
+		continue;
+	    ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
+	    DELAY(1);
+	}
+	ctlr->interrupt[unit].function(ch);
+    }
+}
+
+static void
+ata_31244_reset(device_t dev)
+{
+    struct ata_channel *ch = device_get_softc(dev);
+    ata_sata_phy_enable(ch);
 }
 
 static int
Index: sys/dev/ata/ata-pci.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-pci.h,v
retrieving revision 1.48
diff -u -r1.48 ata-pci.h
--- sys/dev/ata/ata-pci.h	16 May 2005 13:07:27 -0000	1.48
+++ sys/dev/ata/ata-pci.h	2 Jun 2005 05:19:48 -0000
@@ -146,6 +146,7 @@
 #define ATA_I82801GB_R1         0x27c38086
 #define ATA_I82801GB_AH         0x27c18086
 #define ATA_I82801GB_M          0x27c58086
+#define ATA_I31244		0x32008086
 
 #define ATA_ITE_ID              0x1283
 #define ATA_IT8212F             0x82121283


More information about the freebsd-current mailing list