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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [arm/] [kernel/] [dma-isa.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/arch/arm/kernel/dma-isa.c
3
 *
4
 *  Copyright (C) 1999-2000 Russell King
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License version 2 as
8
 * published by the Free Software Foundation.
9
 *
10
 *  ISA DMA primitives
11
 *  Taken from various sources, including:
12
 *   linux/include/asm/dma.h: Defines for using and allocating dma channels.
13
 *     Written by Hennus Bergman, 1992.
14
 *     High DMA channel support & info by Hannu Savolainen and John Boyd,
15
 *     Nov. 1992.
16
 *   arch/arm/kernel/dma-ebsa285.c
17
 *   Copyright (C) 1998 Phil Blundell
18
 */
19
#include <linux/sched.h>
20
#include <linux/ioport.h>
21
#include <linux/init.h>
22
#include <linux/pci.h>
23
 
24
#include <asm/dma.h>
25
#include <asm/io.h>
26
 
27
#include <asm/mach/dma.h>
28
 
29
#define ISA_DMA_MODE_READ       0x44
30
#define ISA_DMA_MODE_WRITE      0x48
31
#define ISA_DMA_MODE_CASCADE    0xc0
32
#define ISA_DMA_AUTOINIT        0x10
33
 
34
#define ISA_DMA_MASK            0
35
#define ISA_DMA_MODE            1
36
#define ISA_DMA_CLRFF           2
37
#define ISA_DMA_PGHI            3
38
#define ISA_DMA_PGLO            4
39
#define ISA_DMA_ADDR            5
40
#define ISA_DMA_COUNT           6
41
 
42
static unsigned int isa_dma_port[8][7] = {
43
        /* MASK   MODE   CLRFF  PAGE_HI PAGE_LO ADDR COUNT */
44
        {  0x0a,  0x0b,  0x0c,  0x487,  0x087,  0x00, 0x01 },
45
        {  0x0a,  0x0b,  0x0c,  0x483,  0x083,  0x02, 0x03 },
46
        {  0x0a,  0x0b,  0x0c,  0x481,  0x081,  0x04, 0x05 },
47
        {  0x0a,  0x0b,  0x0c,  0x482,  0x082,  0x06, 0x07 },
48
        {  0xd4,  0xd6,  0xd8,  0x000,  0x000,  0xc0, 0xc2 },
49
        {  0xd4,  0xd6,  0xd8,  0x48b,  0x08b,  0xc4, 0xc6 },
50
        {  0xd4,  0xd6,  0xd8,  0x489,  0x089,  0xc8, 0xca },
51
        {  0xd4,  0xd6,  0xd8,  0x48a,  0x08a,  0xcc, 0xce }
52
};
53
 
54
static int isa_get_dma_residue(dmach_t channel, dma_t *dma)
55
{
56
        unsigned int io_port = isa_dma_port[channel][ISA_DMA_COUNT];
57
        int count;
58
 
59
        count = 1 + inb(io_port);
60
        count |= inb(io_port) << 8;
61
 
62
        return channel < 4 ? count : (count << 1);
63
}
64
 
65
static void isa_enable_dma(dmach_t channel, dma_t *dma)
66
{
67
        if (dma->invalid) {
68
                unsigned long address, length;
69
                unsigned int mode, direction;
70
 
71
                mode = channel & 3;
72
                switch (dma->dma_mode & DMA_MODE_MASK) {
73
                case DMA_MODE_READ:
74
                        mode |= ISA_DMA_MODE_READ;
75
                        direction = PCI_DMA_FROMDEVICE;
76
                        break;
77
 
78
                case DMA_MODE_WRITE:
79
                        mode |= ISA_DMA_MODE_WRITE;
80
                        direction = PCI_DMA_TODEVICE;
81
                        break;
82
 
83
                case DMA_MODE_CASCADE:
84
                        mode |= ISA_DMA_MODE_CASCADE;
85
                        direction = PCI_DMA_BIDIRECTIONAL;
86
                        break;
87
 
88
                default:
89
                        break;
90
                }
91
 
92
                if (!dma->using_sg) {
93
                        /*
94
                         * Cope with ISA-style drivers which expect cache
95
                         * coherence.
96
                         */
97
                        dma->buf.dma_address = pci_map_single(NULL,
98
                                dma->buf.address, dma->buf.length,
99
                                direction);
100
                }
101
 
102
                address = dma->buf.dma_address;
103
                length  = dma->buf.length - 1;
104
 
105
                outb(address >> 16, isa_dma_port[channel][ISA_DMA_PGLO]);
106
                outb(address >> 24, isa_dma_port[channel][ISA_DMA_PGHI]);
107
 
108
                if (channel >= 4) {
109
                        address >>= 1;
110
                        length >>= 1;
111
                }
112
 
113
                outb(0, isa_dma_port[channel][ISA_DMA_CLRFF]);
114
 
115
                outb(address, isa_dma_port[channel][ISA_DMA_ADDR]);
116
                outb(address >> 8, isa_dma_port[channel][ISA_DMA_ADDR]);
117
 
118
                outb(length, isa_dma_port[channel][ISA_DMA_COUNT]);
119
                outb(length >> 8, isa_dma_port[channel][ISA_DMA_COUNT]);
120
 
121
                if (dma->dma_mode & DMA_AUTOINIT)
122
                        mode |= ISA_DMA_AUTOINIT;
123
 
124
                outb(mode, isa_dma_port[channel][ISA_DMA_MODE]);
125
                dma->invalid = 0;
126
        }
127
        outb(channel & 3, isa_dma_port[channel][ISA_DMA_MASK]);
128
}
129
 
130
static void isa_disable_dma(dmach_t channel, dma_t *dma)
131
{
132
        outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]);
