OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [armnommu/] [kernel/] [dma-rpc.c] - Blame information for rev 1622

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1622 jcastillo
/*
2
 * arch/arm/kernel/dma-rpc.c
3
 *
4
 * Copyright (C) 1998 Russell King
5
 *
6
 * DMA functions specific to RiscPC architecture
7
 */
8
#include <linux/sched.h>
9
#include <linux/malloc.h>
10
#include <linux/mman.h>
11
 
12
#include <asm/page.h>
13
#include <asm/pgtable.h>
14
#include <asm/dma.h>
15
#include <asm/io.h>
16
#include <asm/hardware.h>
17
 
18
#include "dma.h"
19
 
20
#if 0
21
typedef enum {
22
        dma_size_8      = 1,
23
        dma_size_16     = 2,
24
        dma_size_32     = 4,
25
        dma_size_128    = 16
26
} dma_size_t;
27
 
28
typedef struct {
29
        dma_size_t      transfersize;
30
} dma_t;
31
#endif
32
 
33
#define TRANSFER_SIZE   2
34
 
35
#define CURA    (0)
36
#define ENDA    ((IOMD_IO0ENDA - IOMD_IO0CURA) << 2)
37
#define CURB    ((IOMD_IO0CURB - IOMD_IO0CURA) << 2)
38
#define ENDB    ((IOMD_IO0ENDB - IOMD_IO0CURA) << 2)
39
#define CR      ((IOMD_IO0CR - IOMD_IO0CURA) << 2)
40
#define ST      ((IOMD_IO0ST - IOMD_IO0CURA) << 2)
41
 
42
#define state_prog_a    0
43
#define state_wait_a    1
44
#define state_wait_b    2
45
 
46
static void arch_get_next_sg(dmasg_t *sg, dma_t *dma)
47
{
48
        unsigned long end, offset, flags = 0;
49
 
50
        if (dma->sg) {
51
                sg->address = dma->sg->address;
52
                offset = sg->address & ~PAGE_MASK;
53
 
54
                end = offset + dma->sg->length;
55
 
56
                if (end > PAGE_SIZE)
57
                        end = PAGE_SIZE;
58
 
59
                if (offset + (int) TRANSFER_SIZE > end)
60
                        flags |= DMA_END_L;
61
 
62
                sg->length = end - TRANSFER_SIZE;
63
 
64
                dma->sg->length -= end - offset;
65
                dma->sg->address += end - offset;
66
 
67
                if (dma->sg->length == 0) {
68
                        if (dma->sgcount > 1) {
69
                                dma->sg++;
70
                                dma->sgcount--;
71
                        } else {
72
                                dma->sg = NULL;
73
                                flags |= DMA_END_S;
74
                        }
75
                }
76
        } else {
77
                flags = DMA_END_S | DMA_END_L;
78
                sg->address = 0;
79
                sg->length = 0;
80
        }
81
 
82
        sg->length |= flags;
83
}
84
 
85
static inline void arch_setup_dma_a(dmasg_t *sg, dma_t *dma)
86
{
87
        outl_t(sg->address, dma->dma_base + CURA);
88
        outl_t(sg->length, dma->dma_base + ENDA);
89
}
90
 
91
static inline void arch_setup_dma_b(dmasg_t *sg, dma_t *dma)
92
{
93
        outl_t(sg->address, dma->dma_base + CURB);
94
        outl_t(sg->length, dma->dma_base + ENDB);
95
}
96
 
