ata-dma.c revision 53681
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 53681 1999-11-24 21:40:05Z 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, 10353029Ssos ATA_UDMA2, ATA_C_F_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"); 10853681Ssos if (!error) { 10953681Ssos devno = (scp->unit << 1) + ((device == ATA_MASTER) ? 0 : 1); 11053681Ssos mask48 = (1 << devno) + (3 << (16 + (devno << 2))); 11153681Ssos new48 = (1 << devno) + (2 << (16 + (devno << 2))); 11253681Ssos pci_write_config(scp->dev, 0x48, 11353681Ssos (pci_read_config(scp->dev, 0x48, 4) & 11453681Ssos ~mask48) | new48, 4); 11553681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2; 11653681Ssos return 0; 11753681Ssos } 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, 14253029Ssos ATA_WDMA2, ATA_C_F_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"); 14753681Ssos if (!error) { 14853681Ssos if (device == ATA_MASTER) { 14953681Ssos mask40 = 0x0000330f; 15053681Ssos new40 = 0x00002307; 15153681Ssos mask44 = 0; 15253681Ssos new44 = 0; 15353681Ssos } 15453681Ssos else { 15553681Ssos mask40 = 0x000000f0; 15653681Ssos new40 = 0x00000070; 15753681Ssos mask44 = 0x0000000f; 15853681Ssos new44 = 0x0000000b; 15953681Ssos } 16053681Ssos if (scp->unit) { 16153681Ssos mask40 <<= 16; 16253681Ssos new40 <<= 16; 16353681Ssos mask44 <<= 4; 16453681Ssos new44 <<= 4; 16553681Ssos } 16653681Ssos pci_write_config(scp->dev, 0x40, 16753681Ssos (pci_read_config(scp->dev, 0x40, 4) & ~mask40)| 16853681Ssos new40, 4); 16953681Ssos pci_write_config(scp->dev, 0x44, 17053681Ssos (pci_read_config(scp->dev, 0x44, 4) & ~mask44)| 17153681Ssos new44, 4); 17253681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; 17353681Ssos return 0; 17445095Ssos } 17551520Ssos } 17653681Ssos /* we could set PIO mode timings, but we assume the BIOS did that */ 17745095Ssos break; 17845095Ssos 17945095Ssos case 0x12308086: /* Intel PIIX */ 18045095Ssos /* probably not worth the trouble */ 18145095Ssos break; 18245095Ssos 18352067Ssos case 0x522910b9: /* AcerLabs Aladdin IV/V */ 18453029Ssos /* the Aladdin doesn't support ATAPI DMA on both master & slave */ 18553029Ssos if (scp->devices & ATA_ATAPI_MASTER && scp->devices & ATA_ATAPI_SLAVE) { 18653029Ssos printf("ata%d: Aladdin: two atapi devices on this channel, " 18753029Ssos "DMA disabled\n", scp->lun); 18853029Ssos break; 18952067Ssos } 19053681Ssos if (udmamode >= 2) { 19152067Ssos int32_t word54 = pci_read_config(scp->dev, 0x54, 4); 19252067Ssos 19351520Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 19453029Ssos ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 19551520Ssos if (bootverbose) 19652067Ssos printf("ata%d: %s: %s setting up UDMA2 mode on Aladdin chip\n", 19751520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 19851520Ssos (error) ? "failed" : "success"); 19953681Ssos if (!error) { 20053681Ssos word54 |= 0x5555; 20153681Ssos word54 |= (0x0a << (16 + (scp->unit << 3) + (device << 2))); 20253681Ssos pci_write_config(scp->dev, 0x54, word54, 4); 20353681Ssos pci_write_config(scp->dev, 0x53, 20453681Ssos pci_read_config(scp->dev, 0x53, 1) | 0x03, 1); 20553681Ssos scp->flags |= ATA_ATAPI_DMA_RO; 20653681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2; 20753681Ssos return 0; 20853681Ssos } 20951520Ssos } 21053681Ssos if (wdmamode >= 2 && apiomode >= 4) { 21152067Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 21253029Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 21352067Ssos if (bootverbose) 21452067Ssos printf("ata%d: %s: %s setting up WDMA2 mode on Aladdin chip\n", 21552067Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 21652067Ssos (error) ? "failed" : "success"); 21753681Ssos if (!error) { 21853681Ssos pci_write_config(scp->dev, 0x53, 21953681Ssos pci_read_config(scp->dev, 0x53, 1) | 0x03, 1); 22053681Ssos scp->flags |= ATA_ATAPI_DMA_RO; 22153681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; 22253681Ssos return 0; 22353681Ssos } 22452067Ssos } 22553681Ssos /* we could set PIO mode timings, but we assume the BIOS did that */ 22652067Ssos break; 22752067Ssos 22853681Ssos case 0x05711106: /* VIA Apollo 82c586 / 82c686 */ 22953681Ssos devno = (scp->unit << 1) + ((device == ATA_MASTER) ? 0 : 1); 23053681Ssos if (udmamode >= 2 && pci_read_config(scp->dev, 0x0d, 1) >= 0x20) { 23153681Ssos int8_t byte = pci_read_config(scp->dev, 0x53 - devno, 1); 23253681Ssos 23353681Ssos /* enable UDMA transfer modes setting by SETFEATURES cmd */ 23453681Ssos pci_write_config(scp->dev, 0x53 - devno, (byte & 0x1c) | 0x40, 1); 23553681Ssos 23653681Ssos if (udmamode >= 4) { 23753681Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 23853681Ssos ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); 23953681Ssos if (bootverbose) 24053681Ssos printf("ata%d: %s: %s setting up UDMA4 mode on VIA chip\n", 24153681Ssos scp->lun, (device == ATA_MASTER) ? "master":"slave", 24253681Ssos (error) ? "failed" : "success"); 24353681Ssos if (!error) { 24453681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA4; 24553681Ssos return 0; 24653681Ssos } 24753681Ssos } 24853681Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 24953681Ssos ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 25053681Ssos if (bootverbose) 25153681Ssos printf("ata%d: %s: %s setting up UDMA2 mode on VIA chip\n", 25253681Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 25353681Ssos (error) ? "failed" : "success"); 25453681Ssos if (!error) { 25553681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2; 25653681Ssos return 0; 25753681Ssos } 25853681Ssos pci_write_config(scp->dev, 0x53 - devno, byte, 1); 25953681Ssos } 26053681Ssos if (wdmamode >= 2 && apiomode >= 4) { 26153681Ssos int8_t byte; 26253681Ssos 26353681Ssos /* set prefetch, postwrite */ 26453681Ssos byte = pci_read_config(scp->dev, 0x41, 1); 26553681Ssos pci_write_config(scp->dev, 0x41, byte | 0xf0, 1); 26653681Ssos 26753681Ssos /* set fifo configuration half'n'half */ 26853681Ssos byte = pci_read_config(scp->dev, 0x43, 1); 26953681Ssos pci_write_config(scp->dev, 0x43, (byte & 0x90) | 0x2a, 1); 27053681Ssos 27153681Ssos /* set status register read retry */ 27253681Ssos byte = pci_read_config(scp->dev, 0x44, 1); 27353681Ssos pci_write_config(scp->dev, 0x44, byte | 0x08, 1); 27453681Ssos 27553681Ssos /* set DMA read & end-of-sector fifo flush */ 27653681Ssos byte = pci_read_config(scp->dev, 0x46, 1); 27753681Ssos pci_write_config(scp->dev, 0x46, (byte & 0x0c) | 0xf0, 1); 27853681Ssos 27953681Ssos /* set WDMA2 mode timing */ 28053681Ssos pci_write_config(scp->dev, 0x4b - devno, 0x31 , 1); 28153681Ssos 28253681Ssos /* set sector size */ 28353681Ssos pci_write_config(scp->dev, scp->unit ? 0x68 : 0x60, DEV_BSIZE, 2); 28453681Ssos 28553681Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 28653681Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 28753681Ssos if (bootverbose) 28853681Ssos printf("ata%d: %s: %s setting up WDMA2 mode on VIA chip\n", 28953681Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 29053681Ssos (error) ? "failed" : "success"); 29153681Ssos if (!error) { 29253681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; 29353681Ssos return 0; 29453681Ssos } 29553681Ssos } 29653681Ssos /* we could set PIO mode timings, but we assume the BIOS did that */ 29753681Ssos break; 29853681Ssos 29952067Ssos case 0x4d33105a: /* Promise Ultra33 / FastTrak33 controllers */ 30052067Ssos case 0x4d38105a: /* Promise Ultra66 / FastTrak66 controllers */ 30152067Ssos /* the Promise can only do DMA on ATA disks not on ATAPI devices */ 30252067Ssos if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) || 30352067Ssos (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) 30452067Ssos break; 30552067Ssos 30652067Ssos devno = (scp->unit << 1) + ((device == ATA_MASTER) ? 0 : 1); 30752918Ssos if (udmamode >=4 && type == 0x4d38105a && 30852918Ssos !(pci_read_config(scp->dev, 0x50, 2)&(scp->unit ? 1<<11 : 1<<10))) { 30952918Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 31053029Ssos ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); 31152918Ssos if (bootverbose) 31252918Ssos printf("ata%d: %s: %s setting up UDMA4 mode on Promise chip\n", 31352918Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 31452918Ssos (error) ? "failed" : "success"); 31553681Ssos if (!error) { 31653681Ssos outb(scp->bmaddr+0x11, inl(scp->bmaddr+0x11) | scp->unit ? 8:2); 31753681Ssos pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004127f3, 4); 31853681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA4; 31953681Ssos return 0; 32053681Ssos } 32152918Ssos } 32253681Ssos if (udmamode >= 2) { 32345095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 32453029Ssos ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 32551520Ssos if (bootverbose) 32651520Ssos printf("ata%d: %s: %s setting up UDMA2 mode on Promise chip\n", 32751520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 32851520Ssos (error) ? "failed" : "success"); 32953681Ssos if (!error) { 33053681Ssos pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004127f3, 4); 33153681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2; 33253681Ssos return 0; 33353681Ssos } 33445095Ssos } 33553681Ssos if (wdmamode >= 2 && apiomode >= 4) { 33645095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 33753029Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 33851520Ssos if (bootverbose) 33951520Ssos printf("ata%d: %s: %s setting up WDMA2 mode on Promise chip\n", 34051520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 34151520Ssos (error) ? "failed" : "success"); 34253681Ssos if (!error) { 34353681Ssos pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004367f3, 4); 34453681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; 34553681Ssos return 0; 34653681Ssos } 34751520Ssos } 34853681Ssos if (bootverbose) 34953681Ssos printf("ata%d: %s: setting PIO mode on Promise chip\n", 35053681Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave"); 35153681Ssos pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004fe924, 4); 35245095Ssos break; 35345095Ssos 35452067Ssos case 0x00041103: /* HighPoint HPT366 IDE controller */ 35553681Ssos /* no ATAPI devices for now */ 35651520Ssos if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) || 35752067Ssos (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) 35852067Ssos break; 35951520Ssos 36052067Ssos devno = (device == ATA_MASTER) ? 0 : 1; 36152067Ssos if (udmamode >=4 && !(pci_read_config(scp->dev, 0x5a, 1) & 0x2)) { 36252067Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 36353029Ssos ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); 36452067Ssos if (bootverbose) 36552067Ssos printf("ata%d: %s: %s setting up UDMA4 mode on HPT366 chip\n", 36652067Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 36752067Ssos (error) ? "failed" : "success"); 36853681Ssos if (!error) { 36953681Ssos hpt366_timing(scp, device, ATA_MODE_UDMA4); 37053681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA4; 37153681Ssos return 0; 37253681Ssos } 37351520Ssos } 37452918Ssos if (udmamode >=3 && !(pci_read_config(scp->dev, 0x5a, 1) & 0x2)) { 37545095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 37653029Ssos ATA_UDMA3, ATA_C_F_SETXFER, ATA_WAIT_READY); 37752067Ssos if (bootverbose) 37852067Ssos printf("ata%d: %s: %s setting up UDMA3 mode on HPT366 chip\n", 37952067Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 38052067Ssos (error) ? "failed" : "success"); 38153681Ssos if (!error) { 38253681Ssos hpt366_timing(scp, device, ATA_MODE_UDMA3); 38353681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA3; 38453681Ssos return 0; 38553681Ssos } 38652067Ssos } 38753681Ssos if (udmamode >= 2) { 38852067Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 38953029Ssos ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 39051520Ssos if (bootverbose) 39152067Ssos printf("ata%d: %s: %s setting up UDMA2 mode on HPT366 chip\n", 39251520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 39351520Ssos (error) ? "failed" : "success"); 39453681Ssos if (!error) { 39553681Ssos hpt366_timing(scp, device, ATA_MODE_UDMA2); 39653681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2; 39753681Ssos return 0; 39853681Ssos } 39945095Ssos } 40053681Ssos if (wdmamode >= 2 && apiomode >= 4) { 40145095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 40253029Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 40351520Ssos if (bootverbose) 40452067Ssos printf("ata%d: %s: %s setting up WDMA2 mode on HPT366 chip\n", 40551520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 40651520Ssos (error) ? "failed" : "success"); 40753681Ssos if (!error) { 40853681Ssos hpt366_timing(scp, device, ATA_MODE_WDMA2); 40953681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; 41053681Ssos return 0; 41153681Ssos } 41245095Ssos } 41353681Ssos if (bootverbose) 41453681Ssos printf("ata%d: %s: setting PIO mode on HPT366 chip\n", 41553681Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave"); 41653681Ssos hpt366_timing(scp, device, ATA_MODE_PIO); 41745095Ssos break; 41845095Ssos 41951548Ssos default: /* unknown controller chip */ 42051548Ssos /* better not try generic DMA on ATAPI devices it almost never works */ 42151548Ssos if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) || 42251548Ssos (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) 42351548Ssos break; 42451548Ssos 42551548Ssos /* well, we have no support for this, but try anyways */ 42651520Ssos if (((wdmamode >= 2 && apiomode >= 4) || udmamode >= 2) && 42751520Ssos (inb(scp->bmaddr + ATA_BMSTAT_PORT) & 42851520Ssos ((device == ATA_MASTER) ? 42951520Ssos ATA_BMSTAT_DMA_SLAVE : ATA_BMSTAT_DMA_MASTER))) { 43045095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 43153029Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 43251520Ssos if (bootverbose) 43351520Ssos printf("ata%d: %s: %s setting up WDMA2 mode on generic chip\n", 43451520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 43551520Ssos (error) ? "failed" : "success"); 43653681Ssos if (!error) { 43753681Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; 43853681Ssos return 0; 43953681Ssos } 44045095Ssos } 44145095Ssos } 44245095Ssos free(dmatab, M_DEVBUF); 44345095Ssos return -1; 44445095Ssos} 44545095Ssos 44645095Ssosint32_t 44745095Ssosata_dmasetup(struct ata_softc *scp, int32_t device, 44845095Ssos int8_t *data, int32_t count, int32_t flags) 44945095Ssos{ 45045095Ssos struct ata_dmaentry *dmatab; 45145095Ssos u_int32_t dma_count, dma_base; 45245095Ssos int32_t i = 0; 45345095Ssos 45451520Ssos#ifdef ATA_DMADEBUG 45545095Ssos printf("ata%d: dmasetup\n", scp->lun); 45645095Ssos#endif 45745720Speter if (((uintptr_t)data & 1) || (count & 1)) 45845095Ssos return -1; 45945095Ssos 46045095Ssos if (!count) { 46151520Ssos#ifdef ATA_DMADEBUG 46245095Ssos printf("ata%d: zero length DMA transfer attempt on %s\n", 46351520Ssos scp->lun, ((device == ATA_MASTER) ? "master" : "slave")); 46451520Ssos#endif 46545095Ssos return -1; 46645095Ssos } 46745095Ssos 46851520Ssos dmatab = scp->dmatab[(device == ATA_MASTER) ? 0 : 1]; 46945095Ssos dma_base = vtophys(data); 47045720Speter dma_count = MIN(count, (PAGE_SIZE - ((uintptr_t)data & PAGE_MASK))); 47145095Ssos data += dma_count; 47245095Ssos count -= dma_count; 47345095Ssos 47445095Ssos while (count) { 47545095Ssos dmatab[i].base = dma_base; 47645095Ssos dmatab[i].count = (dma_count & 0xffff); 47745095Ssos i++; 47845095Ssos if (i >= ATA_DMA_ENTRIES) { 47945095Ssos printf("ata%d: too many segments in DMA table for %s\n", 48045095Ssos scp->lun, (device ? "slave" : "master")); 48145095Ssos return -1; 48245095Ssos } 48345095Ssos dma_base = vtophys(data); 48445095Ssos dma_count = MIN(count, PAGE_SIZE); 48545095Ssos data += MIN(count, PAGE_SIZE); 48645095Ssos count -= MIN(count, PAGE_SIZE); 48745095Ssos } 48851520Ssos#ifdef ATA_DMADEBUG 48951520Ssos printf("ata_dmasetup: base=%08x count%08x\n", dma_base, dma_count); 49045095Ssos#endif 49145095Ssos dmatab[i].base = dma_base; 49245095Ssos dmatab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT; 49345095Ssos 49445095Ssos outl(scp->bmaddr + ATA_BMDTP_PORT, vtophys(dmatab)); 49551520Ssos#ifdef ATA_DMADEBUG 49651520Ssos printf("dmatab=%08x %08x\n", 49751520Ssos vtophys(dmatab), inl(scp->bmaddr+ATA_BMDTP_PORT)); 49845095Ssos#endif 49945095Ssos outb(scp->bmaddr + ATA_BMCMD_PORT, flags ? ATA_BMCMD_WRITE_READ:0); 50045095Ssos outb(scp->bmaddr + ATA_BMSTAT_PORT, (inb(scp->bmaddr + ATA_BMSTAT_PORT) | 50145095Ssos (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); 50245095Ssos return 0; 50345095Ssos} 50445095Ssos 50545095Ssosvoid 50652067Ssosata_dmastart(struct ata_softc *scp) 50745095Ssos{ 50851520Ssos#ifdef ATA_DMADEBUG 50945095Ssos printf("ata%d: dmastart\n", scp->lun); 51045095Ssos#endif 51152067Ssos scp->flags |= ATA_DMA_ACTIVE; 51245095Ssos outb(scp->bmaddr + ATA_BMCMD_PORT, 51345095Ssos inb(scp->bmaddr + ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP); 51445095Ssos} 51545095Ssos 51645095Ssosint32_t 51752067Ssosata_dmadone(struct ata_softc *scp) 51845095Ssos{ 51951520Ssos#ifdef ATA_DMADEBUG 52045095Ssos printf("ata%d: dmadone\n", scp->lun); 52145095Ssos#endif 52245095Ssos outb(scp->bmaddr + ATA_BMCMD_PORT, 52345095Ssos inb(scp->bmaddr + ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); 52452067Ssos scp->flags &= ~ATA_DMA_ACTIVE; 52545095Ssos return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 52645095Ssos} 52745095Ssos 52845095Ssosint32_t 52952067Ssosata_dmastatus(struct ata_softc *scp) 53045095Ssos{ 53151520Ssos#ifdef ATA_DMADEBUG 53245095Ssos printf("ata%d: dmastatus\n", scp->lun); 53345095Ssos#endif 53445095Ssos return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 53545095Ssos} 53645095Ssos 53752067Ssosstatic void 53852067Ssoshpt366_timing(struct ata_softc *scp, int32_t device, int32_t mode) 53952067Ssos{ 54052067Ssos u_int32_t timing; 54152067Ssos 54252067Ssos switch (pci_read_config(scp->dev, (device == ATA_MASTER) ? 0x41 : 0x45, 1)){ 54352067Ssos case 0x85: /* 25Mhz */ 54452067Ssos switch (mode) { 54552067Ssos case ATA_MODE_PIO: timing = 0xc0ca8521; break; 54652067Ssos case ATA_MODE_WDMA2: timing = 0xa0ca8521; break; 54752067Ssos case ATA_MODE_UDMA2: 54852067Ssos case ATA_MODE_UDMA3: timing = 0x90cf8521; break; 54952067Ssos case ATA_MODE_UDMA4: timing = 0x90c98521; break; 55052067Ssos default: timing = 0x01208585; 55152067Ssos } 55252067Ssos break; 55352067Ssos default: 55452067Ssos case 0xa7: /* 33MHz */ 55552067Ssos switch (mode) { 55652067Ssos case ATA_MODE_PIO: timing = 0xc0c8a731; break; 55752067Ssos case ATA_MODE_WDMA2: timing = 0xa0c8a731; break; 55852067Ssos case ATA_MODE_UDMA2: timing = 0x90caa731; break; 55952067Ssos case ATA_MODE_UDMA3: timing = 0x90cfa731; break; 56052067Ssos case ATA_MODE_UDMA4: timing = 0x90c9a731; break; 56152067Ssos default: timing = 0x0120a7a7; 56252067Ssos } 56352067Ssos break; 56452067Ssos case 0xd9: /* 40Mhz */ 56552067Ssos switch (mode) { 56652067Ssos case ATA_MODE_PIO: timing = 0xc008d963; break; 56752067Ssos case ATA_MODE_WDMA2: timing = 0xa008d943; break; 56852067Ssos case ATA_MODE_UDMA2: timing = 0x900bd943; break; 56952067Ssos case ATA_MODE_UDMA3: timing = 0x900ad943; break; 57052067Ssos case ATA_MODE_UDMA4: timing = 0x900fd943; break; 57152067Ssos default: timing = 0x0120d9d9; 57252067Ssos } 57352067Ssos } 57452067Ssos pci_write_config(scp->dev, 0x40 + (device==ATA_MASTER ? 0 : 4), timing, 4); 57552067Ssos} 57652067Ssos 57745095Ssos#else /* NPCI > 0 */ 57845095Ssos 57945095Ssosint32_t 58045095Ssosata_dmainit(struct ata_softc *scp, int32_t device, 58151520Ssos int32_t piomode, int32_t wdmamode, int32_t udmamode) 58245095Ssos{ 58345095Ssos return -1; 58445095Ssos} 58545095Ssos 58645095Ssosint32_t 58745095Ssosata_dmasetup(struct ata_softc *scp, int32_t device, 58851520Ssos int8_t *data, int32_t count, int32_t flags) 58945095Ssos{ 59045095Ssos return -1; 59145095Ssos} 59245095Ssos 59345095Ssosvoid 59452067Ssosata_dmastart(struct ata_softc *scp) 59545095Ssos{ 59645095Ssos} 59745095Ssos 59845095Ssosint32_t 59952067Ssosata_dmadone(struct ata_softc *scp) 60045095Ssos{ 60145095Ssos return -1; 60245095Ssos} 60345095Ssos 60445095Ssosint32_t 60552067Ssosata_dmastatus(struct ata_softc *scp) 60645095Ssos{ 60745095Ssos return -1; 60845095Ssos} 60945095Ssos 61045095Ssos#endif /* NPCI > 0 */ 611