ata-dma.c revision 55333
145095Ssos/*- 255333Ssos * Copyright (c) 1998,1999,2000 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 55333 2000-01-03 10:26:59Z 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> 3854270Ssos#include <sys/disk.h> 3954270Ssos#include <sys/devicestat.h> 4051520Ssos#include <vm/vm.h> 4145095Ssos#include <vm/pmap.h> 4247272Ssos#if NPCI > 0 4345095Ssos#include <pci/pcivar.h> 4447272Ssos#endif 4551520Ssos#if NAPM > 0 4651520Ssos#include <machine/apm_bios.h> 4751520Ssos#endif 4845095Ssos#include <dev/ata/ata-all.h> 4954270Ssos#include <dev/ata/ata-disk.h> 5045095Ssos 5152067Ssos/* prototypes */ 5255333Ssosstatic void promise_timing(struct ata_softc *, int32_t, int32_t); 5352067Ssosstatic void hpt366_timing(struct ata_softc *, int32_t, int32_t); 5452067Ssos 5552067Ssos/* misc defines */ 5652067Ssos#define MIN(a,b) ((a)>(b)?(b):(a)) 5745720Speter#ifdef __alpha__ 5845720Speter#undef vtophys 5951520Ssos#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va) 6045720Speter#endif 6145720Speter 6245150Ssos#if NPCI > 0 6345150Ssos 6445095Ssosint32_t 6545095Ssosata_dmainit(struct ata_softc *scp, int32_t device, 6645095Ssos int32_t apiomode, int32_t wdmamode, int32_t udmamode) 6745095Ssos{ 6854969Ssos int32_t devno = (scp->unit << 1) + ((device == ATA_MASTER) ? 0 : 1); 6955333Ssos int32_t error; 7045095Ssos void *dmatab; 7145095Ssos 7245095Ssos if (!scp->bmaddr) 7345095Ssos return -1; 7445095Ssos 7552067Ssos /* if simplex controller, only allow DMA on primary channel */ 7652067Ssos if (scp->unit == 1) { 7752067Ssos outb(scp->bmaddr + ATA_BMSTAT_PORT, inb(scp->bmaddr + ATA_BMSTAT_PORT) & 7852067Ssos (ATA_BMSTAT_DMA_MASTER | ATA_BMSTAT_DMA_SLAVE)); 7952067Ssos if (inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_DMA_SIMPLEX) { 8052067Ssos printf("ata%d: simplex device, DMA on primary channel only\n", 8152067Ssos scp->lun); 8252067Ssos return -1; 8352067Ssos } 8452067Ssos } 8552067Ssos 8645095Ssos if (!(dmatab = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT))) 8751520Ssos return -1; 8845095Ssos 8945798Ssos if (((uintptr_t)dmatab >> PAGE_SHIFT) ^ 9045798Ssos (((uintptr_t)dmatab + PAGE_SIZE - 1) >> PAGE_SHIFT)) { 9154969Ssos printf("ata%d-%s: dmatab crosses page boundary, no DMA\n", 9254969Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave"); 9351520Ssos free(dmatab, M_DEVBUF); 9451520Ssos return -1; 9545095Ssos } 9651520Ssos scp->dmatab[(device == ATA_MASTER) ? 0 : 1] = dmatab; 9745095Ssos 9855333Ssos switch (scp->chiptype) { 9945095Ssos 10045095Ssos case 0x71118086: /* Intel PIIX4 */ 10154969Ssos case 0x71998086: /* Intel PIIX4 */ 10245095Ssos if (udmamode >= 2) { 10351520Ssos int32_t mask48, new48; 10445095Ssos 10545095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 10653029Ssos ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 10751520Ssos if (bootverbose) 10854969Ssos printf("ata%d-%s: %s setting up UDMA2 mode on PIIX4 chip\n", 10951520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 11051520Ssos (error) ? "failed" : "success"); 11153681Ssos if (!error) { 11253681Ssos mask48 = (1 << devno) + (3 << (16 + (devno << 2))); 11353681Ssos new48 = (1 << devno) + (2 << (16 + (devno << 2))); 11453681Ssos pci_write_config(scp->dev, 0x48, 11553681Ssos (pci_read_config(scp->dev, 0x48, 4) & 11653681Ssos ~mask48) | new48, 4); 11755333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA2; 11853681Ssos return 0; 11953681Ssos } 12045095Ssos } 12145095Ssos /* FALLTHROUGH */ 12245095Ssos 12345095Ssos case 0x70108086: /* Intel PIIX3 */ 12445095Ssos if (wdmamode >= 2 && apiomode >= 4) { 12545095Ssos int32_t mask40, new40, mask44, new44; 12645095Ssos 12745095Ssos /* if SITRE not set doit for both channels */ 12845798Ssos if (!((pci_read_config(scp->dev, 0x40, 4)>>(scp->unit<<8))&0x4000)){ 12951520Ssos new40 = pci_read_config(scp->dev, 0x40, 4); 13051520Ssos new44 = pci_read_config(scp->dev, 0x44, 4); 13151520Ssos if (!(new40 & 0x00004000)) { 13251520Ssos new44 &= ~0x0000000f; 13351520Ssos new44 |= ((new40&0x00003000)>>10)|((new40&0x00000300)>>8); 13451520Ssos } 13551520Ssos if (!(new40 & 0x40000000)) { 13651520Ssos new44 &= ~0x000000f0; 13751520Ssos new44 |= ((new40&0x30000000)>>22)|((new40&0x03000000)>>20); 13851520Ssos } 13951520Ssos new40 |= 0x40004000; 14051520Ssos pci_write_config(scp->dev, 0x40, new40, 4); 14151520Ssos pci_write_config(scp->dev, 0x44, new44, 4); 14245095Ssos } 14345095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 14453029Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 14551520Ssos if (bootverbose) 14654969Ssos printf("ata%d-%s: %s setting up WDMA2 mode on PIIX%s chip\n", 14751520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 14854969Ssos (error) ? "failed" : "success", 14955333Ssos (scp->chiptype == 0x70108086) ? "3" : "4"); 15053681Ssos if (!error) { 15153681Ssos if (device == ATA_MASTER) { 15253681Ssos mask40 = 0x0000330f; 15353681Ssos new40 = 0x00002307; 15453681Ssos mask44 = 0; 15553681Ssos new44 = 0; 15653681Ssos } 15753681Ssos else { 15853681Ssos mask40 = 0x000000f0; 15953681Ssos new40 = 0x00000070; 16053681Ssos mask44 = 0x0000000f; 16153681Ssos new44 = 0x0000000b; 16253681Ssos } 16353681Ssos if (scp->unit) { 16453681Ssos mask40 <<= 16; 16553681Ssos new40 <<= 16; 16653681Ssos mask44 <<= 4; 16753681Ssos new44 <<= 4; 16853681Ssos } 16953681Ssos pci_write_config(scp->dev, 0x40, 17053681Ssos (pci_read_config(scp->dev, 0x40, 4) & ~mask40)| 17153681Ssos new40, 4); 17253681Ssos pci_write_config(scp->dev, 0x44, 17353681Ssos (pci_read_config(scp->dev, 0x44, 4) & ~mask44)| 17453681Ssos new44, 4); 17555333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_WDMA2; 17653681Ssos return 0; 17745095Ssos } 17851520Ssos } 17953681Ssos /* we could set PIO mode timings, but we assume the BIOS did that */ 18045095Ssos break; 18145095Ssos 18245095Ssos case 0x12308086: /* Intel PIIX */ 18354544Ssos if (wdmamode >= 2 && apiomode >= 4) { 18454544Ssos int32_t word40; 18554544Ssos 18654544Ssos word40 = pci_read_config(scp->dev, 0x40, 4); 18754544Ssos word40 >>= scp->unit * 16; 18854544Ssos 18954544Ssos /* Check for timing config usable for DMA on controller */ 19054544Ssos if (!((word40 & 0x3300) == 0x2300 && 19154544Ssos ((word40 >> (device == ATA_MASTER ? 0 : 4)) & 1) == 1)) 19254544Ssos break; 19354544Ssos 19454544Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 19554544Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 19654544Ssos if (bootverbose) 19754969Ssos printf("ata%d-%s: %s setting up WDMA2 mode on PIIX chip\n", 19854544Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 19954544Ssos (error) ? "failed" : "success"); 20054544Ssos if (!error) { 20155333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_WDMA2; 20254544Ssos return 0; 20354544Ssos } 20454544Ssos } 20545095Ssos break; 20645095Ssos 20752067Ssos case 0x522910b9: /* AcerLabs Aladdin IV/V */ 20853029Ssos /* the Aladdin doesn't support ATAPI DMA on both master & slave */ 20953029Ssos if (scp->devices & ATA_ATAPI_MASTER && scp->devices & ATA_ATAPI_SLAVE) { 21053029Ssos printf("ata%d: Aladdin: two atapi devices on this channel, " 21153029Ssos "DMA disabled\n", scp->lun); 21253029Ssos break; 21352067Ssos } 21453681Ssos if (udmamode >= 2) { 21552067Ssos int32_t word54 = pci_read_config(scp->dev, 0x54, 4); 21652067Ssos 21751520Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 21853029Ssos ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 21951520Ssos if (bootverbose) 22054969Ssos printf("ata%d-%s: %s setting up UDMA2 mode on Aladdin chip\n", 22151520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 22251520Ssos (error) ? "failed" : "success"); 22353681Ssos if (!error) { 22453681Ssos word54 |= 0x5555; 22553681Ssos word54 |= (0x0a << (16 + (scp->unit << 3) + (device << 2))); 22653681Ssos pci_write_config(scp->dev, 0x54, word54, 4); 22753681Ssos pci_write_config(scp->dev, 0x53, 22853681Ssos pci_read_config(scp->dev, 0x53, 1) | 0x03, 1); 22953681Ssos scp->flags |= ATA_ATAPI_DMA_RO; 23055333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA2; 23153681Ssos return 0; 23253681Ssos } 23351520Ssos } 23453681Ssos if (wdmamode >= 2 && apiomode >= 4) { 23552067Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 23653029Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 23752067Ssos if (bootverbose) 23854969Ssos printf("ata%d-%s: %s setting up WDMA2 mode on Aladdin chip\n", 23952067Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 24052067Ssos (error) ? "failed" : "success"); 24153681Ssos if (!error) { 24253681Ssos pci_write_config(scp->dev, 0x53, 24353681Ssos pci_read_config(scp->dev, 0x53, 1) | 0x03, 1); 24453681Ssos scp->flags |= ATA_ATAPI_DMA_RO; 24555333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_WDMA2; 24653681Ssos return 0; 24753681Ssos } 24852067Ssos } 24953681Ssos /* we could set PIO mode timings, but we assume the BIOS did that */ 25052067Ssos break; 25152067Ssos 25255333Ssos case 0x05711106: /* VIA 82C571, 82C586, 82C596 & 82C686 */ 25354969Ssos case 0x74091022: /* AMD 756 */ 25455333Ssos /* UDMA4 mode only on 82C686 and AMD 756 */ 25554969Ssos if ((udmamode >= 4 && ata_find_dev(scp->dev, 0x06861106)) || 25655333Ssos (udmamode >= 4 && scp->chiptype == 0x74091022)) { 25754270Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 25853681Ssos ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); 25954270Ssos if (bootverbose) 26054969Ssos printf("ata%d-%s: %s setting up UDMA4 mode on %s chip\n", 26154270Ssos scp->lun, (device == ATA_MASTER) ? "master":"slave", 26254969Ssos (error) ? "failed" : "success", 26355333Ssos (scp->chiptype == 0x74091022) ? "AMD" : "VIA"); 26454270Ssos if (!error) { 26554969Ssos pci_write_config(scp->dev, 0x53 - devno, 0xc3, 1); 26655333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA4; 26754270Ssos return 0; 26853681Ssos } 26954270Ssos } 27054270Ssos 27155333Ssos /* UDMA2 mode only on 82C586 > rev1, 82C596, 82C686, AMD 756 */ 27255333Ssos if ((udmamode >= 2 && ata_find_dev(scp->dev, 0x05861106) && 27355333Ssos pci_read_config(scp->dev, 0x08, 1) >= 0x01) || 27455333Ssos (udmamode >= 2 && ata_find_dev(scp->dev, 0x05961106)) || 27555333Ssos (udmamode >= 2 && ata_find_dev(scp->dev, 0x06861106)) || 27655333Ssos (udmamode >= 2 && scp->chiptype == 0x74091022)) { 27753681Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 27853681Ssos ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 27953681Ssos if (bootverbose) 28054969Ssos printf("ata%d-%s: %s setting up UDMA2 mode on %s chip\n", 28153681Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 28254969Ssos (error) ? "failed" : "success", 28355333Ssos (scp->chiptype == 0x74091022) ? "AMD" : "VIA"); 28453681Ssos if (!error) { 28554969Ssos pci_write_config(scp->dev, 0x53 - devno, 0xc0, 1); 28655333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA2; 28753681Ssos return 0; 28853681Ssos } 28953681Ssos } 29053681Ssos if (wdmamode >= 2 && apiomode >= 4) { 29153681Ssos /* set WDMA2 mode timing */ 29253681Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 29353681Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 29453681Ssos if (bootverbose) 29554969Ssos printf("ata%d-%s: %s setting up WDMA2 mode on %s chip\n", 29653681Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 29754969Ssos (error) ? "failed" : "success", 29855333Ssos (scp->chiptype == 0x74091022) ? "AMD" : "VIA"); 29953681Ssos if (!error) { 30054969Ssos pci_write_config(scp->dev, 0x53 - devno, 0x82, 1); 30154969Ssos pci_write_config(scp->dev, 0x4b - devno, 0x31, 1); 30255333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_WDMA2; 30353681Ssos return 0; 30453681Ssos } 30553681Ssos } 30653681Ssos /* we could set PIO mode timings, but we assume the BIOS did that */ 30753681Ssos break; 30853681Ssos 30954544Ssos case 0x55131039: /* SiS 5591 */ 31054544Ssos if (udmamode >= 2) { 31154544Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 31254544Ssos ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 31354544Ssos if (bootverbose) 31454969Ssos printf("ata%d-%s: %s setting up UDMA2 mode on SiS chip\n", 31554544Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 31654544Ssos (error) ? "failed" : "success"); 31754544Ssos if (!error) { 31854544Ssos pci_write_config(scp->dev, 0x40 + (devno << 1), 0xa301, 2); 31955333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA2; 32054544Ssos return 0; 32154544Ssos } 32254544Ssos } 32354544Ssos if (wdmamode >=2 && apiomode >= 4) { 32454544Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 32554544Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 32654544Ssos if (bootverbose) 32754969Ssos printf("ata%d-%s: %s setting up WDMA2 mode on SiS chip\n", 32854544Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 32954544Ssos (error) ? "failed" : "success"); 33054544Ssos if (!error) { 33154544Ssos pci_write_config(scp->dev, 0x40 + (devno << 1), 0x0301, 2); 33255333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_WDMA2; 33354544Ssos return 0; 33454544Ssos } 33554544Ssos } 33654544Ssos /* we could set PIO mode timings, but we assume the BIOS did that */ 33754544Ssos break; 33854544Ssos 33952067Ssos case 0x4d33105a: /* Promise Ultra33 / FastTrak33 controllers */ 34052067Ssos case 0x4d38105a: /* Promise Ultra66 / FastTrak66 controllers */ 34152067Ssos /* the Promise can only do DMA on ATA disks not on ATAPI devices */ 34252067Ssos if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) || 34352067Ssos (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) 34452067Ssos break; 34552067Ssos 34655333Ssos if (udmamode >=4 && scp->chiptype == 0x4d38105a && 34752918Ssos !(pci_read_config(scp->dev, 0x50, 2)&(scp->unit ? 1<<11 : 1<<10))) { 34852918Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 34953029Ssos ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); 35052918Ssos if (bootverbose) 35154969Ssos printf("ata%d-%s: %s setting up UDMA4 mode on Promise chip\n", 35252918Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 35352918Ssos (error) ? "failed" : "success"); 35453681Ssos if (!error) { 35553681Ssos outb(scp->bmaddr+0x11, inl(scp->bmaddr+0x11) | scp->unit ? 8:2); 35655333Ssos promise_timing(scp, devno, ATA_UDMA4); 35755333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA4; 35853681Ssos return 0; 35953681Ssos } 36052918Ssos } 36153681Ssos if (udmamode >= 2) { 36245095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 36353029Ssos ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 36451520Ssos if (bootverbose) 36554969Ssos printf("ata%d-%s: %s setting up UDMA2 mode on Promise chip\n", 36651520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 36751520Ssos (error) ? "failed" : "success"); 36853681Ssos if (!error) { 36955333Ssos promise_timing(scp, devno, ATA_UDMA2); 37055333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA2; 37153681Ssos return 0; 37253681Ssos } 37345095Ssos } 37453681Ssos if (wdmamode >= 2 && apiomode >= 4) { 37545095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 37653029Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 37751520Ssos if (bootverbose) 37854969Ssos printf("ata%d-%s: %s setting up WDMA2 mode on Promise chip\n", 37951520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 38051520Ssos (error) ? "failed" : "success"); 38153681Ssos if (!error) { 38255333Ssos promise_timing(scp, devno, ATA_WDMA2); 38355333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_WDMA2; 38453681Ssos return 0; 38553681Ssos } 38651520Ssos } 38755333Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 38855333Ssos ata_pio2mode(apiomode), 38955333Ssos ATA_C_F_SETXFER, ATA_WAIT_READY); 39053681Ssos if (bootverbose) 39155333Ssos printf("ata%d-%s: %s setting up PIO%d mode on Promise chip\n", 39255333Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 39355333Ssos (error) ? "failed" : "success", 39455333Ssos (apiomode >= 0) ? apiomode : 0); 39555333Ssos if (!error) { 39655333Ssos promise_timing(scp, devno, ata_pio2mode(apiomode)); 39755333Ssos return 0; 39855333Ssos } 39945095Ssos break; 40045095Ssos 40154270Ssos case 0x00041103: /* HighPoint HPT366 controller */ 40253681Ssos /* no ATAPI devices for now */ 40351520Ssos if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) || 40452067Ssos (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) 40552067Ssos break; 40651520Ssos 40752067Ssos if (udmamode >=4 && !(pci_read_config(scp->dev, 0x5a, 1) & 0x2)) { 40852067Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 40953029Ssos ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); 41052067Ssos if (bootverbose) 41154969Ssos printf("ata%d-%s: %s setting up UDMA4 mode on HPT366 chip\n", 41252067Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 41352067Ssos (error) ? "failed" : "success"); 41453681Ssos if (!error) { 41555333Ssos hpt366_timing(scp, devno, ATA_UDMA4); 41655333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA4; 41753681Ssos return 0; 41853681Ssos } 41951520Ssos } 42053681Ssos if (udmamode >= 2) { 42152067Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 42253029Ssos ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 42351520Ssos if (bootverbose) 42454969Ssos printf("ata%d-%s: %s setting up UDMA2 mode on HPT366 chip\n", 42551520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 42651520Ssos (error) ? "failed" : "success"); 42753681Ssos if (!error) { 42855333Ssos hpt366_timing(scp, devno, ATA_UDMA2); 42955333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA2; 43053681Ssos return 0; 43153681Ssos } 43245095Ssos } 43353681Ssos if (wdmamode >= 2 && apiomode >= 4) { 43445095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 43553029Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 43651520Ssos if (bootverbose) 43754969Ssos printf("ata%d-%s: %s setting up WDMA2 mode on HPT366 chip\n", 43851520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 43951520Ssos (error) ? "failed" : "success"); 44053681Ssos if (!error) { 44155333Ssos hpt366_timing(scp, devno, ATA_WDMA2); 44255333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_WDMA2; 44353681Ssos return 0; 44453681Ssos } 44545095Ssos } 44655333Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 44755333Ssos ata_pio2mode(apiomode), 44855333Ssos ATA_C_F_SETXFER, ATA_WAIT_READY); 44953681Ssos if (bootverbose) 45055333Ssos printf("ata%d-%s: %s setting up PIO%d mode on HPT366 chip\n", 45155333Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 45255333Ssos (error) ? "failed" : "success", 45355333Ssos (apiomode >= 0) ? apiomode : 0); 45455333Ssos if (!error) { 45555333Ssos hpt366_timing(scp, devno, ata_pio2mode(apiomode)); 45655333Ssos return 0; 45755333Ssos } 45845095Ssos break; 45945095Ssos 46051548Ssos default: /* unknown controller chip */ 46151548Ssos /* better not try generic DMA on ATAPI devices it almost never works */ 46251548Ssos if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) || 46351548Ssos (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) 46451548Ssos break; 46551548Ssos 46651548Ssos /* well, we have no support for this, but try anyways */ 46754594Ssos if ((wdmamode >= 2 && apiomode >= 4) && scp->bmaddr) { 46854594Ssos#if MAYBE_NOT 46955333Ssos && (inb(scp->bmaddr + ATA_BMSTAT_PORT) & 47051520Ssos ((device == ATA_MASTER) ? 47154544Ssos ATA_BMSTAT_DMA_MASTER : ATA_BMSTAT_DMA_SLAVE))) { 47254594Ssos#endif 47345095Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 47453029Ssos ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); 47551520Ssos if (bootverbose) 47654969Ssos printf("ata%d-%s: %s setting up WDMA2 mode on generic chip\n", 47751520Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 47851520Ssos (error) ? "failed" : "success"); 47953681Ssos if (!error) { 48055333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_WDMA2; 48153681Ssos return 0; 48253681Ssos } 48345095Ssos } 48445095Ssos } 48545095Ssos free(dmatab, M_DEVBUF); 48655333Ssos error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 48755333Ssos ata_pio2mode(apiomode), ATA_C_F_SETXFER,ATA_WAIT_READY); 48855333Ssos if (bootverbose) 48955333Ssos printf("ata%d-%s: %s setting up PIO%d mode on generic chip\n", 49055333Ssos scp->lun, (device == ATA_MASTER) ? "master" : "slave", 49155333Ssos (error) ? "failed" : "success", (apiomode >= 0) ? apiomode : 0); 49255333Ssos if (!error) 49355333Ssos scp->mode[(device == ATA_MASTER) ? 0 : 1] = ata_pio2mode(apiomode); 49445095Ssos return -1; 49545095Ssos} 49645095Ssos 49745095Ssosint32_t 49845095Ssosata_dmasetup(struct ata_softc *scp, int32_t device, 49945095Ssos int8_t *data, int32_t count, int32_t flags) 50045095Ssos{ 50145095Ssos struct ata_dmaentry *dmatab; 50245095Ssos u_int32_t dma_count, dma_base; 50345095Ssos int32_t i = 0; 50445095Ssos 50545720Speter if (((uintptr_t)data & 1) || (count & 1)) 50645095Ssos return -1; 50745095Ssos 50845095Ssos if (!count) { 50954969Ssos printf("ata%d-%s: zero length DMA transfer attempted\n", 51051520Ssos scp->lun, ((device == ATA_MASTER) ? "master" : "slave")); 51145095Ssos return -1; 51245095Ssos } 51345095Ssos 51451520Ssos dmatab = scp->dmatab[(device == ATA_MASTER) ? 0 : 1]; 51545095Ssos dma_base = vtophys(data); 51645720Speter dma_count = MIN(count, (PAGE_SIZE - ((uintptr_t)data & PAGE_MASK))); 51745095Ssos data += dma_count; 51845095Ssos count -= dma_count; 51945095Ssos 52045095Ssos while (count) { 52145095Ssos dmatab[i].base = dma_base; 52245095Ssos dmatab[i].count = (dma_count & 0xffff); 52345095Ssos i++; 52445095Ssos if (i >= ATA_DMA_ENTRIES) { 52554969Ssos printf("ata%d-%s: too many segments in DMA table\n", 52645095Ssos scp->lun, (device ? "slave" : "master")); 52745095Ssos return -1; 52845095Ssos } 52945095Ssos dma_base = vtophys(data); 53045095Ssos dma_count = MIN(count, PAGE_SIZE); 53145095Ssos data += MIN(count, PAGE_SIZE); 53245095Ssos count -= MIN(count, PAGE_SIZE); 53345095Ssos } 53445095Ssos dmatab[i].base = dma_base; 53545095Ssos dmatab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT; 53645095Ssos outl(scp->bmaddr + ATA_BMDTP_PORT, vtophys(dmatab)); 53745095Ssos outb(scp->bmaddr + ATA_BMCMD_PORT, flags ? ATA_BMCMD_WRITE_READ:0); 53845095Ssos outb(scp->bmaddr + ATA_BMSTAT_PORT, (inb(scp->bmaddr + ATA_BMSTAT_PORT) | 53945095Ssos (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); 54045095Ssos return 0; 54145095Ssos} 54245095Ssos 54345095Ssosvoid 54452067Ssosata_dmastart(struct ata_softc *scp) 54545095Ssos{ 54652067Ssos scp->flags |= ATA_DMA_ACTIVE; 54745095Ssos outb(scp->bmaddr + ATA_BMCMD_PORT, 54845095Ssos inb(scp->bmaddr + ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP); 54945095Ssos} 55045095Ssos 55145095Ssosint32_t 55252067Ssosata_dmadone(struct ata_softc *scp) 55345095Ssos{ 55445095Ssos outb(scp->bmaddr + ATA_BMCMD_PORT, 55545095Ssos inb(scp->bmaddr + ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); 55652067Ssos scp->flags &= ~ATA_DMA_ACTIVE; 55745095Ssos return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 55845095Ssos} 55945095Ssos 56045095Ssosint32_t 56152067Ssosata_dmastatus(struct ata_softc *scp) 56245095Ssos{ 56345095Ssos return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 56445095Ssos} 56545095Ssos 56652067Ssosstatic void 56755333Ssospromise_timing(struct ata_softc *scp, int32_t devno, int32_t mode) 56852067Ssos{ 56952067Ssos u_int32_t timing; 57055333Ssos switch (mode) { 57155333Ssos default: 57255333Ssos case ATA_PIO0: timing = 0x004ff329; break; 57355333Ssos case ATA_PIO1: timing = 0x004fec25; break; 57455333Ssos case ATA_PIO2: timing = 0x004fe823; break; 57555333Ssos case ATA_PIO3: timing = 0x004fe622; break; 57655333Ssos case ATA_PIO4: timing = 0x004fe421; break; 57755333Ssos case ATA_WDMA2: timing = 0x004367f3; break; 57855333Ssos case ATA_UDMA2: timing = 0x004127f3; break; 57955333Ssos case ATA_UDMA4: timing = 0x004127f3; break; 58055333Ssos } 58155333Ssos pci_write_config(scp->dev, 0x60 + (devno << 2), timing, 4); 58255333Ssos} 58352067Ssos 58455333Ssosstatic void 58555333Ssoshpt366_timing(struct ata_softc *scp, int32_t devno, int32_t mode) 58655333Ssos{ 58755333Ssos u_int32_t timing; 58855333Ssos 58955333Ssos switch (pci_read_config(scp->dev, 0x41 + (devno << 2), 1)) { 59052067Ssos case 0x85: /* 25Mhz */ 59152067Ssos switch (mode) { 59255333Ssos case ATA_PIO0: timing = 0xc0d08585; break; 59355333Ssos case ATA_PIO1: timing = 0xc0d08572; break; 59455333Ssos case ATA_PIO2: timing = 0xc0ca8542; break; 59555333Ssos case ATA_PIO3: timing = 0xc0ca8532; break; 59655333Ssos case ATA_PIO4: timing = 0xc0ca8521; break; 59755333Ssos case ATA_WDMA2: timing = 0xa0ca8521; break; 59855333Ssos case ATA_UDMA2: timing = 0x90cf8521; break; 59955333Ssos case ATA_UDMA4: timing = 0x90c98521; break; 60055333Ssos default: timing = 0x01208585; 60152067Ssos } 60252067Ssos break; 60352067Ssos default: 60452067Ssos case 0xa7: /* 33MHz */ 60552067Ssos switch (mode) { 60655333Ssos case ATA_PIO0: timing = 0xc0d0a7aa; break; 60755333Ssos case ATA_PIO1: timing = 0xc0d0a7a3; break; 60855333Ssos case ATA_PIO2: timing = 0xc0d0a753; break; 60955333Ssos case ATA_PIO3: timing = 0xc0c8a742; break; 61055333Ssos case ATA_PIO4: timing = 0xc0c8a731; break; 61155333Ssos case ATA_WDMA2: timing = 0xa0c8a731; break; 61255333Ssos case ATA_UDMA2: timing = 0x90caa731; break; 61355333Ssos case ATA_UDMA4: timing = 0x90c9a731; break; 61455333Ssos default: timing = 0x0120a7a7; 61552067Ssos } 61652067Ssos break; 61752067Ssos case 0xd9: /* 40Mhz */ 61852067Ssos switch (mode) { 61955333Ssos case ATA_PIO0: timing = 0xc018d9d9; break; 62055333Ssos case ATA_PIO1: timing = 0xc010d9c7; break; 62155333Ssos case ATA_PIO2: timing = 0xc010d997; break; 62255333Ssos case ATA_PIO3: timing = 0xc010d974; break; 62355333Ssos case ATA_PIO4: timing = 0xc008d963; break; 62455333Ssos case ATA_WDMA2: timing = 0xa008d943; break; 62555333Ssos case ATA_UDMA2: timing = 0x900bd943; break; 62655333Ssos case ATA_UDMA4: timing = 0x900fd943; break; 62755333Ssos default: timing = 0x0120d9d9; 62852067Ssos } 62952067Ssos } 63055333Ssos pci_write_config(scp->dev, 0x40 + (devno << 2) , timing, 4); 63152067Ssos} 63252067Ssos 63345095Ssos#else /* NPCI > 0 */ 63445095Ssos 63545095Ssosint32_t 63645095Ssosata_dmainit(struct ata_softc *scp, int32_t device, 63751520Ssos int32_t piomode, int32_t wdmamode, int32_t udmamode) 63845095Ssos{ 63945095Ssos return -1; 64045095Ssos} 64145095Ssos 64245095Ssosint32_t 64345095Ssosata_dmasetup(struct ata_softc *scp, int32_t device, 64451520Ssos int8_t *data, int32_t count, int32_t flags) 64545095Ssos{ 64645095Ssos return -1; 64745095Ssos} 64845095Ssos 64945095Ssosvoid 65052067Ssosata_dmastart(struct ata_softc *scp) 65145095Ssos{ 65245095Ssos} 65345095Ssos 65445095Ssosint32_t 65552067Ssosata_dmadone(struct ata_softc *scp) 65645095Ssos{ 65745095Ssos return -1; 65845095Ssos} 65945095Ssos 66045095Ssosint32_t 66152067Ssosata_dmastatus(struct ata_softc *scp) 66245095Ssos{ 66345095Ssos return -1; 66445095Ssos} 66545095Ssos 66645095Ssos#endif /* NPCI > 0 */ 667