133
}
134
 
135
static struct dma_ops isa_dma_ops = {
136
        .type           = "ISA",
137
        .enable         = isa_enable_dma,
138
        .disable        = isa_disable_dma,
139
        .residue        = isa_get_dma_residue,
140
};
141
 
142
static struct resource dma_resources[] = {
143
        { "dma1",               0x0000, 0x000f },
144
        { "dma low page",       0x0080, 0x008f },
145
        { "dma2",               0x00c0, 0x00df },
146
        { "dma high page",      0x0480, 0x048f }
147
};
148
 
149
void __init isa_init_dma(dma_t *dma)
150
{
151
        /*
152
         * Try to autodetect presence of an ISA DMA controller.
153
         * We do some minimal initialisation, and check that
154
         * channel 0's DMA address registers are writeable.
155
         */
156
        outb(0xff, 0x0d);
157
        outb(0xff, 0xda);
158
 
159
        /*
160
         * Write high and low address, and then read them back
161
         * in the same order.
162
         */
163
        outb(0x55, 0x00);
164
        outb(0xaa, 0x00);
165
 
166
        if (inb(0) == 0x55 && inb(0) == 0xaa) {
167
                int channel, i;
168
 
169
                for (channel = 0; channel < 8; channel++) {
170
                        dma[channel].d_ops = &isa_dma_ops;
171
                        isa_disable_dma(channel, NULL);
172
                }
173
 
174
                outb(0x40, 0x0b);
175
                outb(0x41, 0x0b);
176
                outb(0x42, 0x0b);
177
                outb(0x43, 0x0b);
178
 
179
                outb(0xc0, 0xd6);
180
                outb(0x41, 0xd6);
181
                outb(0x42, 0xd6);
182
                outb(0x43, 0xd6);
183
 
184
                outb(0, 0xd4);
185
 
186
                outb(0x10, 0x08);
187
                outb(0x10, 0xd0);
188
 
189
                /*
190
                 * Is this correct?  According to my documentation, it
191
                 * doesn't appear to be.  It should be:
192
                 *  outb(0x3f, 0x40b); outb(0x3f, 0x4d6);
193
                 */
194
                outb(0x30, 0x40b);
195
                outb(0x31, 0x40b);
196
                outb(0x32, 0x40b);
197
                outb(0x33, 0x40b);
198
                outb(0x31, 0x4d6);
199
                outb(0x32, 0x4d6);
200
                outb(0x33, 0x4d6);
201
 
202
                request_dma(DMA_ISA_CASCADE, "cascade");
203
 
204
                for (i = 0; i < sizeof(dma_resources) / sizeof(dma_resources[0]); i++)
205
                        request_resource(&ioport_resource, dma_resources + i);
206
        }
207
}

powered by: WebSVN 2.1.0

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