Deleted Added
sdiff udiff text old ( 50477 ) new ( 51520 )
full compact
1/*-
2 * Copyright (c) 1998,1999 S�ren Schmidt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/dev/ata/ata-dma.c 51520 1999-09-21 19:50:40Z sos $
29 */
30
31#include "ata.h"
32#include "pci.h"
33#include "apm.h"
34
35#if NATA > 0
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#include <sys/buf.h>
41#include <sys/malloc.h>
42#include <sys/bus.h>
43#include <vm/vm.h>
44#include <vm/pmap.h>
45#if NPCI > 0
46#include <pci/pcivar.h>
47#include <pci/pcireg.h>
48#endif
49#if NAPM > 0
50#include <machine/apm_bios.h>
51#endif
52#include <dev/ata/ata-all.h>
53
54#ifdef __alpha__
55#undef vtophys
56#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va)
57#endif
58
59/* misc defines */
60#define MIN(a,b) ((a)>(b)?(b):(a))
61
62#if NPCI > 0
63
64int32_t
65ata_dmainit(struct ata_softc *scp, int32_t device,
66 int32_t apiomode, int32_t wdmamode, int32_t udmamode)
67{
68 int32_t type, devno, error;
69 void *dmatab;
70
71 if (!scp->bmaddr)
72 return -1;
73#ifdef ATA_DMADEBUG
74 printf("ata%d: dmainit: ioaddr=0x%x altioaddr=0x%x, bmaddr=0x%x\n",
75 scp->lun, scp->ioaddr, scp->altioaddr, scp->bmaddr);
76#endif
77
78 if (!(dmatab = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT)))
79 return -1;
80
81 if (((uintptr_t)dmatab >> PAGE_SHIFT) ^
82 (((uintptr_t)dmatab + PAGE_SIZE - 1) >> PAGE_SHIFT)) {
83 printf("ata_dmainit: dmatab crosses page boundary, no DMA\n");
84 free(dmatab, M_DEVBUF);
85 return -1;
86 }
87 scp->dmatab[(device == ATA_MASTER) ? 0 : 1] = dmatab;
88
89 switch (type = pci_get_devid(scp->dev)) {
90
91 case 0x71118086: /* Intel PIIX4 */
92 if (udmamode >= 2) {
93 int32_t mask48, new48;
94
95 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
96 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
97 if (bootverbose)
98 printf("ata%d: %s: %s setting up UDMA2 mode on PIIX4 chip\n",
99 scp->lun, (device == ATA_MASTER) ? "master" : "slave",
100 (error) ? "failed" : "success");
101 if (error)
102 break;
103 devno = (scp->unit << 1) + ((device == ATA_MASTER) ? 0 : 1);
104 mask48 = (1 << devno) + (3 << (16 + (devno << 2)));
105 new48 = (1 << devno) + (2 << (16 + (devno << 2)));
106 pci_write_config(scp->dev, 0x48,
107 (pci_read_config(scp->dev, 0x48, 4) &
108 ~mask48) | new48, 4);
109 scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA33;
110 return 0;
111 }
112 /* FALLTHROUGH */
113
114 case 0x70108086: /* Intel PIIX3 */
115 if (wdmamode >= 2 && apiomode >= 4) {
116 int32_t mask40, new40, mask44, new44;
117
118 /* if SITRE not set doit for both channels */
119 if (!((pci_read_config(scp->dev, 0x40, 4)>>(scp->unit<<8))&0x4000)){
120 new40 = pci_read_config(scp->dev, 0x40, 4);
121 new44 = pci_read_config(scp->dev, 0x44, 4);
122 if (!(new40 & 0x00004000)) {
123 new44 &= ~0x0000000f;
124 new44 |= ((new40&0x00003000)>>10)|((new40&0x00000300)>>8);
125 }
126 if (!(new40 & 0x40000000)) {
127 new44 &= ~0x000000f0;
128 new44 |= ((new40&0x30000000)>>22)|((new40&0x03000000)>>20);
129 }
130 new40 |= 0x40004000;
131 pci_write_config(scp->dev, 0x40, new40, 4);
132 pci_write_config(scp->dev, 0x44, new44, 4);
133 }
134 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
135 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
136 if (bootverbose)
137 printf("ata%d: %s: %s setting up WDMA2 mode on PIIX4 chip\n",
138 scp->lun, (device == ATA_MASTER) ? "master" : "slave",
139 (error) ? "failed" : "success");
140 if (error)
141 break;
142 if (device == ATA_MASTER) {
143 mask40 = 0x0000330f;
144 new40 = 0x00002307;
145 mask44 = 0;
146 new44 = 0;
147 } else {
148 mask40 = 0x000000f0;
149 new40 = 0x00000070;
150 mask44 = 0x0000000f;
151 new44 = 0x0000000b;
152 }
153 if (scp->unit) {
154 mask40 <<= 16;
155 new40 <<= 16;
156 mask44 <<= 4;
157 new44 <<= 4;
158 }
159 pci_write_config(scp->dev, 0x40,
160 (pci_read_config(scp->dev, 0x40, 4) & ~mask40) |
161 new40, 4);
162 pci_write_config(scp->dev, 0x44,
163 (pci_read_config(scp->dev, 0x44, 4) & ~mask44) |
164 new44, 4);
165 scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_DMA;
166 return 0;
167 }
168 break;
169
170 case 0x12308086: /* Intel PIIX */
171 /* probably not worth the trouble */
172 break;
173
174 case 0x4d33105a: /* Promise Ultra/33 / FastTrack controllers */
175 case 0x4d38105a: /* Promise Ultra/66 controllers */
176 /* the Promise can only do DMA on ATA disks not on ATAPI devices */
177 if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) ||
178 (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE))
179 break;
180
181 devno = (scp->unit << 1) + ((device == ATA_MASTER) ? 0 : 1);
182 if (udmamode >=4 && type == 0x4d38105a) {
183 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
184 ATA_UDMA4, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
185 if (bootverbose)
186 printf("ata%d: %s: %s setting up UDMA4 mode on Promise chip\n",
187 scp->lun, (device == ATA_MASTER) ? "master" : "slave",
188 (error) ? "failed" : "success");
189 if (error)
190 break;
191 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004117f3, 4);
192 scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA66;
193 return 0;
194 }
195
196 if (udmamode >=2) {
197 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
198 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
199 if (bootverbose)
200 printf("ata%d: %s: %s setting up UDMA2 mode on Promise chip\n",
201 scp->lun, (device == ATA_MASTER) ? "master" : "slave",
202 (error) ? "failed" : "success");
203 if (error)
204 break;
205 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004127f3, 4);
206 scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA33;
207 return 0;
208 }
209 else if (wdmamode >= 2 && apiomode >= 4) {
210 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
211 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
212 if (bootverbose)
213 printf("ata%d: %s: %s setting up WDMA2 mode on Promise chip\n",
214 scp->lun, (device == ATA_MASTER) ? "master" : "slave",
215 (error) ? "failed" : "success");
216 if (error)
217 break;
218 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004367f3, 4);
219 scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_DMA;
220 return 0;
221 }
222 else {
223 if (bootverbose)
224 printf("ata%d: %s: setting PIO mode on Promise chip\n",
225 scp->lun, (device == ATA_MASTER) ? "master" : "slave");
226 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004fe924, 4);
227 }
228 break;
229
230 case 0x522910b9: /* AcerLabs Aladdin IV/V */
231 /* the Aladdin has to be setup specially for ATAPI devices */
232 if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) ||
233 (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) {
234 int8_t word53 = pci_read_config(scp->dev, 0x53, 1);
235
236 /* if needed set atapi fifo & dma */
237 if ((udmamode >=2) || (wdmamode >= 2 && apiomode >= 4)) {
238 pci_write_config(scp->dev, 0x53, word53 | 0x03, 1);
239 scp->flags |= ATA_ATAPI_DMA_RO;
240 if (device == ATA_MASTER)
241 outb(scp->bmaddr + ATA_BMSTAT_PORT,
242 inb(scp->bmaddr + ATA_BMSTAT_PORT) |
243 ATA_BMSTAT_DMA_MASTER);
244 else
245 outb(scp->bmaddr + ATA_BMSTAT_PORT,
246 inb(scp->bmaddr + ATA_BMSTAT_PORT) |
247 ATA_BMSTAT_DMA_SLAVE);
248 }
249 else {
250 pci_write_config(scp->dev, 0x53, (word53 & ~0x01) | 0x02, 1);
251 }
252 }
253 if (udmamode >=2) {
254 int32_t word54 = pci_read_config(scp->dev, 0x54, 4);
255
256 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
257 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
258 if (bootverbose)
259 printf("ata%d: %s: %s setting up UDMA2 mode on Aladdin chip\n",
260 scp->lun, (device == ATA_MASTER) ? "master" : "slave",
261 (error) ? "failed" : "success");
262 if (error)
263 break;
264 word54 |= 0x5555;
265 word54 |= (0x0a << (16 + (scp->unit << 3) + (device << 2)));
266 pci_write_config(scp->dev, 0x54, word54, 4);
267 scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA33;
268 return 0;
269
270 }
271 else if (wdmamode >= 2 && apiomode >= 4) {
272 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
273 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
274 if (bootverbose)
275 printf("ata%d: %s: %s setting up WDMA2 mode on Aladdin chip\n",
276 scp->lun, (device == ATA_MASTER) ? "master" : "slave",
277 (error) ? "failed" : "success");
278 if (error)
279 break;
280 scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_DMA;
281 return 0;
282 }
283 break;
284
285 default: /* well, we have no support for this, but try anyways */
286 if (((wdmamode >= 2 && apiomode >= 4) || udmamode >= 2) &&
287 (inb(scp->bmaddr + ATA_BMSTAT_PORT) &
288 ((device == ATA_MASTER) ?
289 ATA_BMSTAT_DMA_SLAVE : ATA_BMSTAT_DMA_MASTER))) {
290 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
291 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
292 if (bootverbose)
293 printf("ata%d: %s: %s setting up WDMA2 mode on generic chip\n",
294 scp->lun, (device == ATA_MASTER) ? "master" : "slave",
295 (error) ? "failed" : "success");
296 if (error)
297 break;
298 scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_DMA;
299 return 0;
300 }
301 }
302 free(dmatab, M_DEVBUF);
303 return -1;
304}
305
306int32_t
307ata_dmasetup(struct ata_softc *scp, int32_t device,
308 int8_t *data, int32_t count, int32_t flags)
309{
310 struct ata_dmaentry *dmatab;
311 u_int32_t dma_count, dma_base;
312 int32_t i = 0;
313
314#ifdef ATA_DMADEBUG
315 printf("ata%d: dmasetup\n", scp->lun);
316#endif
317 if (((uintptr_t)data & 1) || (count & 1))
318 return -1;
319
320 if (!count) {
321#ifdef ATA_DMADEBUG
322 printf("ata%d: zero length DMA transfer attempt on %s\n",
323 scp->lun, ((device == ATA_MASTER) ? "master" : "slave"));
324#endif
325 return -1;
326 }
327
328 dmatab = scp->dmatab[(device == ATA_MASTER) ? 0 : 1];
329 dma_base = vtophys(data);
330 dma_count = MIN(count, (PAGE_SIZE - ((uintptr_t)data & PAGE_MASK)));
331 data += dma_count;
332 count -= dma_count;
333
334 while (count) {
335 dmatab[i].base = dma_base;
336 dmatab[i].count = (dma_count & 0xffff);
337 i++;
338 if (i >= ATA_DMA_ENTRIES) {
339 printf("ata%d: too many segments in DMA table for %s\n",
340 scp->lun, (device ? "slave" : "master"));
341 return -1;
342 }
343 dma_base = vtophys(data);
344 dma_count = MIN(count, PAGE_SIZE);
345 data += MIN(count, PAGE_SIZE);
346 count -= MIN(count, PAGE_SIZE);
347 }
348#ifdef ATA_DMADEBUG
349 printf("ata_dmasetup: base=%08x count%08x\n", dma_base, dma_count);
350#endif
351 dmatab[i].base = dma_base;
352 dmatab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT;
353
354 outl(scp->bmaddr + ATA_BMDTP_PORT, vtophys(dmatab));
355#ifdef ATA_DMADEBUG
356 printf("dmatab=%08x %08x\n",
357 vtophys(dmatab), inl(scp->bmaddr+ATA_BMDTP_PORT));
358#endif
359 outb(scp->bmaddr + ATA_BMCMD_PORT, flags ? ATA_BMCMD_WRITE_READ:0);
360 outb(scp->bmaddr + ATA_BMSTAT_PORT, (inb(scp->bmaddr + ATA_BMSTAT_PORT) |
361 (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
362 return 0;
363}
364
365void
366ata_dmastart(struct ata_softc *scp, int32_t device)
367{
368#ifdef ATA_DMADEBUG
369 printf("ata%d: dmastart\n", scp->lun);
370#endif
371 outb(scp->bmaddr + ATA_BMCMD_PORT,
372 inb(scp->bmaddr + ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP);
373}
374
375int32_t
376ata_dmadone(struct ata_softc *scp, int32_t device)
377{
378#ifdef ATA_DMADEBUG
379 printf("ata%d: dmadone\n", scp->lun);
380#endif
381 outb(scp->bmaddr + ATA_BMCMD_PORT,
382 inb(scp->bmaddr + ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
383 return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
384}
385
386int32_t
387ata_dmastatus(struct ata_softc *scp, int32_t device)
388{
389#ifdef ATA_DMADEBUG
390 printf("ata%d: dmastatus\n", scp->lun);
391#endif
392 return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
393}
394
395#else /* NPCI > 0 */
396
397int32_t
398ata_dmainit(struct ata_softc *scp, int32_t device,
399 int32_t piomode, int32_t wdmamode, int32_t udmamode)
400{
401 return -1;
402}
403
404int32_t
405ata_dmasetup(struct ata_softc *scp, int32_t device,
406 int8_t *data, int32_t count, int32_t flags)
407{
408 return -1;
409}
410
411void
412ata_dmastart(struct ata_softc *scp, int32_t device)
413{
414}

--- 15 unchanged lines hidden ---