Revision 12abac85
b/hw/slavio_serial.c | ||
---|---|---|
89 | 89 |
int rptr, wptr, count; |
90 | 90 |
} SERIOQueue; |
91 | 91 |
|
92 |
#define SERIAL_REGS 16 |
|
92 | 93 |
typedef struct ChannelState { |
93 | 94 |
qemu_irq irq; |
94 | 95 |
int reg; |
... | ... | |
96 | 97 |
chn_id_t chn; // this channel, A (base+4) or B (base+0) |
97 | 98 |
chn_type_t type; |
98 | 99 |
struct ChannelState *otherchn; |
99 |
uint8_t rx, tx, wregs[16], rregs[16];
|
|
100 |
uint8_t rx, tx, wregs[SERIAL_REGS], rregs[SERIAL_REGS];
|
|
100 | 101 |
SERIOQueue queue; |
101 | 102 |
CharDriverState *chr; |
102 | 103 |
int e0_mode, led_mode, caps_lock_mode, num_lock_mode; |
... | ... | |
109 | 110 |
|
110 | 111 |
#define SERIAL_MAXADDR 7 |
111 | 112 |
#define SERIAL_SIZE (SERIAL_MAXADDR + 1) |
113 |
#define SERIAL_CTRL 0 |
|
114 |
#define SERIAL_DATA 1 |
|
115 |
|
|
116 |
#define W_CMD 0 |
|
117 |
#define CMD_PTR_MASK 0x07 |
|
118 |
#define CMD_CMD_MASK 0x38 |
|
119 |
#define CMD_HI 0x08 |
|
120 |
#define CMD_CLR_TXINT 0x28 |
|
121 |
#define CMD_CLR_IUS 0x38 |
|
122 |
#define W_INTR 1 |
|
123 |
#define INTR_INTALL 0x01 |
|
124 |
#define INTR_TXINT 0x02 |
|
125 |
#define INTR_RXMODEMSK 0x18 |
|
126 |
#define INTR_RXINT1ST 0x08 |
|
127 |
#define INTR_RXINTALL 0x10 |
|
128 |
#define W_IVEC 2 |
|
129 |
#define W_RXCTRL 3 |
|
130 |
#define RXCTRL_RXEN 0x01 |
|
131 |
#define W_TXCTRL1 4 |
|
132 |
#define TXCTRL1_PAREN 0x01 |
|
133 |
#define TXCTRL1_PAREV 0x02 |
|
134 |
#define TXCTRL1_1STOP 0x04 |
|
135 |
#define TXCTRL1_1HSTOP 0x08 |
|
136 |
#define TXCTRL1_2STOP 0x0c |
|
137 |
#define TXCTRL1_STPMSK 0x0c |
|
138 |
#define TXCTRL1_CLK1X 0x00 |
|
139 |
#define TXCTRL1_CLK16X 0x40 |
|
140 |
#define TXCTRL1_CLK32X 0x80 |
|
141 |
#define TXCTRL1_CLK64X 0xc0 |
|
142 |
#define TXCTRL1_CLKMSK 0xc0 |
|
143 |
#define W_TXCTRL2 5 |
|
144 |
#define TXCTRL2_TXEN 0x08 |
|
145 |
#define TXCTRL2_BITMSK 0x60 |
|
146 |
#define TXCTRL2_5BITS 0x00 |
|
147 |
#define TXCTRL2_7BITS 0x20 |
|
148 |
#define TXCTRL2_6BITS 0x40 |
|
149 |
#define TXCTRL2_8BITS 0x60 |
|
150 |
#define W_SYNC1 6 |
|
151 |
#define W_SYNC2 7 |
|
152 |
#define W_TXBUF 8 |
|
153 |
#define W_MINTR 9 |
|
154 |
#define MINTR_STATUSHI 0x10 |
|
155 |
#define MINTR_RST_MASK 0xc0 |
|
156 |
#define MINTR_RST_B 0x40 |
|
157 |
#define MINTR_RST_A 0x80 |
|
158 |
#define MINTR_RST_ALL 0xc0 |
|
159 |
#define W_MISC1 10 |
|
160 |
#define W_CLOCK 11 |
|
161 |
#define CLOCK_TRXC 0x08 |
|
162 |
#define W_BRGLO 12 |
|
163 |
#define W_BRGHI 13 |
|
164 |
#define W_MISC2 14 |
|
165 |
#define MISC2_PLLDIS 0x30 |
|
166 |
#define W_EXTINT 15 |
|
167 |
#define EXTINT_DCD 0x08 |
|
168 |
#define EXTINT_SYNCINT 0x10 |
|
169 |
#define EXTINT_CTSINT 0x20 |
|
170 |
#define EXTINT_TXUNDRN 0x40 |
|
171 |
#define EXTINT_BRKINT 0x80 |
|
172 |
|
|
173 |
#define R_STATUS 0 |
|
174 |
#define STATUS_RXAV 0x01 |
|
175 |
#define STATUS_ZERO 0x02 |
|
176 |
#define STATUS_TXEMPTY 0x04 |
|
177 |
#define STATUS_DCD 0x08 |
|
178 |
#define STATUS_SYNC 0x10 |
|
179 |
#define STATUS_CTS 0x20 |
|
180 |
#define STATUS_TXUNDRN 0x40 |
|
181 |
#define STATUS_BRK 0x80 |
|
182 |
#define R_SPEC 1 |
|
183 |
#define SPEC_ALLSENT 0x01 |
|
184 |
#define SPEC_BITS8 0x06 |
|
185 |
#define R_IVEC 2 |
|
186 |
#define IVEC_TXINTB 0x00 |
|
187 |
#define IVEC_LONOINT 0x06 |
|
188 |
#define IVEC_LORXINTA 0x0c |
|
189 |
#define IVEC_LORXINTB 0x04 |
|
190 |
#define IVEC_LOTXINTA 0x08 |
|
191 |
#define IVEC_HINOINT 0x60 |
|
192 |
#define IVEC_HIRXINTA 0x30 |
|
193 |
#define IVEC_HIRXINTB 0x20 |
|
194 |
#define IVEC_HITXINTA 0x10 |
|
195 |
#define R_INTR 3 |
|
196 |
#define INTR_EXTINTB 0x01 |
|
197 |
#define INTR_TXINTB 0x02 |
|
198 |
#define INTR_RXINTB 0x04 |
|
199 |
#define INTR_EXTINTA 0x08 |
|
200 |
#define INTR_TXINTA 0x10 |
|
201 |
#define INTR_RXINTA 0x20 |
|
202 |
#define R_IPEN 4 |
|
203 |
#define R_TXCTRL1 5 |
|
204 |
#define R_TXCTRL2 6 |
|
205 |
#define R_BC 7 |
|
206 |
#define R_RXBUF 8 |
|
207 |
#define R_RXCTRL 9 |
|
208 |
#define R_MISC 10 |
|
209 |
#define R_MISC1 11 |
|
210 |
#define R_BRGLO 12 |
|
211 |
#define R_BRGHI 13 |
|
212 |
#define R_MISC1I 14 |
|
213 |
#define R_EXTINT 15 |
|
112 | 214 |
|
113 | 215 |
static void handle_kbd_command(ChannelState *s, int val); |
114 | 216 |
static int serial_can_receive(void *opaque); |
... | ... | |
159 | 261 |
|
160 | 262 |
static int slavio_serial_update_irq_chn(ChannelState *s) |
161 | 263 |
{ |
162 |
if ((s->wregs[1] & 1) && // interrupts enabled |
|
163 |
(((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending |
|
164 |
((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) && |
|
264 |
if ((s->wregs[W_INTR] & INTR_INTALL) && // interrupts enabled |
|
265 |
(((s->wregs[W_INTR] & INTR_TXINT) && s->txint == 1) || |
|
266 |
// tx ints enabled, pending |
|
267 |
((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) || |
|
268 |
((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) && |
|
165 | 269 |
s->rxint == 1) || // rx ints enabled, pending |
166 |
((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p |
|
270 |
((s->wregs[W_EXTINT] & EXTINT_BRKINT) && |
|
271 |
(s->rregs[R_STATUS] & STATUS_BRK)))) { // break int e&p |
|
167 | 272 |
return 1; |
168 | 273 |
} |
169 | 274 |
return 0; |
... | ... | |
189 | 294 |
s->rregs[i] = 0; |
190 | 295 |
s->wregs[i] = 0; |
191 | 296 |
} |
192 |
s->wregs[4] = 4; |
|
193 |
s->wregs[9] = 0xc0; |
|
194 |
s->wregs[11] = 8; |
|
195 |
s->wregs[14] = 0x30; |
|
196 |
s->wregs[15] = 0xf8; |
|
297 |
s->wregs[W_TXCTRL1] = TXCTRL1_1STOP; // 1X divisor, 1 stop bit, no parity |
|
298 |
s->wregs[W_MINTR] = MINTR_RST_ALL; |
|
299 |
s->wregs[W_CLOCK] = CLOCK_TRXC; // Synch mode tx clock = TRxC |
|
300 |
s->wregs[W_MISC2] = MISC2_PLLDIS; // PLL disabled |
|
301 |
s->wregs[W_EXTINT] = EXTINT_DCD | EXTINT_SYNCINT | EXTINT_CTSINT | |
|
302 |
EXTINT_TXUNDRN | EXTINT_BRKINT; // Enable most interrupts |
|
197 | 303 |
if (s->disabled) |
198 |
s->rregs[0] = 0x7c; |
|
304 |
s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_DCD | STATUS_SYNC | |
|
305 |
STATUS_CTS | STATUS_TXUNDRN; |
|
199 | 306 |
else |
200 |
s->rregs[0] = 0x44;
|
|
201 |
s->rregs[1] = 6;
|
|
307 |
s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_TXUNDRN;
|
|
308 |
s->rregs[R_SPEC] = SPEC_BITS8;
|
|
202 | 309 |
|
203 | 310 |
s->rx = s->tx = 0; |
204 | 311 |
s->rxint = s->txint = 0; |
... | ... | |
219 | 326 |
s->rxint = 0; |
220 | 327 |
s->rxint_under_svc = 0; |
221 | 328 |
if (s->chn == chn_a) { |
222 |
if (s->wregs[9] & 0x10)
|
|
223 |
s->otherchn->rregs[2] = 0x60;
|
|
329 |
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
|
330 |
s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
|
|
224 | 331 |
else |
225 |
s->otherchn->rregs[2] = 0x06;
|
|
226 |
s->rregs[3] &= ~0x20;
|
|
332 |
s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
|
|
333 |
s->rregs[R_INTR] &= ~INTR_RXINTA;
|
|
227 | 334 |
} else { |
228 |
if (s->wregs[9] & 0x10)
|
|
229 |
s->rregs[2] = 0x60;
|
|
335 |
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
|
336 |
s->rregs[R_IVEC] = IVEC_HINOINT;
|
|
230 | 337 |
else |
231 |
s->rregs[2] = 0x06;
|
|
232 |
s->otherchn->rregs[3] &= ~4;
|
|
338 |
s->rregs[R_IVEC] = IVEC_LONOINT;
|
|
339 |
s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
|
|
233 | 340 |
} |
234 | 341 |
if (s->txint) |
235 | 342 |
set_txint(s); |
... | ... | |
242 | 349 |
if (!s->txint_under_svc) { |
243 | 350 |
s->rxint_under_svc = 1; |
244 | 351 |
if (s->chn == chn_a) { |
245 |
if (s->wregs[9] & 0x10)
|
|
246 |
s->otherchn->rregs[2] = 0x30;
|
|
352 |
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
|
353 |
s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
|
|
247 | 354 |
else |
248 |
s->otherchn->rregs[2] = 0x0c;
|
|
355 |
s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
|
|
249 | 356 |
} else { |
250 |
if (s->wregs[9] & 0x10)
|
|
251 |
s->rregs[2] = 0x20;
|
|
357 |
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
|
358 |
s->rregs[R_IVEC] = IVEC_HIRXINTB;
|
|
252 | 359 |
else |
253 |
s->rregs[2] = 0x04;
|
|
360 |
s->rregs[R_IVEC] = IVEC_LORXINTB;
|
|
254 | 361 |
} |
255 | 362 |
} |
256 | 363 |
if (s->chn == chn_a) |
257 |
s->rregs[3] |= 0x20;
|
|
364 |
s->rregs[R_INTR] |= INTR_RXINTA;
|
|
258 | 365 |
else |
259 |
s->otherchn->rregs[3] |= 4;
|
|
366 |
s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
|
|
260 | 367 |
slavio_serial_update_irq(s); |
261 | 368 |
} |
262 | 369 |
|
... | ... | |
265 | 372 |
s->txint = 0; |
266 | 373 |
s->txint_under_svc = 0; |
267 | 374 |
if (s->chn == chn_a) { |
268 |
if (s->wregs[9] & 0x10)
|
|
269 |
s->otherchn->rregs[2] = 0x60;
|
|
375 |
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
|
376 |
s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
|
|
270 | 377 |
else |
271 |
s->otherchn->rregs[2] = 0x06;
|
|
272 |
s->rregs[3] &= ~0x10;
|
|
378 |
s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
|
|
379 |
s->rregs[R_INTR] &= ~INTR_TXINTA;
|
|
273 | 380 |
} else { |
274 |
if (s->wregs[9] & 0x10)
|
|
275 |
s->rregs[2] = 0x60;
|
|
381 |
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
|
382 |
s->rregs[R_IVEC] = IVEC_HINOINT;
|
|
276 | 383 |
else |
277 |
s->rregs[2] = 0x06;
|
|
278 |
s->otherchn->rregs[3] &= ~2;
|
|
384 |
s->rregs[R_IVEC] = IVEC_LONOINT;
|
|
385 |
s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
|
|
279 | 386 |
} |
280 | 387 |
if (s->rxint) |
281 | 388 |
set_rxint(s); |
... | ... | |
288 | 395 |
if (!s->rxint_under_svc) { |
289 | 396 |
s->txint_under_svc = 1; |
290 | 397 |
if (s->chn == chn_a) { |
291 |
if (s->wregs[9] & 0x10)
|
|
292 |
s->otherchn->rregs[2] = 0x10;
|
|
398 |
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
|
399 |
s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
|
|
293 | 400 |
else |
294 |
s->otherchn->rregs[2] = 0x08;
|
|
401 |
s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
|
|
295 | 402 |
} else { |
296 |
s->rregs[2] = 0;
|
|
403 |
s->rregs[R_IVEC] = IVEC_TXINTB;
|
|
297 | 404 |
} |
298 | 405 |
} |
299 | 406 |
if (s->chn == chn_a) |
300 |
s->rregs[3] |= 0x10;
|
|
407 |
s->rregs[R_INTR] |= INTR_TXINTA;
|
|
301 | 408 |
else |
302 |
s->otherchn->rregs[3] |= 2;
|
|
409 |
s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
|
|
303 | 410 |
slavio_serial_update_irq(s); |
304 | 411 |
} |
305 | 412 |
|
... | ... | |
311 | 418 |
if (!s->chr || s->type != ser) |
312 | 419 |
return; |
313 | 420 |
|
314 |
if (s->wregs[4] & 1) {
|
|
315 |
if (s->wregs[4] & 2)
|
|
421 |
if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
|
|
422 |
if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)
|
|
316 | 423 |
parity = 'E'; |
317 | 424 |
else |
318 | 425 |
parity = 'O'; |
319 | 426 |
} else { |
320 | 427 |
parity = 'N'; |
321 | 428 |
} |
322 |
if ((s->wregs[4] & 0x0c) == 0x0c)
|
|
429 |
if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)
|
|
323 | 430 |
stop_bits = 2; |
324 | 431 |
else |
325 | 432 |
stop_bits = 1; |
326 |
switch (s->wregs[5] & 0x60) {
|
|
327 |
case 0x00:
|
|
433 |
switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
|
|
434 |
case TXCTRL2_5BITS:
|
|
328 | 435 |
data_bits = 5; |
329 | 436 |
break; |
330 |
case 0x20:
|
|
437 |
case TXCTRL2_7BITS:
|
|
331 | 438 |
data_bits = 7; |
332 | 439 |
break; |
333 |
case 0x40:
|
|
440 |
case TXCTRL2_6BITS:
|
|
334 | 441 |
data_bits = 6; |
335 | 442 |
break; |
336 | 443 |
default: |
337 |
case 0x60:
|
|
444 |
case TXCTRL2_8BITS:
|
|
338 | 445 |
data_bits = 8; |
339 | 446 |
break; |
340 | 447 |
} |
341 |
speed = 2457600 / ((s->wregs[12] | (s->wregs[13] << 8)) + 2);
|
|
342 |
switch (s->wregs[4] & 0xc0) {
|
|
343 |
case 0x00:
|
|
448 |
speed = 2457600 / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
|
|
449 |
switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {
|
|
450 |
case TXCTRL1_CLK1X:
|
|
344 | 451 |
break; |
345 |
case 0x40:
|
|
452 |
case TXCTRL1_CLK16X:
|
|
346 | 453 |
speed /= 16; |
347 | 454 |
break; |
348 |
case 0x80:
|
|
455 |
case TXCTRL1_CLK32X:
|
|
349 | 456 |
speed /= 32; |
350 | 457 |
break; |
351 | 458 |
default: |
352 |
case 0xc0:
|
|
459 |
case TXCTRL1_CLK64X:
|
|
353 | 460 |
speed /= 64; |
354 | 461 |
break; |
355 | 462 |
} |
... | ... | |
362 | 469 |
qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); |
363 | 470 |
} |
364 | 471 |
|
365 |
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
472 |
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, |
|
473 |
uint32_t val) |
|
366 | 474 |
{ |
367 | 475 |
SerialState *serial = opaque; |
368 | 476 |
ChannelState *s; |
... | ... | |
374 | 482 |
channel = (addr & SERIAL_MAXADDR) >> 2; |
375 | 483 |
s = &serial->chn[channel]; |
376 | 484 |
switch (saddr) { |
377 |
case 0: |
|
378 |
SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff); |
|
485 |
case SERIAL_CTRL: |
|
486 |
SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, |
|
487 |
val & 0xff); |
|
379 | 488 |
newreg = 0; |
380 | 489 |
switch (s->reg) { |
381 |
case 0:
|
|
382 |
newreg = val & 7;
|
|
383 |
val &= 0x38;
|
|
490 |
case W_CMD:
|
|
491 |
newreg = val & CMD_PTR_MASK;
|
|
492 |
val &= CMD_CMD_MASK;
|
|
384 | 493 |
switch (val) { |
385 |
case 8:
|
|
386 |
newreg |= 0x8;
|
|
494 |
case CMD_HI:
|
|
495 |
newreg |= CMD_HI;
|
|
387 | 496 |
break; |
388 |
case 0x28:
|
|
497 |
case CMD_CLR_TXINT:
|
|
389 | 498 |
clr_txint(s); |
390 | 499 |
break; |
391 |
case 0x38:
|
|
500 |
case CMD_CLR_IUS:
|
|
392 | 501 |
if (s->rxint_under_svc) |
393 | 502 |
clr_rxint(s); |
394 | 503 |
else if (s->txint_under_svc) |
... | ... | |
398 | 507 |
break; |
399 | 508 |
} |
400 | 509 |
break; |
401 |
case 1 ... 3:
|
|
402 |
case 6 ... 8:
|
|
403 |
case 10 ... 11:
|
|
404 |
case 14 ... 15:
|
|
510 |
case W_INTR ... W_RXCTRL:
|
|
511 |
case W_SYNC1 ... W_TXBUF:
|
|
512 |
case W_MISC1 ... W_CLOCK:
|
|
513 |
case W_MISC2 ... W_EXTINT:
|
|
405 | 514 |
s->wregs[s->reg] = val; |
406 | 515 |
break; |
407 |
case 4:
|
|
408 |
case 5:
|
|
409 |
case 12:
|
|
410 |
case 13:
|
|
516 |
case W_TXCTRL1:
|
|
517 |
case W_TXCTRL2:
|
|
518 |
case W_BRGLO:
|
|
519 |
case W_BRGHI:
|
|
411 | 520 |
s->wregs[s->reg] = val; |
412 | 521 |
slavio_serial_update_parameters(s); |
413 | 522 |
break; |
414 |
case 9:
|
|
415 |
switch (val & 0xc0) {
|
|
523 |
case W_MINTR:
|
|
524 |
switch (val & MINTR_RST_MASK) {
|
|
416 | 525 |
case 0: |
417 | 526 |
default: |
418 | 527 |
break; |
419 |
case 0x40:
|
|
528 |
case MINTR_RST_B:
|
|
420 | 529 |
slavio_serial_reset_chn(&serial->chn[1]); |
421 | 530 |
return; |
422 |
case 0x80:
|
|
531 |
case MINTR_RST_A:
|
|
423 | 532 |
slavio_serial_reset_chn(&serial->chn[0]); |
424 | 533 |
return; |
425 |
case 0xc0:
|
|
534 |
case MINTR_RST_ALL:
|
|
426 | 535 |
slavio_serial_reset(serial); |
427 | 536 |
return; |
428 | 537 |
} |
... | ... | |
435 | 544 |
else |
436 | 545 |
s->reg = 0; |
437 | 546 |
break; |
438 |
case 1:
|
|
547 |
case SERIAL_DATA:
|
|
439 | 548 |
SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val); |
440 | 549 |
s->tx = val; |
441 |
if (s->wregs[5] & 8) { // tx enabled
|
|
550 |
if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
|
|
442 | 551 |
if (s->chr) |
443 | 552 |
qemu_chr_write(s->chr, &s->tx, 1); |
444 | 553 |
else if (s->type == kbd && !s->disabled) { |
445 | 554 |
handle_kbd_command(s, val); |
446 | 555 |
} |
447 | 556 |
} |
448 |
s->rregs[0] |= 4; // Tx buffer empty
|
|
449 |
s->rregs[1] |= 1; // All sent
|
|
557 |
s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty
|
|
558 |
s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent
|
|
450 | 559 |
set_txint(s); |
451 | 560 |
break; |
452 | 561 |
default: |
... | ... | |
466 | 575 |
channel = (addr & SERIAL_MAXADDR) >> 2; |
467 | 576 |
s = &serial->chn[channel]; |
468 | 577 |
switch (saddr) { |
469 |
case 0: |
|
470 |
SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]); |
|
578 |
case SERIAL_CTRL: |
|
579 |
SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, |
|
580 |
s->rregs[s->reg]); |
|
471 | 581 |
ret = s->rregs[s->reg]; |
472 | 582 |
s->reg = 0; |
473 | 583 |
return ret; |
474 |
case 1:
|
|
475 |
s->rregs[0] &= ~1;
|
|
584 |
case SERIAL_DATA:
|
|
585 |
s->rregs[R_STATUS] &= ~STATUS_RXAV;
|
|
476 | 586 |
clr_rxint(s); |
477 | 587 |
if (s->type == kbd || s->type == mouse) |
478 | 588 |
ret = get_queue(s); |
... | ... | |
493 | 603 |
ChannelState *s = opaque; |
494 | 604 |
int ret; |
495 | 605 |
|
496 |
if (((s->wregs[3] & 1) == 0) // Rx not enabled |
|
497 |
|| ((s->rregs[0] & 1) == 1)) // char already available |
|
606 |
if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) // Rx not enabled |
|
607 |
|| ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV)) |
|
608 |
// char already available |
|
498 | 609 |
ret = 0; |
499 | 610 |
else |
500 | 611 |
ret = 1; |
501 |
//SER_DPRINTF("channel %c can receive %d\n", CHN_C(s), ret); |
|
502 | 612 |
return ret; |
503 | 613 |
} |
504 | 614 |
|
505 | 615 |
static void serial_receive_byte(ChannelState *s, int ch) |
506 | 616 |
{ |
507 | 617 |
SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch); |
508 |
s->rregs[0] |= 1;
|
|
618 |
s->rregs[R_STATUS] |= STATUS_RXAV;
|
|
509 | 619 |
s->rx = ch; |
510 | 620 |
set_rxint(s); |
511 | 621 |
} |
512 | 622 |
|
513 | 623 |
static void serial_receive_break(ChannelState *s) |
514 | 624 |
{ |
515 |
s->rregs[0] |= 0x80;
|
|
625 |
s->rregs[R_STATUS] |= STATUS_BRK;
|
|
516 | 626 |
slavio_serial_update_irq(s); |
517 | 627 |
} |
518 | 628 |
|
... | ... | |
553 | 663 |
qemu_put_be32s(f, &s->txint_under_svc); |
554 | 664 |
qemu_put_8s(f, &s->rx); |
555 | 665 |
qemu_put_8s(f, &s->tx); |
556 |
qemu_put_buffer(f, s->wregs, 16);
|
|
557 |
qemu_put_buffer(f, s->rregs, 16);
|
|
666 |
qemu_put_buffer(f, s->wregs, SERIAL_REGS);
|
|
667 |
qemu_put_buffer(f, s->rregs, SERIAL_REGS);
|
|
558 | 668 |
} |
559 | 669 |
|
560 | 670 |
static void slavio_serial_save(QEMUFile *f, void *opaque) |
... | ... | |
582 | 692 |
} |
583 | 693 |
qemu_get_8s(f, &s->rx); |
584 | 694 |
qemu_get_8s(f, &s->tx); |
585 |
qemu_get_buffer(f, s->wregs, 16);
|
|
586 |
qemu_get_buffer(f, s->rregs, 16);
|
|
695 |
qemu_get_buffer(f, s->wregs, SERIAL_REGS);
|
|
696 |
qemu_get_buffer(f, s->rregs, SERIAL_REGS);
|
|
587 | 697 |
return 0; |
588 | 698 |
} |
589 | 699 |
|
... | ... | |
610 | 720 |
if (!s) |
611 | 721 |
return NULL; |
612 | 722 |
|
613 |
slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s); |
|
723 |
slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, |
|
724 |
slavio_serial_mem_write, |
|
725 |
s); |
|
614 | 726 |
cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory); |
615 | 727 |
|
616 | 728 |
s->chn[0].chr = chr1; |
... | ... | |
629 | 741 |
} |
630 | 742 |
s->chn[0].otherchn = &s->chn[1]; |
631 | 743 |
s->chn[1].otherchn = &s->chn[0]; |
632 |
register_savevm("slavio_serial", base, 2, slavio_serial_save, slavio_serial_load, s); |
|
744 |
register_savevm("slavio_serial", base, 2, slavio_serial_save, |
|
745 |
slavio_serial_load, s); |
|
633 | 746 |
qemu_register_reset(slavio_serial_reset, s); |
634 | 747 |
slavio_serial_reset(s); |
635 | 748 |
return s; |
... | ... | |
662 | 775 |
ChannelState *s = opaque; |
663 | 776 |
int release = ch & 0x80; |
664 | 777 |
|
665 |
KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" : "press"); |
|
778 |
KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" : |
|
779 |
"press"); |
|
666 | 780 |
switch (ch) { |
667 | 781 |
case 58: // Caps lock press |
668 | 782 |
s->caps_lock_mode ^= 1; |
... | ... | |
792 | 906 |
s->chn[0].disabled = disabled; |
793 | 907 |
s->chn[1].disabled = disabled; |
794 | 908 |
|
795 |
slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s); |
|
909 |
slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, |
|
910 |
slavio_serial_mem_write, |
|
911 |
s); |
|
796 | 912 |
cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory); |
797 | 913 |
|
798 |
qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, "QEMU Sun Mouse"); |
|
914 |
qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, |
|
915 |
"QEMU Sun Mouse"); |
|
799 | 916 |
qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]); |
800 |
register_savevm("slavio_serial_mouse", base, 2, slavio_serial_save, slavio_serial_load, s); |
|
917 |
register_savevm("slavio_serial_mouse", base, 2, slavio_serial_save, |
|
918 |
slavio_serial_load, s); |
|
801 | 919 |
qemu_register_reset(slavio_serial_reset, s); |
802 | 920 |
slavio_serial_reset(s); |
803 | 921 |
} |
Also available in: Unified diff