|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1992 NeXT Computer, Inc.
27: *
28: * dma.c -- DMA Routines.
29: *
30: * HISTORY
31: *
32: * 08 Jan 1993 David Somayajulu at NeXT
33: * added functions is_dma_done, get_dma_addr, get_dma_count
34: *
35: * 13 July 1992 ? at NeXT
36: * Created.
37: */
38:
39: #import <mach/mach_types.h>
40:
41: #import <machdep/i386/dma.h>
42: #import <machdep/i386/dma_internal.h>
43: #import <machdep/i386/dma_inline.h>
44: #import <machdep/i386/dma_exported.h>
45:
46: struct _dma_chan_port _dma_chan_port[DMA_NCHAN] = {
47: {
48: DMA_CHAN0_ADDR_PORT,
49: DMA_CHAN0_PAGE_PORT, DMA_CHAN0_HIPAGE_PORT,
50: DMA_CHAN0_COUNT_PORT, DMA_CHAN0_HICOUNT_PORT },
51: {
52: DMA_CHAN1_ADDR_PORT,
53: DMA_CHAN1_PAGE_PORT, DMA_CHAN1_HIPAGE_PORT,
54: DMA_CHAN1_COUNT_PORT, DMA_CHAN1_HICOUNT_PORT },
55: {
56: DMA_CHAN2_ADDR_PORT,
57: DMA_CHAN2_PAGE_PORT, DMA_CHAN2_HIPAGE_PORT,
58: DMA_CHAN2_COUNT_PORT, DMA_CHAN2_HICOUNT_PORT },
59: {
60: DMA_CHAN3_ADDR_PORT,
61: DMA_CHAN3_PAGE_PORT, DMA_CHAN3_HIPAGE_PORT,
62: DMA_CHAN3_COUNT_PORT, DMA_CHAN3_HICOUNT_PORT },
63: {
64: /* CASCADE channel */
65: },
66: {
67: DMA2_CHAN1_ADDR_PORT,
68: DMA2_CHAN1_PAGE_PORT, DMA2_CHAN1_HIPAGE_PORT,
69: DMA2_CHAN1_COUNT_PORT, DMA2_CHAN1_HICOUNT_PORT },
70: {
71: DMA2_CHAN2_ADDR_PORT,
72: DMA2_CHAN2_PAGE_PORT, DMA2_CHAN2_HIPAGE_PORT,
73: DMA2_CHAN2_COUNT_PORT, DMA2_CHAN2_HICOUNT_PORT },
74: {
75: DMA2_CHAN3_ADDR_PORT,
76: DMA2_CHAN3_PAGE_PORT, DMA2_CHAN3_HIPAGE_PORT,
77: DMA2_CHAN3_COUNT_PORT, DMA2_CHAN3_HICOUNT_PORT },
78: };
79:
80: struct _dma_chip_port _dma_chip_port[] = {
81: {
82: DMA_CMD_STATUS_PORT, DMA_REQ_PORT, DMA_MASK_PORT, DMA_MODE_PORT,
83: DMA_CLEAR_FF_PORT, DMA_MASTER_RESET_PORT, DMA_EXTEND_MODE_PORT },
84: {
85: DMA2_CMD_STATUS_PORT, DMA2_REQ_PORT, DMA2_MASK_PORT, DMA2_MODE_PORT,
86: DMA2_CLEAR_FF_PORT, DMA2_MASTER_RESET_PORT, DMA2_EXTEND_MODE_PORT }
87: };
88:
89: unsigned char dma_assigned_bits;
90: struct dma_write_regs dma_write_regs[DMA_NCHAN];
91: dma_cmd_reg_t dma_cmd_regs[DMA_NCHIPS];
92:
93: unsigned prev_tcstatus0, /* previous transfer count status of
94: DMA Chip Port 0,for channels 0-3*/
95: prev_tcstatus1; /* previous transfer count status of
96: DMA Chip Port 1,for channels 5-7*/
97: /* The TC bits in the status register get cleared
98: when it is read. Hence we need to keep track of it
99: seperately */
100:
101: static void dma_init_extend_mode(int chan);
102:
103: #define PRIORITY_ROTATING 1
104:
105: void
106: dma_initialize(
107: void
108: )
109: {
110: dma_cmd_reg_t cmd = { 0 };
111: int chan;
112:
113: dma_master_reset();
114: prev_tcstatus0 = 0;
115: prev_tcstatus1 = 0;
116:
117: #if PRIORITY_ROTATING
118: cmd.priority = DMA_PRIO_ROTATING;
119: #else PRIORITY_ROTATING
120: cmd.priority = DMA_PRIO_FIXED;
121: #endif PRIORITY_ROTATING
122: dma_set_cmd(0, cmd);
123: dma_set_cmd(1, cmd);
124: dma_cmd_regs[0] = cmd;
125: dma_cmd_regs[1] = cmd;
126:
127: for (chan = 0; chan < DMA_NCHAN; chan++) {
128: (void) dma_assign_chan(chan);
129:
130: if (chan != DMA_CASCADE_CHAN) {
131: dma_deassign_chan(chan); // does an unmask
132: dma_init_extend_mode(chan);
133: }
134: else {
135: dma_chan_xfer_mode(chan, DMA_MODE_CASCADE);
136: dma_unmask_chan(chan); // unmask and leave
137: // assigned
138: }
139: }
140: dma_buf_initialize();
141: }
142:
143: /*
144: * Initialize extended mode register to defaults.
145: */
146: static void
147: dma_init_extend_mode(
148: int chan
149: )
150: {
151: dma_write_regs[chan].extend_mode.dma_timing =
152: DMA_TIMING_COMPAT;
153: dma_write_regs[chan].extend_mode.eop_io =
154: DMA_EOP_OUT;
155: dma_write_regs[chan].extend_mode.stop_enable =
156: DMA_STOP_DISABLE;
157: if (!eisa_present()) {
158: /* on ISA, use this to indicate transfer mode,
159: * but don't actually try to set the mode in hardware
160: */
161: if (chan < 4)
162: dma_write_regs[chan].extend_mode.xfer_width =
163: DMA_XFR_8_BIT;
164: else
165: dma_write_regs[chan].extend_mode.xfer_width =
166: DMA_XFR_16_BIT_WORD;
167: } else {
168: dma_write_regs[chan].extend_mode.xfer_width =
169: DMA_XFR_8_BIT;
170: dma_set_chan_extend_mode(chan, dma_write_regs[chan].extend_mode);
171: }
172: }
173: boolean_t
174: dma_assign_chan(
175: int chan
176: )
177: {
178: if (DMA_CHAN_IS_ASSIGNED(chan))
179: return (FALSE);
180:
181: dma_assigned_bits |= (1 << chan);
182:
183: return (TRUE);
184: }
185:
186: void
187: dma_deassign_chan(
188: int chan
189: )
190: {
191: dma_mask_chan(chan);
192:
193: dma_assigned_bits &= ~(1 << chan);
194: }
195:
196: void
197: dma_mask_chan(
198: int chan
199: )
200: {
201: dma_mask_reg_t mask = { 0 };
202:
203: if (!DMA_CHAN_IS_ASSIGNED(chan))
204: return;
205:
206: mask.mask = DMA_MASK_SET;
207: mask.chan_sel = chan;
208:
209: dma_set_chan_mask(chan, mask);
210: }
211:
212: void
213: dma_unmask_chan(
214: int chan
215: )
216: {
217: dma_mask_reg_t mask = { 0 };
218:
219: if (!DMA_CHAN_IS_ASSIGNED(chan))
220: return;
221:
222: mask.mask = DMA_MASK_CLEAR;
223: mask.chan_sel = chan;
224:
225: dma_set_chan_mask(chan, mask);
226: }
227:
228: void
229: dma_chan_xfer_mode(
230: int chan,
231: int xfer_mode
232: )
233: {
234: dma_mode_reg_t mode;
235:
236: if (!DMA_CHAN_IS_ASSIGNED(chan))
237: return;
238:
239: dma_write_regs[chan].mode.xfer_mode = xfer_mode;
240:
241: mode = dma_write_regs[chan].mode;
242: mode.chan_sel = chan;
243:
244: dma_set_chan_mode(chan, mode);
245: }
246:
247: void
248: dma_chan_autoinit(
249: int chan,
250: boolean_t autoinit)
251: {
252: dma_mode_reg_t mode;
253:
254: if (!DMA_CHAN_IS_ASSIGNED(chan))
255: return;
256:
257: dma_write_regs[chan].mode.autoinit = autoinit;
258: mode = dma_write_regs[chan].mode;
259: mode.chan_sel = chan;
260: dma_set_chan_mode(chan, mode);
261: }
262:
263: void
264: dma_chan_adrs_dir(
265: int chan,
266: boolean_t adrs_dir)
267: {
268: dma_mode_reg_t mode;
269:
270: if (!DMA_CHAN_IS_ASSIGNED(chan))
271: return;
272:
273: dma_write_regs[chan].mode.adrs_dir = adrs_dir ? 1 : 0;
274: mode = dma_write_regs[chan].mode;
275: mode.chan_sel = chan;
276: dma_set_chan_mode(chan, mode);
277: }
278:
279: void
280: dma_chan_xfer_dir(
281: int chan,
282: int xfer_dir
283: )
284: {
285: dma_mode_reg_t mode;
286:
287: if (!DMA_CHAN_IS_ASSIGNED(chan))
288: return;
289:
290: dma_write_regs[chan].mode.xfer_dir = xfer_dir;
291:
292: mode = dma_write_regs[chan].mode;
293: mode.chan_sel = chan;
294:
295: dma_set_chan_mode(chan, mode);
296: }
297:
298: boolean_t
299: dma_xfer_chan(
300: int chan,
301: dma_xfer_t *xfer
302: )
303: {
304: vm_offset_t phys;
305: extern boolean_t isEISA;
306:
307: // REMOVE THIS
308: caddr_t dma_addr;
309: unsigned dma_count;
310:
311:
312: if (!DMA_CHAN_IS_ASSIGNED(chan))
313: return (FALSE);
314:
315: if (!eisa_present())
316: xfer->lower16 = xfer->bound64 = TRUE;
317:
318: if (!dma_xfer(xfer, &phys))
319: return (FALSE);
320:
321: xfer->chan = chan; xfer->use_chan = TRUE;
322:
323: (void) dma_mask_chan(chan);
324:
325: if (xfer->read)
326: dma_chan_xfer_dir(chan, DMA_XFER_WRITE);/* dma write to memory */
327: else
328: dma_chan_xfer_dir(chan, DMA_XFER_READ);/* dma read from memory */
329:
330: dma_set_chan_addr(chan, phys);
331:
332: #if DMA_DEBUG
333: dma_addr = get_dma_addr(2);
334: dma_count = get_dma_count(2);
335: #endif
336: dma_set_chan_count(chan, xfer->len);
337:
338: #if DMA_DEBUG
339: dma_count = get_dma_count(2);
340: #endif
341: /*
342: * Clear the shadow "channel done" bit.
343: */
344: if(chan <= 3) {
345: prev_tcstatus0 &= ~(1 << chan);
346: }
347: else {
348: prev_tcstatus1 &= ~(1 << (chan - 4));
349: }
350: (void) dma_unmask_chan(chan);
351:
352: #if DMA_DEBUG
353: dma_count = get_dma_count(2);
354: #endif
355:
356: return (TRUE);
357: }
358:
359: boolean_t
360: dma_xfer(
361: dma_xfer_t *xfer,
362: vm_offset_t *rphys
363: )
364: {
365: dma_buf_t *buf = &xfer->buf;
366:
367: /* Allocate DMA-able memory if we need to,
368: * and if a buffer has not already been allocated for this xfer.
369: */
370: if (xfer->lower16 && ((xfer->phys )>= (16*1024*1024))
371: && !xfer->buffered) {
372: vm_offset_t phys;
373:
374: if (!dma_buf_alloc(buf, xfer->len))
375: return (FALSE);
376:
377: xfer->buffered = TRUE;
378:
379: phys = (vm_offset_t)buf->_ptr;
380:
381: if (!xfer->read)
382: bcopy(
383: pmap_phys_to_kern(xfer->phys),
384: pmap_phys_to_kern(phys),
385: xfer->len);
386:
387: *rphys = phys;
388: }
389: else
390: *rphys = xfer->phys;
391:
392: xfer->active = TRUE;
393:
394: return (TRUE);
395: }
396:
397: void
398: dma_xfer_done(
399: dma_xfer_t *xfer
400: )
401: {
402: if (xfer->active) {
403: if (xfer->buffered) {
404: dma_buf_t *buf = &xfer->buf;
405: vm_offset_t phys;
406:
407: phys = (vm_offset_t)buf->_ptr;
408:
409: if (xfer->read)
410: bcopy(
411: pmap_phys_to_kern(phys),
412: pmap_phys_to_kern(xfer->phys),
413: xfer->len);
414:
415: dma_buf_free(buf);
416: }
417:
418: xfer->active = xfer->buffered = FALSE;
419: }
420: }
421:
422: void
423: dma_xfer_abort(
424: dma_xfer_t *xfer
425: )
426: {
427: if (xfer->active) {
428: if (xfer->buffered)
429: dma_buf_free(&xfer->buf);
430:
431: xfer->active = xfer->buffered = FALSE;
432: }
433: }
434:
435: /*
436: * Extended Mode register manipulation
437: */
438: void
439: dma_xfer_width(
440: int chan,
441: int xfer_width
442: )
443: {
444: dma_extend_mode_reg_t extend_mode;
445:
446: if (!DMA_CHAN_IS_ASSIGNED(chan))
447: return;
448:
449: dma_write_regs[chan].extend_mode.xfer_width = xfer_width;
450: extend_mode = dma_write_regs[chan].extend_mode;
451: extend_mode.chan_sel = chan;
452: dma_set_chan_extend_mode(chan, extend_mode);
453: }
454:
455: /*
456: * Get the current transfer width for a channel.
457: */
458: int
459: get_dma_xfer_width(
460: int chan
461: )
462: {
463: if (!DMA_CHAN_IS_ASSIGNED(chan))
464: return -1;
465: return dma_write_regs[chan].extend_mode.xfer_width;
466: }
467:
468:
469: void
470: dma_timing(
471: int chan,
472: int dma_timing
473: )
474: {
475: dma_extend_mode_reg_t extend_mode;
476:
477: if (!DMA_CHAN_IS_ASSIGNED(chan))
478: return;
479:
480: dma_write_regs[chan].extend_mode.dma_timing = dma_timing;
481: extend_mode = dma_write_regs[chan].extend_mode;
482: extend_mode.chan_sel = chan;
483: dma_set_chan_extend_mode(chan, extend_mode);
484: }
485:
486: void
487: dma_eop_in(
488: int chan,
489: int eop_io
490: )
491: {
492: dma_extend_mode_reg_t extend_mode;
493:
494: if (!DMA_CHAN_IS_ASSIGNED(chan))
495: return;
496:
497: dma_write_regs[chan].extend_mode.eop_io = eop_io;
498: extend_mode = dma_write_regs[chan].extend_mode;
499: extend_mode.chan_sel = chan;
500: dma_set_chan_extend_mode(chan, extend_mode);
501: }
502:
503: void
504: dma_stop_enable(
505: int chan,
506: int stop_enable
507: )
508: {
509: dma_extend_mode_reg_t extend_mode;
510:
511: if (!DMA_CHAN_IS_ASSIGNED(chan))
512: return;
513:
514: dma_write_regs[chan].extend_mode.stop_enable = stop_enable;
515: extend_mode = dma_write_regs[chan].extend_mode;
516: extend_mode.chan_sel = chan;
517: dma_set_chan_extend_mode(chan, extend_mode);
518: }
519:
520: /* returns the status register contents for the corresponding channel */
521: boolean_t is_dma_done(int chan)
522: {
523: unsigned char status;
524:
525: DMA_DELAY;
526: status = (unsigned char)(inb(DMA_CHIP_PORT(chan, cmd_status)));
527:
528: /*
529: * Save the volatile bits we just read and OR in shadow
530: * bits for current test.
531: */
532: if (chan <= 3) {
533: prev_tcstatus0 |= (status & 0xf);
534: return (prev_tcstatus0 & (1 << chan)) ? TRUE : FALSE;
535:
536: }else {
537: chan = chan - 4;
538: prev_tcstatus1 |= (status & 0xf);
539: return (prev_tcstatus1 & (1 << chan)) ? TRUE : FALSE;
540: }
541: }
542:
543: vm_offset_t get_dma_addr(int chan)
544: {
545: union {
546: vm_offset_t addr;
547: struct {
548: vm_offset_t addr_byte0 :8,
549: addr_byte1 :8,
550: page :8,
551: hipage :8;
552: } data;
553: struct {
554: vm_offset_t addr :16,
555: page :8,
556: hipage :8;
557: } isa_data;
558: } tconv;
559: tconv.addr = 0;
560: dma_chip_disable(chan);
561:
562: DMA_DELAY;
563: outb(DMA_CHIP_PORT(chan, clear_ff), 0xff);
564: DMA_DELAY;
565: tconv.data.addr_byte0 = inb(DMA_CHAN_PORT(chan, addr));
566: dprintf(("reading from port =0x%x value = 0x%x\n",
567: DMA_CHAN_PORT(chan, addr), tconv.data.addr_byte0));
568: DMA_DELAY;
569: tconv.data.addr_byte1 = inb(DMA_CHAN_PORT(chan, addr));
570: dprintf(("reading from port =0x%x value = 0x%x\n",
571: DMA_CHAN_PORT(chan, addr), tconv.data.addr_byte1));
572: DMA_DELAY;
573: tconv.data.page = inb(DMA_CHAN_PORT(chan, page));
574: dprintf(("reading from port =0x%x value = 0x%x\n",
575: DMA_CHAN_PORT(chan, page), tconv.data.page));
576: if(eisa_present()){
577: DMA_DELAY;
578: tconv.data.hipage = inb(DMA_CHAN_PORT(chan, hipage));
579: dprintf(("reading from port =0x%x value = 0x%x\n",
580: DMA_CHAN_PORT(chan, hipage), tconv.data.hipage));
581: }
582: dma_chip_enable(chan);
583: if (dma_write_regs[chan].extend_mode.xfer_width ==
584: DMA_XFR_16_BIT_WORD) {
585: tconv.isa_data.addr <<= 1;
586: }
587: return(tconv.addr);
588: }
589:
590: vm_size_t get_dma_count(int chan)
591: {
592: union {
593: vm_size_t count;
594: struct {
595: vm_size_t count_byte0 :8,
596: count_byte1 :8,
597: hicount :8,
598: :8;
599: } data;
600: } tconv;
601:
602: dma_chip_disable(chan);
603: tconv.count = 0x00;
604: DMA_DELAY;
605: outb(DMA_CHIP_PORT(chan, clear_ff), 0xff);
606:
607: DMA_DELAY;
608: tconv.data.count_byte0 = inb(DMA_CHAN_PORT(chan, count));
609: dprintf(("reading from port =0x%x value = 0x%x\n",
610: DMA_CHAN_PORT(chan, count), tconv.data.count_byte0));
611:
612: DMA_DELAY;
613: tconv.data.count_byte1 = inb(DMA_CHAN_PORT(chan, count));
614: dprintf(("reading from port =0x%x value = 0x%x\n",
615: DMA_CHAN_PORT(chan, count), tconv.data.count_byte1));
616: if (eisa_present()){
617: tconv.data.hicount = inb(DMA_CHAN_PORT(chan, hicount));
618: dprintf(("reading from port =0x%x value = 0x%x\n",
619: DMA_CHAN_PORT(chan, hicount), tconv.data.hicount));
620: dma_chip_enable(chan);
621:
622: if (tconv.count == 0xFFFFFF) {
623: tconv.count = 0;
624: }
625: else {
626: ++tconv.count;
627: }
628: } else {
629: dma_chip_enable(chan);
630: if (tconv.count == 0xFFFF) {
631: tconv.count = 0;
632: }
633: else {
634: ++tconv.count;
635: }
636: }
637: if (dma_write_regs[chan].extend_mode.xfer_width ==
638: DMA_XFR_16_BIT_WORD) {
639: tconv.count <<= 1;
640: }
641:
642: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.