97
static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
98
{
99
        dma_t *dma = (dma_t *)dev_id;
100
        unsigned int status = 0, no_buffer = dma->sg == NULL;
101
 
102
        do {
103
                switch (dma->state) {
104
                case state_prog_a:
105
                        arch_get_next_sg(&dma->cur_sg, dma);
106
                        arch_setup_dma_a(&dma->cur_sg, dma);
107
                        dma->state = state_wait_a;
108
 
109
                case state_wait_a:
110
                        status = inb_t(dma->dma_base + ST);
111
                        switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
112
                        case DMA_ST_OFL|DMA_ST_INT:
113
                                arch_get_next_sg(&dma->cur_sg, dma);
114
                                arch_setup_dma_a(&dma->cur_sg, dma);
115
                                break;
116
 
117
                        case DMA_ST_INT:
118
                                arch_get_next_sg(&dma->cur_sg, dma);
119
                                arch_setup_dma_b(&dma->cur_sg, dma);
120
                                dma->state = state_wait_b;
121
                                break;
122
 
123
                        case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB:
124
                                arch_setup_dma_b(&dma->cur_sg, dma);
125
                                dma->state = state_wait_b;
126
                                break;
127
                        }
128
                        break;
129
 
130
                case state_wait_b:
131
                        status = inb_t(dma->dma_base + ST);
132
                        switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
133
                        case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB:
134
                                arch_get_next_sg(&dma->cur_sg, dma);
135
                                arch_setup_dma_b(&dma->cur_sg, dma);
136
                                break;
137
 
138
                        case DMA_ST_INT|DMA_ST_AB:
139
                                arch_get_next_sg(&dma->cur_sg, dma);
140
                                arch_setup_dma_a(&dma->cur_sg, dma);
141
                                dma->state = state_wait_a;
142
                                break;
143
 
144
                        case DMA_ST_OFL|DMA_ST_INT:
145
                                arch_setup_dma_a(&dma->cur_sg, dma);
146
                                dma->state = state_wait_a;
147
                                break;
148
                        }
149
                        break;
150
                }
151
        } while (dma->sg && (status & DMA_ST_INT));
152
 
153
        if (!no_buffer)
154
                enable_irq(irq);
155
}
156
 
157
int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
158
{
159
        unsigned long flags;
160
        int ret;
161
 
162
        switch (channel) {
163
        case DMA_0:
164
        case DMA_1:
165
        case DMA_2:
166
        case DMA_3:
167
        case DMA_S0:
168
        case DMA_S1:
169
                save_flags_cli(flags);
170
                ret = request_irq(dma->dma_irq, arch_dma_handle, SA_INTERRUPT, dev_name, dma);
171
                if (!ret)
172
                        disable_irq(dma->dma_irq);
173
                restore_flags(flags);
174
                break;
175
 
176
        case DMA_VIRTUAL_FLOPPY:
177
                ret = 0;
178
                break;
179
 
180
        case DMA_VIRTUAL_SOUND:
181
                ret = 0;
182
                break;
183
 
184
        default:
185
                ret = -EINVAL;
186
                break;
187
        }
188
 
189
        return ret;
190
}
191
 
192
void arch_free_dma(dmach_t channel, dma_t *dma)
193
{
194
        switch (channel) {
195
        case DMA_0:
196
        case DMA_1:
197
        case DMA_2:
198
        case DMA_3:
199
        case DMA_S0:
200
        case DMA_S1:
201
                free_irq(dma->dma_irq, dma);
202
                break;
203
 
204
        default:
205
                break;
206
        }
207
}
208
 
209
int arch_get_dma_residue(dmach_t channel, dma_t *dma)
210
{
211
        int residue = 0;
212
 
213
        switch (channel) {
214
        case DMA_0:     /* Physical DMA channels */
215
        case DMA_1:
216
        case DMA_2:
217
        case DMA_3:
218
        case DMA_S0:
219
        case DMA_S1:
220
                break;
221
 
222
        case DMA_VIRTUAL_FLOPPY: {
223
                extern int floppy_fiqresidual(void);
224
                residue = floppy_fiqresidual();
225
                }
226
                break;
227
        }
228
        return residue;
229
}
230
 
