--- //depot/vendor/freebsd_6/src/sys/dev/ata/ata-chipset.c 2007/02/11 16:28:42 +++ //depot/yahoo/ybsd_6/src/sys/dev/ata/ata-chipset.c 2007/03/05 12:51:25 @@ -450,6 +450,7 @@ { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); + uint64_t work; int offset = (ch->unit << 7); /* setup legacy cruft we need */ @@ -478,13 +479,13 @@ ch->hw.command = NULL; /* not used here */ /* setup the work areas */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, - ch->dma->work_bus + ATA_AHCI_CL_OFFSET); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, 0x00000000); + work = ch->dma->work_bus + ATA_AHCI_CL_OFFSET; + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, - ch->dma->work_bus + ATA_AHCI_FB_OFFSET); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, 0x00000000); + work = ch->dma->work_bus + ATA_AHCI_FB_OFFSET; + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32); /* enable wanted port interrupts */ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, @@ -727,12 +728,15 @@ static void ata_ahci_dmainit(device_t dev) { + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); ata_dmainit(dev); if (ch->dma) { /* note start and stop are not used here */ ch->dma->setprd = ata_ahci_dmasetprd; + if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_64BIT) + ch->dma->alloc = ata_dmaalloc_64; ch->dma->max_iosize = 8192 * DEV_BSIZE; } } @@ -2383,7 +2387,7 @@ { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); - bus_addr_t work = ch->dma->work_bus; + uint64_t work = ch->dma->work_bus; int i; /* clear work area */ @@ -2436,7 +2440,7 @@ ATA_OUTL(ctlr->r_res1, 0x02000 + ATA_MV_EDMA_BASE(ch), (1<<11) | (1<<13)); /* request queue base high */ - ATA_OUTL(ctlr->r_res1, 0x02010 + ATA_MV_EDMA_BASE(ch), (work >> 16) >> 16); + ATA_OUTL(ctlr->r_res1, 0x02010 + ATA_MV_EDMA_BASE(ch), work >> 32); /* request queue in ptr */ ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), work & 0xffffffff); @@ -2446,7 +2450,7 @@ /* response queue base high */ work += 1024; - ATA_OUTL(ctlr->r_res1, 0x0201c + ATA_MV_EDMA_BASE(ch), (work >> 16) >> 16); + ATA_OUTL(ctlr->r_res1, 0x0201c + ATA_MV_EDMA_BASE(ch), work >> 32); /* response queue in ptr */ ATA_OUTL(ctlr->r_res1, 0x02020 + ATA_MV_EDMA_BASE(ch), 0x0); @@ -2566,7 +2570,7 @@ /* fill in this request */ quadp[0] = (long)ch->dma->sg_bus & 0xffffffff; - quadp[1] = (ch->dma->sg_bus & 0xffffffff00000000ull) >> 32; + quadp[1] = (uint64_t)ch->dma->sg_bus >> 32; wordp[4] = (request->flags & ATA_R_READ ? 0x01 : 0x00) | (tag<<1); i = 10; @@ -2707,7 +2711,7 @@ for (i = 0; i < nsegs; i++) { prd[i].addrlo = htole32(segs[i].ds_addr); - prd[i].addrhi = 0; + prd[i].addrhi = htole32((uint64_t)segs[i].ds_addr >> 32); prd[i].count = htole32(segs[i].ds_len); } prd[i - 1].count |= htole32(ATA_DMA_EOT); @@ -2721,6 +2725,7 @@ ata_dmainit(dev); if (ch->dma) { /* note start and stop are not used here */ + ch->dma->alloc = ata_dmaalloc_64; ch->dma->setprd = ata_marvell_dmasetprd; } } --- //depot/vendor/freebsd_6/src/sys/dev/ata/ata-dma.c 2006/01/25 01:30:53 +++ //depot/yahoo/ybsd_6/src/sys/dev/ata/ata-dma.c 2007/03/05 12:51:25 @@ -90,6 +90,72 @@ cba->maddr = segs[0].ds_addr; } +void +ata_dmaalloc_64(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + struct ata_dc_cb_args ccba; + + if (bus_dma_tag_create(NULL, ch->dma->alignment, 0, + BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, + NULL, NULL, ch->dma->max_iosize, + ATA_DMA_ENTRIES, ch->dma->segsize, + 0, NULL, NULL, &ch->dma->dmatag)) + goto error; + + if (bus_dma_tag_create(ch->dma->dmatag, PAGE_SIZE, PAGE_SIZE, + BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, + NULL, NULL, MAXTABSZ, 1, MAXTABSZ, + 0, NULL, NULL, &ch->dma->sg_tag)) + goto error; + + if (bus_dma_tag_create(ch->dma->dmatag,ch->dma->alignment,ch->dma->boundary, + BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, + NULL, NULL, ch->dma->max_iosize, + ATA_DMA_ENTRIES, ch->dma->segsize, + 0, NULL, NULL, &ch->dma->data_tag)) + goto error; + + if (bus_dmamem_alloc(ch->dma->sg_tag, (void **)&ch->dma->sg, 0, + &ch->dma->sg_map)) + goto error; + + if (bus_dmamap_load(ch->dma->sg_tag, ch->dma->sg_map, ch->dma->sg, + MAXTABSZ, ata_dmasetupc_cb, &ccba, 0) || ccba.error) { + bus_dmamem_free(ch->dma->sg_tag, ch->dma->sg, ch->dma->sg_map); + goto error; + } + ch->dma->sg_bus = ccba.maddr; + + if (bus_dmamap_create(ch->dma->data_tag, 0, &ch->dma->data_map)) + goto error; + + if (bus_dma_tag_create(ch->dma->dmatag, PAGE_SIZE, 64 * 1024, + BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, + NULL, NULL, MAXWSPCSZ, 1, MAXWSPCSZ, + 0, NULL, NULL, &ch->dma->work_tag)) + goto error; + + if (bus_dmamem_alloc(ch->dma->work_tag, (void **)&ch->dma->work, 0, + &ch->dma->work_map)) + goto error; + + if (bus_dmamap_load(ch->dma->work_tag, ch->dma->work_map,ch->dma->work, + MAXWSPCSZ, ata_dmasetupc_cb, &ccba, 0) || ccba.error) { + bus_dmamem_free(ch->dma->work_tag,ch->dma->work, ch->dma->work_map); + goto error; + } + ch->dma->work_bus = ccba.maddr; + + return; + +error: + device_printf(dev, "WARNING - DMA allocation failed, disabling DMA\n"); + ata_dmafree(dev); + free(ch->dma, M_ATADMA); + ch->dma = NULL; +} + static void ata_dmaalloc(device_t dev) { --- //depot/vendor/freebsd_6/src/sys/dev/ata/ata-pci.h 2007/02/11 16:28:42 +++ //depot/yahoo/ybsd_6/src/sys/dev/ata/ata-pci.h 2007/03/05 12:51:25 @@ -459,3 +459,4 @@ /* global prototypes ata-dma.c */ void ata_dmainit(device_t); +void ata_dmaalloc_64(device_t);