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