231
void arch_enable_dma(dmach_t channel, dma_t *dma)
232
{
233
        unsigned long dma_base = dma->dma_base;
234
        unsigned int ctrl;
235
 
236
        switch (channel) {
237
        case DMA_0:     /* Physical DMA channels */
238
        case DMA_1:
239
        case DMA_2:
240
        case DMA_3:
241
        case DMA_S0:
242
        case DMA_S1:
243
                ctrl = TRANSFER_SIZE | DMA_CR_E;
244
 
245
                if (dma->invalid) {
246
                        dma->invalid = 0;
247
 
248
                        outb_t(DMA_CR_C, dma_base + CR);
249
                        dma->state = state_prog_a;
250
                }
251
 
252
                if (dma->dma_mode == DMA_MODE_READ)
253
                        ctrl |= DMA_CR_D;
254
 
255
                outb_t(ctrl, dma_base + CR);
256
                enable_irq(dma->dma_irq);
257
                break;
258
 
259
        case DMA_VIRTUAL_FLOPPY: {
260
                void *fiqhandler_start;
261
                unsigned int fiqhandler_length;
262
                extern void floppy_fiqsetup(unsigned long len, unsigned long addr,
263
                                             unsigned long port);
264
 
265
                if (dma->dma_mode == DMA_MODE_READ) {
266
                        extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
267
                        fiqhandler_start = &floppy_fiqin_start;
268
                        fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
269
                } else {
270
                        extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
271
                        fiqhandler_start = &floppy_fiqout_start;
272
                        fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
273
                }
274
                memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length);
275
                flush_page_to_ram(0);
276
                floppy_fiqsetup(dma->buf.length, __bus_to_virt(dma->buf.address), (int)PCIO_FLOPPYDMABASE);
277
                enable_irq(dma->dma_irq);
278
                }
279
                break;
280
 
281
        default:
282
                break;
283
        }
284
}
285
 
286
void arch_disable_dma(dmach_t channel, dma_t *dma)
287
{
288
        unsigned long dma_base = dma->dma_base;
289
        unsigned int ctrl;
290
 
291
        switch (channel) {
292
        case DMA_0:     /* Physical DMA channels */
293
        case DMA_1:
294
        case DMA_2:
295
        case DMA_3:
296
        case DMA_S0:
297
        case DMA_S1:
298
                disable_irq(dma->dma_irq);
299
                ctrl = inb_t(dma_base + CR);
300
                outb_t(ctrl & ~DMA_CR_E, dma_base + CR);
301
                break;
302
 
303
        case DMA_VIRTUAL_FLOPPY:
304
                disable_irq(dma->dma_irq);
305
                break;
306
        }
307
}
308
 
309
void arch_dma_init(dma_t *dma)
310
{
311
        outb(0, IOMD_IO0CR);
312
        outb(0, IOMD_IO1CR);
313
        outb(0, IOMD_IO2CR);
314
        outb(0, IOMD_IO3CR);
315
 
316
//      outb(0xf0, IOMD_DMATCR);
317
 
318
        dma[0].dma_base = ioaddr(IOMD_IO0CURA);
319
        dma[0].dma_irq  = IRQ_DMA0;
320
        dma[1].dma_base = ioaddr(IOMD_IO1CURA);
321
        dma[1].dma_irq  = IRQ_DMA1;
322
        dma[2].dma_base = ioaddr(IOMD_IO2CURA);
323
        dma[2].dma_irq  = IRQ_DMA2;
324
        dma[3].dma_base = ioaddr(IOMD_IO3CURA);
325
        dma[3].dma_irq  = IRQ_DMA3;
326
        dma[4].dma_base = ioaddr(IOMD_SD0CURA);
327
        dma[4].dma_irq  = IRQ_DMAS0;
328
        dma[5].dma_base = ioaddr(IOMD_SD1CURA);
329
        dma[5].dma_irq  = IRQ_DMAS1;
330
        dma[6].dma_irq  = 64;
331
 
332
        /* Setup DMA channels 2,3 to be for podules
333
         * and channels 0,1 for internal devices
334
         */
335
        outb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
336
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.