Commit 9eb153f18f69306d8b729c34e9f267bcacfe07c5

Authored by bellard
1 parent aaba6c15

dma clean up - added missing read accesses


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@711 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 88 additions and 61 deletions
hw/dma.c
... ... @@ -55,6 +55,7 @@ static struct dma_cont {
55 55 uint8_t command;
56 56 uint8_t mask;
57 57 uint8_t flip_flop;
  58 + int dshift;
58 59 struct dma_regs regs[4];
59 60 } dma_controllers[2];
60 61  
... ... @@ -73,76 +74,87 @@ enum {
73 74  
74 75 };
75 76  
  77 +static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
  78 +
76 79 static void write_page (void *opaque, uint32_t nport, uint32_t data)
77 80 {
  81 + struct dma_cont *d = opaque;
78 82 int ichan;
79   - int ncont;
80   - static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
81 83  
82   - ncont = nport > 0x87;
83   - ichan = channels[nport - 0x80 - (ncont << 3)];
  84 + ichan = channels[nport & 7];
84 85  
85 86 if (-1 == ichan) {
86 87 log ("invalid channel %#x %#x\n", nport, data);
87 88 return;
88 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;
89 97  
90   - dma_controllers[ncont].regs[ichan].page = data;
  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;
91 105 }
92 106  
93   -static void init_chan (int ncont, int ichan)
  107 +static inline void init_chan (struct dma_cont *d, int ichan)
94 108 {
95 109 struct dma_regs *r;
96 110  
97   - r = dma_controllers[ncont].regs + ichan;
98   - r->now[ADDR] = r->base[0] << ncont;
  111 + r = d->regs + ichan;
  112 + r->now[ADDR] = r->base[0] << d->dshift;
99 113 r->now[COUNT] = 0;
100 114 }
101 115  
102   -static inline int getff (int ncont)
  116 +static inline int getff (struct dma_cont *d)
103 117 {
104 118 int ff;
105 119  
106   - ff = dma_controllers[ncont].flip_flop;
107   - dma_controllers[ncont].flip_flop = !ff;
  120 + ff = d->flip_flop;
  121 + d->flip_flop = !ff;
108 122 return ff;
109 123 }
110 124  
111 125 static uint32_t read_chan (void *opaque, uint32_t nport)
112 126 {
113   - int ff;
114   - int ncont, ichan, nreg;
  127 + struct dma_cont *d = opaque;
  128 + int ichan, nreg, iport, ff, val;
115 129 struct dma_regs *r;
116   - int val;
117   -
118   - ncont = nport > 7;
119   - ichan = (nport >> (1 + ncont)) & 3;
120   - nreg = (nport >> ncont) & 1;
121   - r = dma_controllers[ncont].regs + ichan;
122 130  
123   - ff = getff (ncont);
  131 + iport = (nport >> d->dshift) & 0x0f;
  132 + ichan = iport >> 1;
  133 + nreg = iport & 1;
  134 + r = d->regs + ichan;
124 135  
  136 + ff = getff (d);
125 137 if (nreg)
126   - val = (r->base[COUNT] << ncont) - r->now[COUNT];
  138 + val = (r->base[COUNT] << d->dshift) - r->now[COUNT];
127 139 else
128 140 val = r->now[ADDR] + r->now[COUNT];
129 141  
130   - return (val >> (ncont + (ff << 3))) & 0xff;
  142 + return (val >> (d->dshift + (ff << 3))) & 0xff;
131 143 }
132 144  
133 145 static void write_chan (void *opaque, uint32_t nport, uint32_t data)
134 146 {
135   - int ncont, ichan, nreg;
  147 + struct dma_cont *d = opaque;
  148 + int iport, ichan, nreg;
136 149 struct dma_regs *r;
137 150  
138   - ncont = nport > 7;
139   - ichan = (nport >> (1 + ncont)) & 3;
140   - nreg = (nport >> ncont) & 1;
141   - r = dma_controllers[ncont].regs + ichan;
142   -
143   - if (getff (ncont)) {
  151 + iport = (nport >> d->dshift) & 0x0f;
  152 + ichan = iport >> 1;
  153 + nreg = iport & 1;
  154 + r = d->regs + ichan;
  155 + if (getff (d)) {
144 156 r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
145   - init_chan (ncont, ichan);
  157 + init_chan (d, ichan);
146 158 } else {
147 159 r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
148 160 }
... ... @@ -150,20 +162,10 @@ static void write_chan (void *opaque, uint32_t nport, uint32_t data)
150 162  
151 163 static void write_cont (void *opaque, uint32_t nport, uint32_t data)
152 164 {
153   - int iport, ichan, ncont;
154   - struct dma_cont *d;
155   -
156   - ncont = nport > 0xf;
157   - ichan = -1;
158   -
159   - d = dma_controllers + ncont;
160   - if (ncont) {
161   - iport = ((nport - 0xd0) >> 1) + 8;
162   - }
163   - else {
164   - iport = nport;
165   - }
  165 + struct dma_cont *d = opaque;
  166 + int iport, ichan;
166 167  
  168 + iport = (nport >> d->dshift) & 0x0f;
167 169 switch (iport) {
168 170 case 8: /* command */
169 171 if (data && (data | CMD_NOT_SUPPORTED)) {
... ... @@ -239,8 +241,8 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
239 241  
240 242 #ifdef DEBUG_DMA
241 243 if (0xc != iport) {
242   - linfo ("nport %#06x, ncont %d, ichan % 2d, val %#06x\n",
243   - nport, d != dma_controllers, ichan, data);
  244 + linfo ("nport %#06x, ichan % 2d, val %#06x\n",
  245 + nport, ichan, data);
244 246 }
245 247 #endif
246 248 return;
... ... @@ -249,6 +251,27 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
249 251 abort ();
250 252 }
251 253  
  254 +static uint32_t read_cont (void *opaque, uint32_t nport)
  255 +{
  256 + struct dma_cont *d = opaque;
  257 + int iport, val;
  258 +
  259 + iport = (nport >> d->dshift) & 0x0f;
  260 + switch (iport) {
  261 + case 0x08: /* status */
  262 + val = d->status;
  263 + d->status &= 0xf0;
  264 + break;
  265 + case 0x0f: /* mask */
  266 + val = d->mask;
  267 + break;
  268 + default:
  269 + val = 0;
  270 + break;
  271 + }
  272 + return val;
  273 +}
  274 +
252 275 int DMA_get_channel_mode (int nchan)
253 276 {
254 277 return dma_controllers[nchan > 3].regs[nchan & 3].mode;
... ... @@ -334,30 +357,34 @@ void DMA_schedule(int nchan)
334 357 cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
335 358 }
336 359  
337   -void DMA_init (void)
  360 +/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
  361 +static void dma_init2(struct dma_cont *d, int base, int dshift, int page_base)
338 362 {
  363 + const static int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
339 364 int i;
340   - int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
341 365  
  366 + d->dshift = dshift;
342 367 for (i = 0; i < 8; i++) {
343   - register_ioport_write (i, 1, 1, write_chan, NULL);
344   -
345   - register_ioport_write (0xc0 + (i << 1), 1, 1, write_chan, NULL);
346   -
347   - register_ioport_read (i, 1, 1, read_chan, NULL);
348   - register_ioport_read (0xc0 + (i << 1), 1, 1, read_chan, NULL);
  368 + register_ioport_write (base + (i << dshift), 1, 1, write_chan, d);
  369 + register_ioport_read (base + (i << dshift), 1, 1, read_chan, d);
349 370 }
350   -
351 371 for (i = 0; i < LENOFA (page_port_list); i++) {
352   - register_ioport_write (page_port_list[i] + 0x80, 1, 1, write_page, NULL);
353   - register_ioport_write (page_port_list[i] + 0x88, 1, 1, write_page, NULL);
  372 + register_ioport_write (page_base + page_port_list[i], 1, 1,
  373 + write_page, d);
  374 + register_ioport_read (page_base + page_port_list[i], 1, 1,
  375 + read_page, d);
354 376 }
355   -
356 377 for (i = 0; i < 8; i++) {
357   - register_ioport_write (i + 8, 1, 1, write_cont, NULL);
358   - register_ioport_write (0xd0 + (i << 1), 1, 1, write_cont, NULL);
  378 + register_ioport_write (base + ((i + 8) << dshift), 1, 1,
  379 + write_cont, d);
  380 + register_ioport_read (base + ((i + 8) << dshift), 1, 1,
  381 + read_cont, d);
359 382 }
  383 + write_cont (d, base + (0x0d << dshift), 0);
  384 +}
360 385  
361   - write_cont (NULL, 0x0d, 0);
362   - write_cont (NULL, 0xda, 0);
  386 +void DMA_init (void)
  387 +{
  388 + dma_init2(&dma_controllers[0], 0x00, 0, 0x80);
  389 + dma_init2(&dma_controllers[1], 0xc0, 1, 0x88);
363 390 }
... ...