ata-dma.c revision 52918
145095Ssos/*- 245095Ssos * Copyright (c) 1998,1999 S�ren Schmidt 345095Ssos * All rights reserved. 445095Ssos * 545095Ssos * Redistribution and use in source and binary forms, with or without 645095Ssos * modification, are permitted provided that the following conditions 745095Ssos * are met: 845095Ssos * 1. Redistributions of source code must retain the above copyright 945095Ssos * notice, this list of conditions and the following disclaimer, 1045095Ssos * without modification, immediately at the beginning of the file. 1145095Ssos * 2. Redistributions in binary form must reproduce the above copyright 1245095Ssos * notice, this list of conditions and the following disclaimer in the 1345095Ssos * documentation and/or other materials provided with the distribution. 1445095Ssos * 3. The name of the author may not be used to endorse or promote products 1545095Ssos * derived from this software without specific prior written permission. 1645095Ssos * 1745095Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1845095Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1945095Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2045095Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2145095Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2245095Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2345095Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2445095Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2545095Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2645095Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2745095Ssos * 2850477Speter * $FreeBSD: head/sys/dev/ata/ata-dma.c 52918 1999-11-06 16:50:21Z sos $ 2945095Ssos */ 3045095Ssos 3145150Ssos#include "pci.h" 3251520Ssos#include "apm.h" 3345095Ssos#include <sys/param.h> 3445095Ssos#include <sys/systm.h> 3545095Ssos#include <sys/buf.h> 3645095Ssos#include <sys/malloc.h> 3745798Ssos#include <sys/bus.h> 3851520Ssos#include <vm/vm.h> 3945095Ssos#include <vm/pmap.h> 4047272Ssos#if NPCI > 0 4145095Ssos#include <pci/pcivar.h> 4247272Ssos#endif 4351520Ssos#if NAPM > 0 4451520Ssos#include <machine/apm_bios.h> 4551520Ssos#endif 4645095Ssos#include <dev/ata/ata-all.h> 4745095Ssos 4852067Ssos/* prototypes */ 4952067Ssosstatic void hpt366_timing(struct ata_softc *, int32_t, int32_t); 5052067Ssos 5152067Ssos/* misc defines */ 5252067Ssos#define MIN(a,b) ((a)>(b)?(b):(a)) 5345720Speter#ifdef __alpha__ 5445720Speter#undef vtophys 5551520Ssos#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va) 5645720Speter#endif 5745720Speter 5845150Ssos#if NPCI > 0 5945150Ssos 6045095Ssosint32_t 6145095Ssosata_dmainit(struct ata_softc *scp, int32_t device, 6245095Ssos int32_t apiomode, int32_t wdmamode, int32_t udmamode) 6345095Ssos{ 6445095Ssos int32_t type, devno, error; 6545095Ssos void *dmatab; 6645095Ssos 6745095Ssos if (!scp->bmaddr) 6845095Ssos return -1; 6951520Ssos#ifdef ATA_DMADEBUG 7045095Ssos printf("ata%d: dmainit: ioaddr=0x%x altioaddr=0x%x, bmaddr=0x%x\n", 7145095Ssos scp->lun, scp->ioaddr, scp->altioaddr, scp->bmaddr); 7245095Ssos#endif 7345095Ssos 7452067Ssos /* if simplex controller, only allow DMA on primary channel */ 7552067Ssos if (scp->unit == 1) { 7652067Ssos outb(scp->bmaddr + ATA_BMSTAT_PORT, inb(scp->bmaddr + ATA_BMSTAT_PORT) & 7752067Ssos (ATA_BMSTAT_DMA_MASTER | ATA_BMSTAT_DMA_SLAVE)); 7852067Ssos if (inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_DMA_SIMPLEX) { 7952067Ssos printf("ata%d: simplex device, DMA on primary channel only\n", 8052067Ssos scp->lun); 8152067Ssos return -1; 8252067Ssos } 8352067Ssos } 8452067Ssos 8545095Ssos if (!(dmatab = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT))) 8651520Ssos return -1; 8745095Ssos 8845798Ssos if (((uintptr_t)dmatab >> PAGE_SHIFT) ^ 8945798Ssos (((uintptr_t)dmatab + PAGE_SIZE - 1) >> PAGE_SHIFT)) { 9051520Ssos printf("ata_dmainit: dmatab crosses page boundary, no DMA\n"); 9151520Ssos free(dmatab, M_DEVBUF); 9251520Ssos return -1; 9345095Ssos } 9451520Ssos scp->dmatab[(device == ATA_MASTER) ? 0 : 1] = dmatab; 9545095Ssos 9651520Ssos switch (type = pci_get_devid(scp->dev)) { 9745095Ssos 9845095Ssos case 0x71118086: /* Intel PIIX4 */ 9945095Ssos if (udmamode >= 2) { 10051520Ssos int32_t mask48, new48; 10145095Ssos 10245095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 10352918Ssos ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 10451520Ssos if (bootverbose) 10551520Ssos printf("ata%d: %s: %s setting up UDMA2 mode on PIIX4 chip\n", 10651520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 10751520Ssos (error) ? "failed" : "success"); 10851520Ssos if (error) 10945095Ssos break; 11051520Ssos devno = (scp->unit << 1) + ((device == ATA_MASTER) ? 0 : 1); 11145095Ssos mask48 = (1 << devno) + (3 << (16 + (devno << 2))); 11245095Ssos new48 = (1 << devno) + (2 << (16 + (devno << 2))); 11351520Ssos pci_write_config(scp->dev, 0x48, 11445798Ssos (pci_read_config(scp->dev, 0x48, 4) & 11552067Ssos ~mask48) | new48, 4); 11652067Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2; 11745095Ssos return 0; 11845095Ssos } 11945095Ssos /* FALLTHROUGH */ 12045095Ssos 12145095Ssos case 0x70108086: /* Intel PIIX3 */ 12245095Ssos if (wdmamode >= 2 && apiomode >= 4) { 12345095Ssos int32_t mask40, new40, mask44, new44; 12445095Ssos 12545095Ssos /* if SITRE not set doit for both channels */ 12645798Ssos if (!((pci_read_config(scp->dev, 0x40, 4)>>(scp->unit<<8))&0x4000)){ 12751520Ssos new40 = pci_read_config(scp->dev, 0x40, 4); 12851520Ssos new44 = pci_read_config(scp->dev, 0x44, 4); 12951520Ssos if (!(new40 & 0x00004000)) { 13051520Ssos new44 &= ~0x0000000f; 13151520Ssos new44 |= ((new40&0x00003000)>>10)|((new40&0x00000300)>>8); 13251520Ssos } 13351520Ssos if (!(new40 & 0x40000000)) { 13451520Ssos new44 &= ~0x000000f0; 13551520Ssos new44 |= ((new40&0x30000000)>>22)|((new40&0x03000000)>>20); 13651520Ssos } 13751520Ssos new40 |= 0x40004000; 13851520Ssos pci_write_config(scp->dev, 0x40, new40, 4); 13951520Ssos pci_write_config(scp->dev, 0x44, new44, 4); 14045095Ssos } 14145095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 14252918Ssos ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 14351520Ssos if (bootverbose) 14451520Ssos printf("ata%d: %s: %s setting up WDMA2 mode on PIIX4 chip\n", 14551520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 14651520Ssos (error) ? "failed" : "success"); 14751520Ssos if (error) 14845095Ssos break; 14951520Ssos if (device == ATA_MASTER) { 15051520Ssos mask40 = 0x0000330f; 15151520Ssos new40 = 0x00002307; 15251520Ssos mask44 = 0; 15351520Ssos new44 = 0; 15451520Ssos } else { 15551520Ssos mask40 = 0x000000f0; 15651520Ssos new40 = 0x00000070; 15751520Ssos mask44 = 0x0000000f; 15851520Ssos new44 = 0x0000000b; 15945095Ssos } 16051520Ssos if (scp->unit) { 16151520Ssos mask40 <<= 16; 16251520Ssos new40 <<= 16; 16351520Ssos mask44 <<= 4; 16451520Ssos new44 <<= 4; 16551520Ssos } 16651520Ssos pci_write_config(scp->dev, 0x40, 16751520Ssos (pci_read_config(scp->dev, 0x40, 4) & ~mask40) | 16851520Ssos new40, 4); 16951520Ssos pci_write_config(scp->dev, 0x44, 17051520Ssos (pci_read_config(scp->dev, 0x44, 4) & ~mask44) | 17151520Ssos new44, 4); 17252067Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; 17345095Ssos return 0; 17451520Ssos } 17545095Ssos break; 17645095Ssos 17745095Ssos case 0x12308086: /* Intel PIIX */ 17845095Ssos /* probably not worth the trouble */ 17945095Ssos break; 18045095Ssos 18152067Ssos case 0x522910b9: /* AcerLabs Aladdin IV/V */ 18252067Ssos /* the Aladdin has to be setup specially for ATAPI devices */ 18349614Ssos if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) || 18452067Ssos (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) { 18552067Ssos int8_t word53 = pci_read_config(scp->dev, 0x53, 1); 18649614Ssos 18752067Ssos /* set atapi fifo, this should always work */ 18852067Ssos pci_write_config(scp->dev, 0x53, (word53 & ~0x01) | 0x02, 1); 18952067Ssos 19052067Ssos /* if both master & slave are atapi devices dont allow DMA */ 19152067Ssos if (scp->devices & ATA_ATAPI_MASTER && 19252067Ssos scp->devices & ATA_ATAPI_SLAVE) { 19352067Ssos printf("ata%d: Aladdin: two atapi devices on this channel, " 19452067Ssos "DMA disabled\n", scp->lun); 19552067Ssos break; 19652067Ssos } 19752067Ssos /* if needed set atapi fifo & dma */ 19852067Ssos if ((udmamode >=2) || (wdmamode >= 2 && apiomode >= 4)) { 19952067Ssos pci_write_config(scp->dev, 0x53, word53 | 0x03, 1); 20052067Ssos scp->flags |= ATA_ATAPI_DMA_RO; 20152067Ssos if (device == ATA_MASTER) 20252067Ssos outb(scp->bmaddr + ATA_BMSTAT_PORT, 20352067Ssos inb(scp->bmaddr + ATA_BMSTAT_PORT) | 20452067Ssos ATA_BMSTAT_DMA_MASTER); 20552067Ssos else 20652067Ssos outb(scp->bmaddr + ATA_BMSTAT_PORT, 20752067Ssos inb(scp->bmaddr + ATA_BMSTAT_PORT) | 20852067Ssos ATA_BMSTAT_DMA_SLAVE); 20952067Ssos } 21052067Ssos } 21152067Ssos if (udmamode >=2) { 21252067Ssos int32_t word54 = pci_read_config(scp->dev, 0x54, 4); 21352067Ssos 21451520Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 21552918Ssos ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 21651520Ssos if (bootverbose) 21752067Ssos printf("ata%d: %s: %s setting up UDMA2 mode on Aladdin chip\n", 21851520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 21951520Ssos (error) ? "failed" : "success"); 22051520Ssos if (error) 22151520Ssos break; 22252067Ssos word54 |= 0x5555; 22352067Ssos word54 |= (0x0a << (16 + (scp->unit << 3) + (device << 2))); 22452067Ssos pci_write_config(scp->dev, 0x54, word54, 4); 22552067Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2; 22651520Ssos return 0; 22752067Ssos 22851520Ssos } 22952067Ssos else if (wdmamode >= 2 && apiomode >= 4) { 23052067Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 23152918Ssos ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 23252067Ssos if (bootverbose) 23352067Ssos printf("ata%d: %s: %s setting up WDMA2 mode on Aladdin chip\n", 23452067Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 23552067Ssos (error) ? "failed" : "success"); 23652067Ssos if (error) 23752067Ssos break; 23852067Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; 23952067Ssos return 0; 24052067Ssos } 24152067Ssos break; 24252067Ssos 24352067Ssos case 0x4d33105a: /* Promise Ultra33 / FastTrak33 controllers */ 24452067Ssos case 0x4d38105a: /* Promise Ultra66 / FastTrak66 controllers */ 24552067Ssos /* the Promise can only do DMA on ATA disks not on ATAPI devices */ 24652067Ssos if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) || 24752067Ssos (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) 24852067Ssos break; 24952067Ssos 25052067Ssos devno = (scp->unit << 1) + ((device == ATA_MASTER) ? 0 : 1); 25152918Ssos if (udmamode >=4 && type == 0x4d38105a && 25252918Ssos !(pci_read_config(scp->dev, 0x50, 2)&(scp->unit ? 1<<11 : 1<<10))) { 25352918Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 25452918Ssos ATA_UDMA4, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 25552918Ssos if (bootverbose) 25652918Ssos printf("ata%d: %s: %s setting up UDMA4 mode on Promise chip\n", 25752918Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 25852918Ssos (error) ? "failed" : "success"); 25952918Ssos if (error) 26052918Ssos break; 26152918Ssos outb(scp->bmaddr + 0x11, inl(scp->bmaddr + 0x11) | scp->unit ? 8:2); 26252918Ssos pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004127f3, 4); 26352918Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA4; 26452918Ssos return 0; 26552918Ssos } 26645095Ssos if (udmamode >=2) { 26745095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 26852918Ssos ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 26951520Ssos if (bootverbose) 27051520Ssos printf("ata%d: %s: %s setting up UDMA2 mode on Promise chip\n", 27151520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 27251520Ssos (error) ? "failed" : "success"); 27351520Ssos if (error) 27445095Ssos break; 27545798Ssos pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004127f3, 4); 27652067Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2; 27745116Ssos return 0; 27845095Ssos } 27945095Ssos else if (wdmamode >= 2 && apiomode >= 4) { 28045095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 28152918Ssos ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 28251520Ssos if (bootverbose) 28351520Ssos printf("ata%d: %s: %s setting up WDMA2 mode on Promise chip\n", 28451520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 28551520Ssos (error) ? "failed" : "success"); 28651520Ssos if (error) 28745095Ssos break; 28845798Ssos pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004367f3, 4); 28952067Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; 29045116Ssos return 0; 29151520Ssos } 29245095Ssos else { 29351520Ssos if (bootverbose) 29451520Ssos printf("ata%d: %s: setting PIO mode on Promise chip\n", 29551520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave"); 29645798Ssos pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004fe924, 4); 29745095Ssos } 29845095Ssos break; 29945095Ssos 30052067Ssos case 0x00041103: /* HighPoint HPT366 IDE controller */ 30152067Ssos /* punt on ATAPI devices for now */ 30251520Ssos if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) || 30352067Ssos (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) 30452067Ssos break; 30551520Ssos 30652067Ssos devno = (device == ATA_MASTER) ? 0 : 1; 30752067Ssos if (udmamode >=4 && !(pci_read_config(scp->dev, 0x5a, 1) & 0x2)) { 30852067Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 30952918Ssos ATA_UDMA4, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 31052067Ssos if (bootverbose) 31152067Ssos printf("ata%d: %s: %s setting up UDMA4 mode on HPT366 chip\n", 31252067Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 31352067Ssos (error) ? "failed" : "success"); 31452067Ssos if (error) 31552067Ssos break; 31652067Ssos hpt366_timing(scp, device, ATA_MODE_UDMA4); 31752067Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA4; 31852067Ssos return 0; 31951520Ssos } 32052918Ssos if (udmamode >=3 && !(pci_read_config(scp->dev, 0x5a, 1) & 0x2)) { 32145095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 32252918Ssos ATA_UDMA3, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 32352067Ssos if (bootverbose) 32452067Ssos printf("ata%d: %s: %s setting up UDMA3 mode on HPT366 chip\n", 32552067Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 32652067Ssos (error) ? "failed" : "success"); 32752067Ssos if (error) 32852067Ssos break; 32952067Ssos hpt366_timing(scp, device, ATA_MODE_UDMA3); 33052067Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA3; 33152067Ssos return 0; 33252067Ssos } 33352918Ssos if (udmamode >=2) { 33452067Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 33552918Ssos ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 33651520Ssos if (bootverbose) 33752067Ssos printf("ata%d: %s: %s setting up UDMA2 mode on HPT366 chip\n", 33851520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 33951520Ssos (error) ? "failed" : "success"); 34051520Ssos if (error) 34145095Ssos break; 34252067Ssos hpt366_timing(scp, device, ATA_MODE_UDMA2); 34352067Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2; 34445095Ssos return 0; 34545095Ssos } 34645095Ssos else if (wdmamode >= 2 && apiomode >= 4) { 34745095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 34852918Ssos ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 34951520Ssos if (bootverbose) 35052067Ssos printf("ata%d: %s: %s setting up WDMA2 mode on HPT366 chip\n", 35151520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 35251520Ssos (error) ? "failed" : "success"); 35351520Ssos if (error) 35445095Ssos break; 35552067Ssos hpt366_timing(scp, device, ATA_MODE_WDMA2); 35652067Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; 35745095Ssos return 0; 35845095Ssos } 35952067Ssos else { 36052067Ssos if (bootverbose) 36152067Ssos printf("ata%d: %s: setting PIO mode on HPT366 chip\n", 36252067Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave"); 36352067Ssos hpt366_timing(scp, device, ATA_MODE_PIO); 36452067Ssos } 36545095Ssos break; 36645095Ssos 36751548Ssos default: /* unknown controller chip */ 36851548Ssos /* better not try generic DMA on ATAPI devices it almost never works */ 36951548Ssos if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) || 37051548Ssos (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) 37151548Ssos break; 37251548Ssos 37351548Ssos /* well, we have no support for this, but try anyways */ 37451520Ssos if (((wdmamode >= 2 && apiomode >= 4) || udmamode >= 2) && 37551520Ssos (inb(scp->bmaddr + ATA_BMSTAT_PORT) & 37651520Ssos ((device == ATA_MASTER) ? 37751520Ssos ATA_BMSTAT_DMA_SLAVE : ATA_BMSTAT_DMA_MASTER))) { 37845095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 37952918Ssos ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_READY); 38051520Ssos if (bootverbose) 38151520Ssos printf("ata%d: %s: %s setting up WDMA2 mode on generic chip\n", 38251520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 38351520Ssos (error) ? "failed" : "success"); 38451520Ssos if (error) 38545095Ssos break; 38652067Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; 38745095Ssos return 0; 38845095Ssos } 38945095Ssos } 39045095Ssos free(dmatab, M_DEVBUF); 39145095Ssos return -1; 39245095Ssos} 39345095Ssos 39445095Ssosint32_t 39545095Ssosata_dmasetup(struct ata_softc *scp, int32_t device, 39645095Ssos int8_t *data, int32_t count, int32_t flags) 39745095Ssos{ 39845095Ssos struct ata_dmaentry *dmatab; 39945095Ssos u_int32_t dma_count, dma_base; 40045095Ssos int32_t i = 0; 40145095Ssos 40251520Ssos#ifdef ATA_DMADEBUG 40345095Ssos printf("ata%d: dmasetup\n", scp->lun); 40445095Ssos#endif 40545720Speter if (((uintptr_t)data & 1) || (count & 1)) 40645095Ssos return -1; 40745095Ssos 40845095Ssos if (!count) { 40951520Ssos#ifdef ATA_DMADEBUG 41045095Ssos printf("ata%d: zero length DMA transfer attempt on %s\n", 41151520Ssos scp->lun, ((device == ATA_MASTER) ? "master" : "slave")); 41251520Ssos#endif 41345095Ssos return -1; 41445095Ssos } 41545095Ssos 41651520Ssos dmatab = scp->dmatab[(device == ATA_MASTER) ? 0 : 1]; 41745095Ssos dma_base = vtophys(data); 41845720Speter dma_count = MIN(count, (PAGE_SIZE - ((uintptr_t)data & PAGE_MASK))); 41945095Ssos data += dma_count; 42045095Ssos count -= dma_count; 42145095Ssos 42245095Ssos while (count) { 42345095Ssos dmatab[i].base = dma_base; 42445095Ssos dmatab[i].count = (dma_count & 0xffff); 42545095Ssos i++; 42645095Ssos if (i >= ATA_DMA_ENTRIES) { 42745095Ssos printf("ata%d: too many segments in DMA table for %s\n", 42845095Ssos scp->lun, (device ? "slave" : "master")); 42945095Ssos return -1; 43045095Ssos } 43145095Ssos dma_base = vtophys(data); 43245095Ssos dma_count = MIN(count, PAGE_SIZE); 43345095Ssos data += MIN(count, PAGE_SIZE); 43445095Ssos count -= MIN(count, PAGE_SIZE); 43545095Ssos } 43651520Ssos#ifdef ATA_DMADEBUG 43751520Ssos printf("ata_dmasetup: base=%08x count%08x\n", dma_base, dma_count); 43845095Ssos#endif 43945095Ssos dmatab[i].base = dma_base; 44045095Ssos dmatab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT; 44145095Ssos 44245095Ssos outl(scp->bmaddr + ATA_BMDTP_PORT, vtophys(dmatab)); 44351520Ssos#ifdef ATA_DMADEBUG 44451520Ssos printf("dmatab=%08x %08x\n", 44551520Ssos vtophys(dmatab), inl(scp->bmaddr+ATA_BMDTP_PORT)); 44645095Ssos#endif 44745095Ssos outb(scp->bmaddr + ATA_BMCMD_PORT, flags ? ATA_BMCMD_WRITE_READ:0); 44845095Ssos outb(scp->bmaddr + ATA_BMSTAT_PORT, (inb(scp->bmaddr + ATA_BMSTAT_PORT) | 44945095Ssos (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); 45045095Ssos return 0; 45145095Ssos} 45245095Ssos 45345095Ssosvoid 45452067Ssosata_dmastart(struct ata_softc *scp) 45545095Ssos{ 45651520Ssos#ifdef ATA_DMADEBUG 45745095Ssos printf("ata%d: dmastart\n", scp->lun); 45845095Ssos#endif 45952067Ssos scp->flags |= ATA_DMA_ACTIVE; 46045095Ssos outb(scp->bmaddr + ATA_BMCMD_PORT, 46145095Ssos inb(scp->bmaddr + ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP); 46245095Ssos} 46345095Ssos 46445095Ssosint32_t 46552067Ssosata_dmadone(struct ata_softc *scp) 46645095Ssos{ 46751520Ssos#ifdef ATA_DMADEBUG 46845095Ssos printf("ata%d: dmadone\n", scp->lun); 46945095Ssos#endif 47045095Ssos outb(scp->bmaddr + ATA_BMCMD_PORT, 47145095Ssos inb(scp->bmaddr + ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); 47252067Ssos scp->flags &= ~ATA_DMA_ACTIVE; 47345095Ssos return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 47445095Ssos} 47545095Ssos 47645095Ssosint32_t 47752067Ssosata_dmastatus(struct ata_softc *scp) 47845095Ssos{ 47951520Ssos#ifdef ATA_DMADEBUG 48045095Ssos printf("ata%d: dmastatus\n", scp->lun); 48145095Ssos#endif 48245095Ssos return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 48345095Ssos} 48445095Ssos 48552067Ssosstatic void 48652067Ssoshpt366_timing(struct ata_softc *scp, int32_t device, int32_t mode) 48752067Ssos{ 48852067Ssos u_int32_t timing; 48952067Ssos 49052067Ssos switch (pci_read_config(scp->dev, (device == ATA_MASTER) ? 0x41 : 0x45, 1)){ 49152067Ssos case 0x85: /* 25Mhz */ 49252067Ssos switch (mode) { 49352067Ssos case ATA_MODE_PIO: timing = 0xc0ca8521; break; 49452067Ssos case ATA_MODE_WDMA2: timing = 0xa0ca8521; break; 49552067Ssos case ATA_MODE_UDMA2: 49652067Ssos case ATA_MODE_UDMA3: timing = 0x90cf8521; break; 49752067Ssos case ATA_MODE_UDMA4: timing = 0x90c98521; break; 49852067Ssos default: timing = 0x01208585; 49952067Ssos } 50052067Ssos break; 50152067Ssos default: 50252067Ssos case 0xa7: /* 33MHz */ 50352067Ssos switch (mode) { 50452067Ssos case ATA_MODE_PIO: timing = 0xc0c8a731; break; 50552067Ssos case ATA_MODE_WDMA2: timing = 0xa0c8a731; break; 50652067Ssos case ATA_MODE_UDMA2: timing = 0x90caa731; break; 50752067Ssos case ATA_MODE_UDMA3: timing = 0x90cfa731; break; 50852067Ssos case ATA_MODE_UDMA4: timing = 0x90c9a731; break; 50952067Ssos default: timing = 0x0120a7a7; 51052067Ssos } 51152067Ssos break; 51252067Ssos case 0xd9: /* 40Mhz */ 51352067Ssos switch (mode) { 51452067Ssos case ATA_MODE_PIO: timing = 0xc008d963; break; 51552067Ssos case ATA_MODE_WDMA2: timing = 0xa008d943; break; 51652067Ssos case ATA_MODE_UDMA2: timing = 0x900bd943; break; 51752067Ssos case ATA_MODE_UDMA3: timing = 0x900ad943; break; 51852067Ssos case ATA_MODE_UDMA4: timing = 0x900fd943; break; 51952067Ssos default: timing = 0x0120d9d9; 52052067Ssos } 52152067Ssos } 52252067Ssos pci_write_config(scp->dev, 0x40 + (device==ATA_MASTER ? 0 : 4), timing, 4); 52352067Ssos} 52452067Ssos 52545095Ssos#else /* NPCI > 0 */ 52645095Ssos 52745095Ssosint32_t 52845095Ssosata_dmainit(struct ata_softc *scp, int32_t device, 52951520Ssos int32_t piomode, int32_t wdmamode, int32_t udmamode) 53045095Ssos{ 53145095Ssos return -1; 53245095Ssos} 53345095Ssos 53445095Ssosint32_t 53545095Ssosata_dmasetup(struct ata_softc *scp, int32_t device, 53651520Ssos int8_t *data, int32_t count, int32_t flags) 53745095Ssos{ 53845095Ssos return -1; 53945095Ssos} 54045095Ssos 54145095Ssosvoid 54252067Ssosata_dmastart(struct ata_softc *scp) 54345095Ssos{ 54445095Ssos} 54545095Ssos 54645095Ssosint32_t 54752067Ssosata_dmadone(struct ata_softc *scp) 54845095Ssos{ 54945095Ssos return -1; 55045095Ssos} 55145095Ssos 55245095Ssosint32_t 55352067Ssosata_dmastatus(struct ata_softc *scp) 55445095Ssos{ 55545095Ssos return -1; 55645095Ssos} 55745095Ssos 55845095Ssos#endif /* NPCI > 0 */ 559