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