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,6 +55,7 @@ static struct dma_cont {
55 uint8_t command; 55 uint8_t command;
56 uint8_t mask; 56 uint8_t mask;
57 uint8_t flip_flop; 57 uint8_t flip_flop;
  58 + int dshift;
58 struct dma_regs regs[4]; 59 struct dma_regs regs[4];
59 } dma_controllers[2]; 60 } dma_controllers[2];
60 61
@@ -73,76 +74,87 @@ enum { @@ -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 static void write_page (void *opaque, uint32_t nport, uint32_t data) 79 static void write_page (void *opaque, uint32_t nport, uint32_t data)
77 { 80 {
  81 + struct dma_cont *d = opaque;
78 int ichan; 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 if (-1 == ichan) { 86 if (-1 == ichan) {
86 log ("invalid channel %#x %#x\n", nport, data); 87 log ("invalid channel %#x %#x\n", nport, data);
87 return; 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 struct dma_regs *r; 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 r->now[COUNT] = 0; 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 int ff; 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 return ff; 122 return ff;
109 } 123 }
110 124
111 static uint32_t read_chan (void *opaque, uint32_t nport) 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 struct dma_regs *r; 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 if (nreg) 137 if (nreg)
126 - val = (r->base[COUNT] << ncont) - r->now[COUNT]; 138 + val = (r->base[COUNT] << d->dshift) - r->now[COUNT];
127 else 139 else
128 val = r->now[ADDR] + r->now[COUNT]; 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 static void write_chan (void *opaque, uint32_t nport, uint32_t data) 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 struct dma_regs *r; 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 r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00); 156 r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
145 - init_chan (ncont, ichan); 157 + init_chan (d, ichan);
146 } else { 158 } else {
147 r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff); 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,20 +162,10 @@ static void write_chan (void *opaque, uint32_t nport, uint32_t data)
150 162
151 static void write_cont (void *opaque, uint32_t nport, uint32_t data) 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 switch (iport) { 169 switch (iport) {
168 case 8: /* command */ 170 case 8: /* command */
169 if (data && (data | CMD_NOT_SUPPORTED)) { 171 if (data && (data | CMD_NOT_SUPPORTED)) {
@@ -239,8 +241,8 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data) @@ -239,8 +241,8 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
239 241
240 #ifdef DEBUG_DMA 242 #ifdef DEBUG_DMA
241 if (0xc != iport) { 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 #endif 247 #endif
246 return; 248 return;
@@ -249,6 +251,27 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data) @@ -249,6 +251,27 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
249 abort (); 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 int DMA_get_channel_mode (int nchan) 275 int DMA_get_channel_mode (int nchan)
253 { 276 {
254 return dma_controllers[nchan > 3].regs[nchan & 3].mode; 277 return dma_controllers[nchan > 3].regs[nchan & 3].mode;
@@ -334,30 +357,34 @@ void DMA_schedule(int nchan) @@ -334,30 +357,34 @@ void DMA_schedule(int nchan)
334 cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); 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 int i; 364 int i;
340 - int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };  
341 365
  366 + d->dshift = dshift;
342 for (i = 0; i < 8; i++) { 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 for (i = 0; i < LENOFA (page_port_list); i++) { 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 for (i = 0; i < 8; i++) { 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 }