specific VGA BIOS for Cirrus VGA Card
[qemu] / hw / dma.c
1 /*
2  * QEMU DMA emulation
3  * 
4  * Copyright (c) 2003 Vassili Karpov (malc)
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "vl.h"
25
26 #define log(...) fprintf (stderr, "dma: " __VA_ARGS__)
27 #ifdef DEBUG_DMA
28 #define lwarn(...) fprintf (stderr, "dma: " __VA_ARGS__)
29 #define linfo(...) fprintf (stderr, "dma: " __VA_ARGS__)
30 #define ldebug(...) fprintf (stderr, "dma: " __VA_ARGS__)
31 #else
32 #define lwarn(...)
33 #define linfo(...)
34 #define ldebug(...)
35 #endif
36
37 #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
38
39 struct dma_regs {
40     int now[2];
41     uint16_t base[2];
42     uint8_t mode;
43     uint8_t page;
44     uint8_t dack;
45     uint8_t eop;
46     DMA_transfer_handler transfer_handler;
47     void *opaque;
48 };
49
50 #define ADDR 0
51 #define COUNT 1
52
53 static struct dma_cont {
54     uint8_t status;
55     uint8_t command;
56     uint8_t mask;
57     uint8_t flip_flop;
58     int dshift;
59     struct dma_regs regs[4];
60 } dma_controllers[2];
61
62 enum {
63   CMD_MEMORY_TO_MEMORY = 0x01,
64   CMD_FIXED_ADDRESS    = 0x02,
65   CMD_BLOCK_CONTROLLER = 0x04,
66   CMD_COMPRESSED_TIME  = 0x08,
67   CMD_CYCLIC_PRIORITY  = 0x10,
68   CMD_EXTENDED_WRITE   = 0x20,
69   CMD_LOW_DREQ         = 0x40,
70   CMD_LOW_DACK         = 0x80,
71   CMD_NOT_SUPPORTED    = CMD_MEMORY_TO_MEMORY | CMD_FIXED_ADDRESS
72   | CMD_COMPRESSED_TIME | CMD_CYCLIC_PRIORITY | CMD_EXTENDED_WRITE
73   | CMD_LOW_DREQ | CMD_LOW_DACK
74
75 };
76
77 static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
78
79 static void write_page (void *opaque, uint32_t nport, uint32_t data)
80 {
81     struct dma_cont *d = opaque;
82     int ichan;
83
84     ichan = channels[nport & 7];
85
86     if (-1 == ichan) {
87         log ("invalid channel %#x %#x\n", nport, data);
88         return;
89     }
90     d->regs[ichan].page = data;
91 }
92
93 static uint32_t read_page (void *opaque, uint32_t nport)
94 {
95     struct dma_cont *d = opaque;
96     int ichan;
97
98     ichan = channels[nport & 7];
99
100     if (-1 == ichan) {
101         log ("invalid channel read %#x\n", nport);
102         return 0;
103     }
104     return d->regs[ichan].page;
105 }
106
107 static inline void init_chan (struct dma_cont *d, int ichan)
108 {
109     struct dma_regs *r;
110
111     r = d->regs + ichan;
112     r->now[ADDR] = r->base[0] << d->dshift;
113     r->now[COUNT] = 0;
114 }
115
116 static inline int getff (struct dma_cont *d)
117 {
118     int ff;
119
120     ff = d->flip_flop;
121     d->flip_flop = !ff;
122     return ff;
123 }
124
125 static uint32_t read_chan (void *opaque, uint32_t nport)
126 {
127     struct dma_cont *d = opaque;
128     int ichan, nreg, iport, ff, val;
129     struct dma_regs *r;
130
131     iport = (nport >> d->dshift) & 0x0f;
132     ichan = iport >> 1;
133     nreg = iport & 1;
134     r = d->regs + ichan;
135
136     ff = getff (d);
137     if (nreg)
138         val = (r->base[COUNT] << d->dshift) - r->now[COUNT];
139     else
140         val = r->now[ADDR] + r->now[COUNT];
141
142     return (val >> (d->dshift + (ff << 3))) & 0xff;
143 }
144
145 static void write_chan (void *opaque, uint32_t nport, uint32_t data)
146 {
147     struct dma_cont *d = opaque;
148     int iport, ichan, nreg;
149     struct dma_regs *r;
150
151     iport = (nport >> d->dshift) & 0x0f;
152     ichan = iport >> 1;
153     nreg = iport & 1;
154     r = d->regs + ichan;
155     if (getff (d)) {
156         r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
157         init_chan (d, ichan);
158     } else {
159         r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
160     }
161 }
162
163 static void write_cont (void *opaque, uint32_t nport, uint32_t data)
164 {
165     struct dma_cont *d = opaque;
166     int iport, ichan;
167
168     iport = (nport >> d->dshift) & 0x0f;
169     switch (iport) {
170     case 8:                     /* command */
171         if ((data != 0) && (data & CMD_NOT_SUPPORTED)) {
172             log ("command %#x not supported\n", data);
173             return;
174         }
175         d->command = data;
176         break;
177
178     case 9:
179         ichan = data & 3;
180         if (data & 4) {
181             d->status |= 1 << (ichan + 4);
182         }
183         else {
184             d->status &= ~(1 << (ichan + 4));
185         }
186         d->status &= ~(1 << ichan);
187         break;
188
189     case 0xa:                   /* single mask */
190         if (data & 4)
191             d->mask |= 1 << (data & 3);
192         else
193             d->mask &= ~(1 << (data & 3));
194         break;
195
196     case 0xb:                   /* mode */
197         {
198             ichan = data & 3;
199 #ifdef DEBUG_DMA
200             int op;
201             int ai;
202             int dir;
203             int opmode;
204
205             op = (data >> 2) & 3;
206             ai = (data >> 4) & 1;
207             dir = (data >> 5) & 1;
208             opmode = (data >> 6) & 3;
209
210             linfo ("ichan %d, op %d, ai %d, dir %d, opmode %d\n",
211                    ichan, op, ai, dir, opmode);
212 #endif
213
214             d->regs[ichan].mode = data;
215             break;
216         }
217
218     case 0xc:                   /* clear flip flop */
219         d->flip_flop = 0;
220         break;
221
222     case 0xd:                   /* reset */
223         d->flip_flop = 0;
224         d->mask = ~0;
225         d->status = 0;
226         d->command = 0;
227         break;
228
229     case 0xe:                   /* clear mask for all channels */
230         d->mask = 0;
231         break;
232
233     case 0xf:                   /* write mask for all channels */
234         d->mask = data;
235         break;
236
237     default:
238         log ("dma: unknown iport %#x\n", iport);
239         break;
240     }
241
242 #ifdef DEBUG_DMA
243     if (0xc != iport) {
244         linfo ("nport %#06x, ichan % 2d, val %#06x\n",
245                nport, ichan, data);
246     }
247 #endif
248 }
249
250 static uint32_t read_cont (void *opaque, uint32_t nport)
251 {
252     struct dma_cont *d = opaque;
253     int iport, val;
254     
255     iport = (nport >> d->dshift) & 0x0f;
256     switch (iport) {
257     case 0x08: /* status */
258         val = d->status;
259         d->status &= 0xf0;
260         break;
261     case 0x0f: /* mask */
262         val = d->mask;
263         break;
264     default:
265         val = 0;
266         break;
267     }
268     return val;
269 }
270
271 int DMA_get_channel_mode (int nchan)
272 {
273     return dma_controllers[nchan > 3].regs[nchan & 3].mode;
274 }
275
276 void DMA_hold_DREQ (int nchan)
277 {
278     int ncont, ichan;
279
280     ncont = nchan > 3;
281     ichan = nchan & 3;
282     linfo ("held cont=%d chan=%d\n", ncont, ichan);
283     dma_controllers[ncont].status |= 1 << (ichan + 4);
284 }
285
286 void DMA_release_DREQ (int nchan)
287 {
288     int ncont, ichan;
289
290     ncont = nchan > 3;
291     ichan = nchan & 3;
292     linfo ("released cont=%d chan=%d\n", ncont, ichan);
293     dma_controllers[ncont].status &= ~(1 << (ichan + 4));
294 }
295
296 static void channel_run (int ncont, int ichan)
297 {
298     struct dma_regs *r;
299     int n;
300     target_ulong addr;
301 /*     int ai, dir; */
302
303     r = dma_controllers[ncont].regs + ichan;
304 /*   ai = r->mode & 16; */
305 /*   dir = r->mode & 32 ? -1 : 1; */
306
307     addr = (r->page << 16) | r->now[ADDR];
308     n = r->transfer_handler (r->opaque, addr, 
309                              (r->base[COUNT] << ncont) + (1 << ncont));
310     r->now[COUNT] = n;
311
312     ldebug ("dma_pos %d size %d\n",
313             n, (r->base[1] << ncont) + (1 << ncont));
314 }
315
316 void DMA_run (void)
317 {
318     struct dma_cont *d;
319     int icont, ichan;
320
321     d = dma_controllers;
322
323     for (icont = 0; icont < 2; icont++, d++) {
324         for (ichan = 0; ichan < 4; ichan++) {
325             int mask;
326
327             mask = 1 << ichan;
328
329             if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4))))
330                 channel_run (icont, ichan);
331         }
332     }
333 }
334
335 void DMA_register_channel (int nchan,
336                            DMA_transfer_handler transfer_handler, 
337                            void *opaque)
338 {
339     struct dma_regs *r;
340     int ichan, ncont;
341
342     ncont = nchan > 3;
343     ichan = nchan & 3;
344
345     r = dma_controllers[ncont].regs + ichan;
346     r->transfer_handler = transfer_handler;
347     r->opaque = opaque;
348 }
349
350 /* request the emulator to transfer a new DMA memory block ASAP */
351 void DMA_schedule(int nchan)
352 {
353     cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
354 }
355
356 /* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
357 static void dma_init2(struct dma_cont *d, int base, int dshift, int page_base)
358 {
359     const static int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
360     int i;
361
362     d->dshift = dshift;
363     for (i = 0; i < 8; i++) {
364         register_ioport_write (base + (i << dshift), 1, 1, write_chan, d);
365         register_ioport_read (base + (i << dshift), 1, 1, read_chan, d);
366     }
367     for (i = 0; i < LENOFA (page_port_list); i++) {
368         register_ioport_write (page_base + page_port_list[i], 1, 1, 
369                                write_page, d);
370         register_ioport_read (page_base + page_port_list[i], 1, 1, 
371                               read_page, d);
372     }
373     for (i = 0; i < 8; i++) {
374         register_ioport_write (base + ((i + 8) << dshift), 1, 1, 
375                                write_cont, d);
376         register_ioport_read (base + ((i + 8) << dshift), 1, 1, 
377                               read_cont, d);
378     }
379     write_cont (d, base + (0x0d << dshift), 0);
380 }
381
382 void DMA_init (void)
383 {
384     dma_init2(&dma_controllers[0], 0x00, 0, 0x80);
385     dma_init2(&dma_controllers[1], 0xc0, 1, 0x88);
386 }