0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/ioport.h>
0017 #include <linux/init.h>
0018 #include <linux/dma-mapping.h>
0019 #include <linux/io.h>
0020
0021 #include <asm/dma.h>
0022 #include <asm/mach/dma.h>
0023
0024 #define ISA_DMA_MASK 0
0025 #define ISA_DMA_MODE 1
0026 #define ISA_DMA_CLRFF 2
0027 #define ISA_DMA_PGHI 3
0028 #define ISA_DMA_PGLO 4
0029 #define ISA_DMA_ADDR 5
0030 #define ISA_DMA_COUNT 6
0031
0032 static unsigned int isa_dma_port[8][7] = {
0033
0034 { 0x0a, 0x0b, 0x0c, 0x487, 0x087, 0x00, 0x01 },
0035 { 0x0a, 0x0b, 0x0c, 0x483, 0x083, 0x02, 0x03 },
0036 { 0x0a, 0x0b, 0x0c, 0x481, 0x081, 0x04, 0x05 },
0037 { 0x0a, 0x0b, 0x0c, 0x482, 0x082, 0x06, 0x07 },
0038 { 0xd4, 0xd6, 0xd8, 0x000, 0x000, 0xc0, 0xc2 },
0039 { 0xd4, 0xd6, 0xd8, 0x48b, 0x08b, 0xc4, 0xc6 },
0040 { 0xd4, 0xd6, 0xd8, 0x489, 0x089, 0xc8, 0xca },
0041 { 0xd4, 0xd6, 0xd8, 0x48a, 0x08a, 0xcc, 0xce }
0042 };
0043
0044 static int isa_get_dma_residue(unsigned int chan, dma_t *dma)
0045 {
0046 unsigned int io_port = isa_dma_port[chan][ISA_DMA_COUNT];
0047 int count;
0048
0049 count = 1 + inb(io_port);
0050 count |= inb(io_port) << 8;
0051
0052 return chan < 4 ? count : (count << 1);
0053 }
0054
0055 static struct device isa_dma_dev = {
0056 .init_name = "fallback device",
0057 .coherent_dma_mask = ~(dma_addr_t)0,
0058 .dma_mask = &isa_dma_dev.coherent_dma_mask,
0059 };
0060
0061 static void isa_enable_dma(unsigned int chan, dma_t *dma)
0062 {
0063 if (dma->invalid) {
0064 unsigned long address, length;
0065 unsigned int mode;
0066 enum dma_data_direction direction;
0067
0068 mode = (chan & 3) | dma->dma_mode;
0069 switch (dma->dma_mode & DMA_MODE_MASK) {
0070 case DMA_MODE_READ:
0071 direction = DMA_FROM_DEVICE;
0072 break;
0073
0074 case DMA_MODE_WRITE:
0075 direction = DMA_TO_DEVICE;
0076 break;
0077
0078 case DMA_MODE_CASCADE:
0079 direction = DMA_BIDIRECTIONAL;
0080 break;
0081
0082 default:
0083 direction = DMA_NONE;
0084 break;
0085 }
0086
0087 if (!dma->sg) {
0088
0089
0090
0091
0092 dma->sg = &dma->buf;
0093 dma->sgcount = 1;
0094 dma->buf.length = dma->count;
0095 dma->buf.dma_address = dma_map_single(&isa_dma_dev,
0096 dma->addr, dma->count,
0097 direction);
0098 }
0099
0100 address = dma->buf.dma_address;
0101 length = dma->buf.length - 1;
0102
0103 outb(address >> 16, isa_dma_port[chan][ISA_DMA_PGLO]);
0104 outb(address >> 24, isa_dma_port[chan][ISA_DMA_PGHI]);
0105
0106 if (chan >= 4) {
0107 address >>= 1;
0108 length >>= 1;
0109 }
0110
0111 outb(0, isa_dma_port[chan][ISA_DMA_CLRFF]);
0112
0113 outb(address, isa_dma_port[chan][ISA_DMA_ADDR]);
0114 outb(address >> 8, isa_dma_port[chan][ISA_DMA_ADDR]);
0115
0116 outb(length, isa_dma_port[chan][ISA_DMA_COUNT]);
0117 outb(length >> 8, isa_dma_port[chan][ISA_DMA_COUNT]);
0118
0119 outb(mode, isa_dma_port[chan][ISA_DMA_MODE]);
0120 dma->invalid = 0;
0121 }
0122 outb(chan & 3, isa_dma_port[chan][ISA_DMA_MASK]);
0123 }
0124
0125 static void isa_disable_dma(unsigned int chan, dma_t *dma)
0126 {
0127 outb(chan | 4, isa_dma_port[chan][ISA_DMA_MASK]);
0128 }
0129
0130 static struct dma_ops isa_dma_ops = {
0131 .type = "ISA",
0132 .enable = isa_enable_dma,
0133 .disable = isa_disable_dma,
0134 .residue = isa_get_dma_residue,
0135 };
0136
0137 static struct resource dma_resources[] = { {
0138 .name = "dma1",
0139 .start = 0x0000,
0140 .end = 0x000f
0141 }, {
0142 .name = "dma low page",
0143 .start = 0x0080,
0144 .end = 0x008f
0145 }, {
0146 .name = "dma2",
0147 .start = 0x00c0,
0148 .end = 0x00df
0149 }, {
0150 .name = "dma high page",
0151 .start = 0x0480,
0152 .end = 0x048f
0153 } };
0154
0155 static dma_t isa_dma[8];
0156
0157
0158
0159
0160 void __init isa_init_dma(void)
0161 {
0162
0163
0164
0165
0166
0167 outb(0xff, 0x0d);
0168 outb(0xff, 0xda);
0169
0170
0171
0172
0173
0174 outb(0x55, 0x00);
0175 outb(0xaa, 0x00);
0176
0177 if (inb(0) == 0x55 && inb(0) == 0xaa) {
0178 unsigned int chan, i;
0179
0180 for (chan = 0; chan < 8; chan++) {
0181 isa_dma[chan].d_ops = &isa_dma_ops;
0182 isa_disable_dma(chan, NULL);
0183 }
0184
0185 outb(0x40, 0x0b);
0186 outb(0x41, 0x0b);
0187 outb(0x42, 0x0b);
0188 outb(0x43, 0x0b);
0189
0190 outb(0xc0, 0xd6);
0191 outb(0x41, 0xd6);
0192 outb(0x42, 0xd6);
0193 outb(0x43, 0xd6);
0194
0195 outb(0, 0xd4);
0196
0197 outb(0x10, 0x08);
0198 outb(0x10, 0xd0);
0199
0200
0201
0202
0203
0204
0205 outb(0x30, 0x40b);
0206 outb(0x31, 0x40b);
0207 outb(0x32, 0x40b);
0208 outb(0x33, 0x40b);
0209 outb(0x31, 0x4d6);
0210 outb(0x32, 0x4d6);
0211 outb(0x33, 0x4d6);
0212
0213 for (i = 0; i < ARRAY_SIZE(dma_resources); i++)
0214 request_resource(&ioport_resource, dma_resources + i);
0215
0216 for (chan = 0; chan < 8; chan++) {
0217 int ret = isa_dma_add(chan, &isa_dma[chan]);
0218 if (ret)
0219 pr_err("ISADMA%u: unable to register: %d\n",
0220 chan, ret);
0221 }
0222
0223 request_dma(DMA_ISA_CASCADE, "cascade");
0224 }
0225 }