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 50477 1999-08-28 01:08:13Z peter $
29 */
30
31#include "ata.h"
32#include "pci.h"
33#if NATA > 0
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/kernel.h>
37#include <sys/buf.h>
38#include <sys/malloc.h>
39#include <sys/bus.h>
40#include <vm/vm.h>
41#include <vm/pmap.h>
42#if NPCI > 0
43#include <pci/pcivar.h>
44#include <pci/pcireg.h>
45#endif
46#include <dev/ata/ata-all.h>
47
48#ifdef __alpha__
49#undef vtophys
50#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va)
51#endif
52
53/* misc defines */
54#define MIN(a,b) ((a)>(b)?(b):(a))
55
56#if NPCI > 0
57
58int32_t
59ata_dmainit(struct ata_softc *scp, int32_t device,
60 int32_t apiomode, int32_t wdmamode, int32_t udmamode)
61{
62 int32_t type, devno, error;
63 void *dmatab;
64
65 if (!scp->bmaddr)
66 return -1;
67#ifdef ATA_DEBUGDMA
68 printf("ata%d: dmainit: ioaddr=0x%x altioaddr=0x%x, bmaddr=0x%x\n",
69 scp->lun, scp->ioaddr, scp->altioaddr, scp->bmaddr);
70#endif
71
72 if (!(dmatab = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT)))
73 return -1;
74
75 if (((uintptr_t)dmatab >> PAGE_SHIFT) ^
76 (((uintptr_t)dmatab + PAGE_SIZE - 1) >> PAGE_SHIFT)) {
77 printf("ata_dmainit: dmatab crosses page boundary, no DMA\n");
78 free(dmatab, M_DEVBUF);
79 return -1;
80 }
81 scp->dmatab[device ? 1 : 0] = dmatab;
82
83 type = pci_get_devid(scp->dev);
84
85 switch(type) {
86
87 case 0x71118086: /* Intel PIIX4 */
88 if (udmamode >= 2) {
89 int32_t mask48, new48;
90
91 printf("ata%d: %s: setting up UDMA2 mode on PIIX4 chip ",
92 scp->lun, (device) ? "slave" : "master");
93 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
94 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
95 if (error) {
96 printf("failed\n");
97 break;
98 }
99 printf("OK\n");
100 devno = (scp->unit << 1) + (device ? 1 : 0);
101 mask48 = (1 << devno) + (3 << (16 + (devno << 2)));
102 new48 = (1 << devno) + (2 << (16 + (devno << 2)));
103 pci_write_config(scp->dev, 0x48,
104 (pci_read_config(scp->dev, 0x48, 4) &
105 ~mask48) | new48, 4);
106 return 0;
107 }
108 /* FALLTHROUGH */
109
110 case 0x70108086: /* Intel PIIX3 */
111 if (wdmamode >= 2 && apiomode >= 4) {
112 int32_t mask40, new40, mask44, new44;
113
114 /* if SITRE not set doit for both channels */
115 if (!((pci_read_config(scp->dev, 0x40, 4)>>(scp->unit<<8))&0x4000)){
116 new40 = pci_read_config(scp->dev, 0x40, 4);
117 new44 = pci_read_config(scp->dev, 0x44, 4);
118 if (!(new40 & 0x00004000)) {
119 new44 &= ~0x0000000f;
120 new44 |= ((new40&0x00003000)>>10)|((new40&0x00000300)>>8);
121 }
122 if (!(new40 & 0x40000000)) {
123 new44 &= ~0x000000f0;
124 new44 |= ((new40&0x30000000)>>22)|((new40&0x03000000)>>20);
125 }
126 new40 |= 0x40004000;
127 pci_write_config(scp->dev, 0x40, new40, 4);
128 pci_write_config(scp->dev, 0x44, new44, 4);
129 }
130 printf("ata%d: %s: setting up WDMA2 mode on PIIX3/4 chip ",
131 scp->lun, (device) ? "slave" : "master");
132 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
133 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
134 if (error) {
135 printf("failed\n");
136 break;
137 }
138 printf("OK\n");
139 if (device == ATA_MASTER) {
140 mask40 = 0x0000330f;
141 new40 = 0x00002307;
142 mask44 = 0;
143 new44 = 0;
144 } else {
145 mask40 = 0x000000f0;
146 new40 = 0x00000070;
147 mask44 = 0x0000000f;
148 new44 = 0x0000000b;
149 }
150 if (scp->unit) {
151 mask40 <<= 16;
152 new40 <<= 16;
153 mask44 <<= 4;
154 new44 <<= 4;
155 }
156 pci_write_config(scp->dev, 0x40,
157 (pci_read_config(scp->dev, 0x40, 4) &
158 ~mask40) | new40, 4);
159 pci_write_config(scp->dev, 0x44,
160 (pci_read_config(scp->dev, 0x44, 4) &
161 ~mask44) | new44, 4);
162 return 0;
163 }
164 break;
165
166 case 0x12308086: /* Intel PIIX */
167 /* probably not worth the trouble */
168 break;
169
170 case 0x4d33105a: /* Promise Ultra/33 / FastTrack controllers */
171 case 0x4d38105a: /* Promise Ultra/66 controllers */
172 /* the promise seems to have trouble with DMA on ATAPI devices */
173 if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) ||
174 (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE))
175 break;
176
177 devno = (scp->unit << 1) + (device ? 1 : 0);
178 if (udmamode >=2) {
179 printf("ata%d: %s: setting up UDMA2 mode on Promise chip ",
180 scp->lun, (device) ? "slave" : "master");
181 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
182 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
183 if (error) {
184 printf("failed\n");
185 break;
186 }
187 printf("OK\n");
188 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004127f3, 4);
189 return 0;
190 }
191 else if (wdmamode >= 2 && apiomode >= 4) {
192 printf("ata%d: %s: setting up WDMA2 mode on Promise chip ",
193 scp->lun, (device) ? "slave" : "master");
194 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
195 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
196 if (error) {
197 printf("failed\n");
198 break;
199 }
200 printf("OK\n");
201 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004367f3, 4);
202 return 0;
203 }
204 else {
205 printf("ata%d: %s: setting up PIO mode on Promise chip OK\n",
206 scp->lun, (device) ? "slave" : "master");
207 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004fe924, 4);
208 }
209 break;
210
211 case 0x522910b9: /* AcerLabs Aladdin IV/V */
212 if (udmamode >=2) {
213 int32_t word54 = pci_read_config(scp->dev, 0x54, 4);
214
215 printf("ata%d: %s: setting up UDMA2 mode on Aladdin chip ",
216 scp->lun, (device) ? "slave" : "master");
217 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
218 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
219 if (error) {
220 printf("failed\n");
221 break;
222 }
223 printf("OK\n");
224 word54 |= 0x5555;
225 word54 |= (0x0000000A << (16 + (scp->unit << 3) + (device << 2)));
226 pci_write_config(scp->dev, 0x54, word54, 4);
227 return 0;
228
229 }
230 else if (wdmamode >= 2 && apiomode >= 4) {
231 printf("ata%d: %s: setting up WDMA2 mode on Aladdin chip ",
232 scp->lun, (device) ? "slave" : "master");
233 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
234 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
235 if (error) {
236 printf("failed\n");
237 break;
238 }
239 printf("OK\n");
240 return 0;
241 }
242 break;
243
244 default: /* well, we have no support for this, but try anyways */
245 if ((wdmamode >= 2 && apiomode >= 4) || udmamode >= 2) {
246 printf("ata%d: %s: setting up generic WDMA2 mode ",
247 scp->lun, (device) ? "slave" : "master");
248 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
249 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
250 if (error) {
251 printf("failed\n");
252 break;
253 }
254 printf("OK\n");
255 return 0;
256 }
257 }
258 free(dmatab, M_DEVBUF);
259 return -1;
260}
261
262int32_t
263ata_dmasetup(struct ata_softc *scp, int32_t device,
264 int8_t *data, int32_t count, int32_t flags)
265{
266 struct ata_dmaentry *dmatab;
267 u_int32_t dma_count, dma_base;
268 int32_t i = 0;
269
270#ifdef ATA_DEBUGDMA
271 printf("ata%d: dmasetup\n", scp->lun);
272#endif
273 if (((uintptr_t)data & 1) || (count & 1))
274 return -1;
275
276 if (!count) {
277 printf("ata%d: zero length DMA transfer attempt on %s\n",
278 scp->lun, (device ? "slave" : "master"));
279 return -1;
280 }
281
282 dmatab = scp->dmatab[device ? 1 : 0];
283 dma_base = vtophys(data);
284 dma_count = MIN(count, (PAGE_SIZE - ((uintptr_t)data & PAGE_MASK)));
285 data += dma_count;
286 count -= dma_count;
287
288 while (count) {
289 dmatab[i].base = dma_base;
290 dmatab[i].count = (dma_count & 0xffff);
291 i++;
292 if (i >= ATA_DMA_ENTRIES) {
293 printf("ata%d: too many segments in DMA table for %s\n",
294 scp->lun, (device ? "slave" : "master"));
295 return -1;
296 }
297 dma_base = vtophys(data);
298 dma_count = MIN(count, PAGE_SIZE);
299 data += MIN(count, PAGE_SIZE);
300 count -= MIN(count, PAGE_SIZE);
301 }
302#ifdef ATA_DEBUGDMA
303printf("ata_dmasetup: base=%08x count%08x\n",
304 dma_base, dma_count);
305#endif
306 dmatab[i].base = dma_base;
307 dmatab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT;
308
309 outl(scp->bmaddr + ATA_BMDTP_PORT, vtophys(dmatab));
310#ifdef ATA_DEBUGDMA
311printf("dmatab=%08x %08x\n", vtophys(dmatab), inl(scp->bmaddr+ATA_BMDTP_PORT));
312#endif
313 outb(scp->bmaddr + ATA_BMCMD_PORT, flags ? ATA_BMCMD_WRITE_READ:0);
314 outb(scp->bmaddr + ATA_BMSTAT_PORT, (inb(scp->bmaddr + ATA_BMSTAT_PORT) |
315 (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
316 return 0;
317}
318
319void
320ata_dmastart(struct ata_softc *scp, int32_t device)
321{
322#ifdef ATA_DEBUGDMA
323 printf("ata%d: dmastart\n", scp->lun);
324#endif
325 outb(scp->bmaddr + ATA_BMCMD_PORT,
326 inb(scp->bmaddr + ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP);
327}
328
329int32_t
330ata_dmadone(struct ata_softc *scp, int32_t device)
331{
332#ifdef ATA_DEBUGDMA
333 printf("ata%d: dmadone\n", scp->lun);
334#endif
335 outb(scp->bmaddr + ATA_BMCMD_PORT,
336 inb(scp->bmaddr + ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
337 return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
338}
339
340int32_t
341ata_dmastatus(struct ata_softc *scp, int32_t device)
342{
343#ifdef ATA_DEBUGDMA
344 printf("ata%d: dmastatus\n", scp->lun);
345#endif
346 return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
347}
348
349#else /* NPCI > 0 */
350
351int32_t
352ata_dmainit(struct ata_softc *scp, int32_t device,
353 int32_t piomode, int32_t wdmamode, int32_t udmamode)
354{
355 return -1;
356}
357
358int32_t
359ata_dmasetup(struct ata_softc *scp, int32_t device,
360 int8_t *data, int32_t count, int32_t flags)
361{
362 return -1;
363}
364
365void
366ata_dmastart(struct ata_softc *scp, int32_t device)
367{
368}

--- 15 unchanged lines hidden ---