aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/dma-isa.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/dma-isa.c')
-rw-r--r--arch/arm/kernel/dma-isa.c67
1 files changed, 34 insertions, 33 deletions
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
index 4a3a50495c60..0e88e46fc732 100644
--- a/arch/arm/kernel/dma-isa.c
+++ b/arch/arm/kernel/dma-isa.c
@@ -24,11 +24,6 @@
24#include <asm/dma.h> 24#include <asm/dma.h>
25#include <asm/mach/dma.h> 25#include <asm/mach/dma.h>
26 26
27#define ISA_DMA_MODE_READ 0x44
28#define ISA_DMA_MODE_WRITE 0x48
29#define ISA_DMA_MODE_CASCADE 0xc0
30#define ISA_DMA_AUTOINIT 0x10
31
32#define ISA_DMA_MASK 0 27#define ISA_DMA_MASK 0
33#define ISA_DMA_MODE 1 28#define ISA_DMA_MODE 1
34#define ISA_DMA_CLRFF 2 29#define ISA_DMA_CLRFF 2
@@ -49,38 +44,35 @@ static unsigned int isa_dma_port[8][7] = {
49 { 0xd4, 0xd6, 0xd8, 0x48a, 0x08a, 0xcc, 0xce } 44 { 0xd4, 0xd6, 0xd8, 0x48a, 0x08a, 0xcc, 0xce }
50}; 45};
51 46
52static int isa_get_dma_residue(dmach_t channel, dma_t *dma) 47static int isa_get_dma_residue(unsigned int chan, dma_t *dma)
53{ 48{
54 unsigned int io_port = isa_dma_port[channel][ISA_DMA_COUNT]; 49 unsigned int io_port = isa_dma_port[chan][ISA_DMA_COUNT];
55 int count; 50 int count;
56 51
57 count = 1 + inb(io_port); 52 count = 1 + inb(io_port);
58 count |= inb(io_port) << 8; 53 count |= inb(io_port) << 8;
59 54
60 return channel < 4 ? count : (count << 1); 55 return chan < 4 ? count : (count << 1);
61} 56}
62 57
63static void isa_enable_dma(dmach_t channel, dma_t *dma) 58static void isa_enable_dma(unsigned int chan, dma_t *dma)
64{ 59{
65 if (dma->invalid) { 60 if (dma->invalid) {
66 unsigned long address, length; 61 unsigned long address, length;
67 unsigned int mode; 62 unsigned int mode;
68 enum dma_data_direction direction; 63 enum dma_data_direction direction;
69 64
70 mode = channel & 3; 65 mode = (chan & 3) | dma->dma_mode;
71 switch (dma->dma_mode & DMA_MODE_MASK) { 66 switch (dma->dma_mode & DMA_MODE_MASK) {
72 case DMA_MODE_READ: 67 case DMA_MODE_READ:
73 mode |= ISA_DMA_MODE_READ;
74 direction = DMA_FROM_DEVICE; 68 direction = DMA_FROM_DEVICE;
75 break; 69 break;
76 70
77 case DMA_MODE_WRITE: 71 case DMA_MODE_WRITE:
78 mode |= ISA_DMA_MODE_WRITE;
79 direction = DMA_TO_DEVICE; 72 direction = DMA_TO_DEVICE;
80 break; 73 break;
81 74
82 case DMA_MODE_CASCADE: 75 case DMA_MODE_CASCADE:
83 mode |= ISA_DMA_MODE_CASCADE;
84 direction = DMA_BIDIRECTIONAL; 76 direction = DMA_BIDIRECTIONAL;
85 break; 77 break;
86 78
@@ -105,34 +97,31 @@ static void isa_enable_dma(dmach_t channel, dma_t *dma)
105 address = dma->buf.dma_address; 97 address = dma->buf.dma_address;
106 length = dma->buf.length - 1; 98 length = dma->buf.length - 1;
107 99
108 outb(address >> 16, isa_dma_port[channel][ISA_DMA_PGLO]); 100 outb(address >> 16, isa_dma_port[chan][ISA_DMA_PGLO]);
109 outb(address >> 24, isa_dma_port[channel][ISA_DMA_PGHI]); 101 outb(address >> 24, isa_dma_port[chan][ISA_DMA_PGHI]);
110 102
111 if (channel >= 4) { 103 if (chan >= 4) {
112 address >>= 1; 104 address >>= 1;
113 length >>= 1; 105 length >>= 1;
114 } 106 }
115 107
116 outb(0, isa_dma_port[channel][ISA_DMA_CLRFF]); 108 outb(0, isa_dma_port[chan][ISA_DMA_CLRFF]);
117
118 outb(address, isa_dma_port[channel][ISA_DMA_ADDR]);
119 outb(address >> 8, isa_dma_port[channel][ISA_DMA_ADDR]);
120 109
121 outb(length, isa_dma_port[channel][ISA_DMA_COUNT]); 110 outb(address, isa_dma_port[chan][ISA_DMA_ADDR]);
122 outb(length >> 8, isa_dma_port[channel][ISA_DMA_COUNT]); 111 outb(address >> 8, isa_dma_port[chan][ISA_DMA_ADDR]);
123 112
124 if (dma->dma_mode & DMA_AUTOINIT) 113 outb(length, isa_dma_port[chan][ISA_DMA_COUNT]);
125 mode |= ISA_DMA_AUTOINIT; 114 outb(length >> 8, isa_dma_port[chan][ISA_DMA_COUNT]);
126 115
127 outb(mode, isa_dma_port[channel][ISA_DMA_MODE]); 116 outb(mode, isa_dma_port[chan][ISA_DMA_MODE]);
128 dma->invalid = 0; 117 dma->invalid = 0;
129 } 118 }
130 outb(channel & 3, isa_dma_port[channel][ISA_DMA_MASK]); 119 outb(chan & 3, isa_dma_port[chan][ISA_DMA_MASK]);
131} 120}
132 121
133static void isa_disable_dma(dmach_t channel, dma_t *dma) 122static void isa_disable_dma(unsigned int chan, dma_t *dma)
134{ 123{
135 outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]); 124 outb(chan | 4, isa_dma_port[chan][ISA_DMA_MASK]);
136} 125}
137 126
138static struct dma_ops isa_dma_ops = { 127static struct dma_ops isa_dma_ops = {
@@ -160,7 +149,12 @@ static struct resource dma_resources[] = { {
160 .end = 0x048f 149 .end = 0x048f
161} }; 150} };
162 151
163void __init isa_init_dma(dma_t *dma) 152static dma_t isa_dma[8];
153
154/*
155 * ISA DMA always starts at channel 0
156 */
157void __init isa_init_dma(void)
164{ 158{
165 /* 159 /*
166 * Try to autodetect presence of an ISA DMA controller. 160 * Try to autodetect presence of an ISA DMA controller.
@@ -178,11 +172,11 @@ void __init isa_init_dma(dma_t *dma)
178 outb(0xaa, 0x00); 172 outb(0xaa, 0x00);
179 173
180 if (inb(0) == 0x55 && inb(0) == 0xaa) { 174 if (inb(0) == 0x55 && inb(0) == 0xaa) {
181 int channel, i; 175 unsigned int chan, i;
182 176
183 for (channel = 0; channel < 8; channel++) { 177 for (chan = 0; chan < 8; chan++) {
184 dma[channel].d_ops = &isa_dma_ops; 178 isa_dma[chan].d_ops = &isa_dma_ops;
185 isa_disable_dma(channel, NULL); 179 isa_disable_dma(chan, NULL);
186 } 180 }
187 181
188 outb(0x40, 0x0b); 182 outb(0x40, 0x0b);
@@ -217,5 +211,12 @@ void __init isa_init_dma(dma_t *dma)
217 211
218 for (i = 0; i < ARRAY_SIZE(dma_resources); i++) 212 for (i = 0; i < ARRAY_SIZE(dma_resources); i++)
219 request_resource(&ioport_resource, dma_resources + i); 213 request_resource(&ioport_resource, dma_resources + i);
214
215 for (chan = 0; chan < 8; chan++) {
216 int ret = isa_dma_add(chan, &isa_dma[chan]);
217 if (ret)
218 printk(KERN_ERR "ISADMA%u: unable to register: %d\n",
219 chan, ret);
220 }
220 } 221 }
221} 222}