blob: 37424c6cdd6076f66b10ce9c6b24729d63ef0a44 [file] [log] [blame]
bellarde80cfcf2004-12-19 23:18:01 +00001/*
2 * QEMU Sparc SLAVIO serial port emulation
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard8be1f5c2005-04-06 20:42:35 +00004 * Copyright (c) 2003-2005 Fabrice Bellard
ths5fafdf22007-09-16 21:08:06 +00005 *
bellarde80cfcf2004-12-19 23:18:01 +00006 * 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 */
pbrook87ecb682007-11-17 17:14:51 +000024#include "hw.h"
25#include "sun4m.h"
26#include "qemu-char.h"
27#include "console.h"
28
bellard8be1f5c2005-04-06 20:42:35 +000029/* debug serial */
bellarde80cfcf2004-12-19 23:18:01 +000030//#define DEBUG_SERIAL
31
32/* debug keyboard */
33//#define DEBUG_KBD
34
bellard8be1f5c2005-04-06 20:42:35 +000035/* debug mouse */
bellarde80cfcf2004-12-19 23:18:01 +000036//#define DEBUG_MOUSE
37
38/*
39 * This is the serial port, mouse and keyboard part of chip STP2001
40 * (Slave I/O), also produced as NCR89C105. See
41 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
ths5fafdf22007-09-16 21:08:06 +000042 *
bellarde80cfcf2004-12-19 23:18:01 +000043 * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
44 * mouse and keyboard ports don't implement all functions and they are
45 * only asynchronous. There is no DMA.
46 *
47 */
48
bellard715748f2006-09-09 11:35:47 +000049/*
50 * Modifications:
51 * 2006-Aug-10 Igor Kovalenko : Renamed KBDQueue to SERIOQueue, implemented
52 * serial mouse queue.
53 * Implemented serial mouse protocol.
54 */
55
bellard8be1f5c2005-04-06 20:42:35 +000056#ifdef DEBUG_SERIAL
57#define SER_DPRINTF(fmt, args...) \
58do { printf("SER: " fmt , ##args); } while (0)
59#else
60#define SER_DPRINTF(fmt, args...)
61#endif
62#ifdef DEBUG_KBD
63#define KBD_DPRINTF(fmt, args...) \
64do { printf("KBD: " fmt , ##args); } while (0)
65#else
66#define KBD_DPRINTF(fmt, args...)
67#endif
68#ifdef DEBUG_MOUSE
69#define MS_DPRINTF(fmt, args...) \
bellard715748f2006-09-09 11:35:47 +000070do { printf("MSC: " fmt , ##args); } while (0)
bellard8be1f5c2005-04-06 20:42:35 +000071#else
72#define MS_DPRINTF(fmt, args...)
73#endif
74
75typedef enum {
76 chn_a, chn_b,
77} chn_id_t;
78
bellard35db0992006-09-09 12:17:15 +000079#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')
80
bellard8be1f5c2005-04-06 20:42:35 +000081typedef enum {
82 ser, kbd, mouse,
83} chn_type_t;
84
bellard715748f2006-09-09 11:35:47 +000085#define SERIO_QUEUE_SIZE 256
bellard8be1f5c2005-04-06 20:42:35 +000086
87typedef struct {
bellard715748f2006-09-09 11:35:47 +000088 uint8_t data[SERIO_QUEUE_SIZE];
bellard8be1f5c2005-04-06 20:42:35 +000089 int rptr, wptr, count;
bellard715748f2006-09-09 11:35:47 +000090} SERIOQueue;
bellard8be1f5c2005-04-06 20:42:35 +000091
blueswir112abac82007-12-10 20:05:09 +000092#define SERIAL_REGS 16
bellarde80cfcf2004-12-19 23:18:01 +000093typedef struct ChannelState {
pbrookd537cf62007-04-07 18:14:41 +000094 qemu_irq irq;
blueswir122548762008-05-10 10:12:00 +000095 uint32_t reg;
96 uint32_t rxint, txint, rxint_under_svc, txint_under_svc;
bellard8be1f5c2005-04-06 20:42:35 +000097 chn_id_t chn; // this channel, A (base+4) or B (base+0)
98 chn_type_t type;
99 struct ChannelState *otherchn;
blueswir112abac82007-12-10 20:05:09 +0000100 uint8_t rx, tx, wregs[SERIAL_REGS], rregs[SERIAL_REGS];
bellard715748f2006-09-09 11:35:47 +0000101 SERIOQueue queue;
bellarde80cfcf2004-12-19 23:18:01 +0000102 CharDriverState *chr;
blueswir1bbbb2f02007-09-23 11:48:47 +0000103 int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
blueswir1577390f2007-12-04 20:58:31 +0000104 int disabled;
bellarde80cfcf2004-12-19 23:18:01 +0000105} ChannelState;
106
107struct SerialState {
108 struct ChannelState chn[2];
109};
110
111#define SERIAL_MAXADDR 7
blueswir15aca8c32007-05-26 17:39:43 +0000112#define SERIAL_SIZE (SERIAL_MAXADDR + 1)
blueswir112abac82007-12-10 20:05:09 +0000113#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
bellarde80cfcf2004-12-19 23:18:01 +0000214
bellard8be1f5c2005-04-06 20:42:35 +0000215static void handle_kbd_command(ChannelState *s, int val);
216static int serial_can_receive(void *opaque);
217static void serial_receive_byte(ChannelState *s, int ch);
218
blueswir167deb562007-04-18 19:21:38 +0000219static void clear_queue(void *opaque)
220{
221 ChannelState *s = opaque;
222 SERIOQueue *q = &s->queue;
223 q->rptr = q->wptr = q->count = 0;
224}
225
bellard8be1f5c2005-04-06 20:42:35 +0000226static void put_queue(void *opaque, int b)
227{
228 ChannelState *s = opaque;
bellard715748f2006-09-09 11:35:47 +0000229 SERIOQueue *q = &s->queue;
bellard8be1f5c2005-04-06 20:42:35 +0000230
bellard35db0992006-09-09 12:17:15 +0000231 SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b);
bellard715748f2006-09-09 11:35:47 +0000232 if (q->count >= SERIO_QUEUE_SIZE)
bellard8be1f5c2005-04-06 20:42:35 +0000233 return;
234 q->data[q->wptr] = b;
bellard715748f2006-09-09 11:35:47 +0000235 if (++q->wptr == SERIO_QUEUE_SIZE)
bellard8be1f5c2005-04-06 20:42:35 +0000236 q->wptr = 0;
237 q->count++;
238 serial_receive_byte(s, 0);
239}
240
241static uint32_t get_queue(void *opaque)
242{
243 ChannelState *s = opaque;
bellard715748f2006-09-09 11:35:47 +0000244 SERIOQueue *q = &s->queue;
bellard8be1f5c2005-04-06 20:42:35 +0000245 int val;
ths3b46e622007-09-17 08:09:54 +0000246
bellard8be1f5c2005-04-06 20:42:35 +0000247 if (q->count == 0) {
blueswir1f930d072007-10-06 11:28:21 +0000248 return 0;
bellard8be1f5c2005-04-06 20:42:35 +0000249 } else {
250 val = q->data[q->rptr];
bellard715748f2006-09-09 11:35:47 +0000251 if (++q->rptr == SERIO_QUEUE_SIZE)
bellard8be1f5c2005-04-06 20:42:35 +0000252 q->rptr = 0;
253 q->count--;
254 }
blueswir167deb562007-04-18 19:21:38 +0000255 SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
bellard8be1f5c2005-04-06 20:42:35 +0000256 if (q->count > 0)
blueswir1f930d072007-10-06 11:28:21 +0000257 serial_receive_byte(s, 0);
bellard8be1f5c2005-04-06 20:42:35 +0000258 return val;
259}
260
bellarde4a89052006-09-09 11:38:11 +0000261static int slavio_serial_update_irq_chn(ChannelState *s)
bellarde80cfcf2004-12-19 23:18:01 +0000262{
blueswir112abac82007-12-10 20:05:09 +0000263 if ((s->wregs[W_INTR] & INTR_INTALL) && // interrupts enabled
264 (((s->wregs[W_INTR] & INTR_TXINT) && s->txint == 1) ||
265 // tx ints enabled, pending
266 ((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||
267 ((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&
blueswir1f930d072007-10-06 11:28:21 +0000268 s->rxint == 1) || // rx ints enabled, pending
blueswir112abac82007-12-10 20:05:09 +0000269 ((s->wregs[W_EXTINT] & EXTINT_BRKINT) &&
270 (s->rregs[R_STATUS] & STATUS_BRK)))) { // break int e&p
bellarde4a89052006-09-09 11:38:11 +0000271 return 1;
bellarde80cfcf2004-12-19 23:18:01 +0000272 }
bellarde4a89052006-09-09 11:38:11 +0000273 return 0;
274}
275
276static void slavio_serial_update_irq(ChannelState *s)
277{
278 int irq;
279
280 irq = slavio_serial_update_irq_chn(s);
281 irq |= slavio_serial_update_irq_chn(s->otherchn);
282
pbrookd537cf62007-04-07 18:14:41 +0000283 SER_DPRINTF("IRQ = %d\n", irq);
284 qemu_set_irq(s->irq, irq);
bellarde80cfcf2004-12-19 23:18:01 +0000285}
286
287static void slavio_serial_reset_chn(ChannelState *s)
288{
289 int i;
290
291 s->reg = 0;
blueswir15aca8c32007-05-26 17:39:43 +0000292 for (i = 0; i < SERIAL_SIZE; i++) {
blueswir1f930d072007-10-06 11:28:21 +0000293 s->rregs[i] = 0;
294 s->wregs[i] = 0;
bellarde80cfcf2004-12-19 23:18:01 +0000295 }
blueswir112abac82007-12-10 20:05:09 +0000296 s->wregs[W_TXCTRL1] = TXCTRL1_1STOP; // 1X divisor, 1 stop bit, no parity
297 s->wregs[W_MINTR] = MINTR_RST_ALL;
298 s->wregs[W_CLOCK] = CLOCK_TRXC; // Synch mode tx clock = TRxC
299 s->wregs[W_MISC2] = MISC2_PLLDIS; // PLL disabled
300 s->wregs[W_EXTINT] = EXTINT_DCD | EXTINT_SYNCINT | EXTINT_CTSINT |
301 EXTINT_TXUNDRN | EXTINT_BRKINT; // Enable most interrupts
blueswir1577390f2007-12-04 20:58:31 +0000302 if (s->disabled)
blueswir112abac82007-12-10 20:05:09 +0000303 s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_DCD | STATUS_SYNC |
304 STATUS_CTS | STATUS_TXUNDRN;
blueswir1577390f2007-12-04 20:58:31 +0000305 else
blueswir112abac82007-12-10 20:05:09 +0000306 s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_TXUNDRN;
blueswir1f48c5372007-12-27 20:24:15 +0000307 s->rregs[R_SPEC] = SPEC_BITS8 | SPEC_ALLSENT;
bellarde80cfcf2004-12-19 23:18:01 +0000308
309 s->rx = s->tx = 0;
310 s->rxint = s->txint = 0;
bellarde4a89052006-09-09 11:38:11 +0000311 s->rxint_under_svc = s->txint_under_svc = 0;
blueswir1bbbb2f02007-09-23 11:48:47 +0000312 s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
blueswir167deb562007-04-18 19:21:38 +0000313 clear_queue(s);
bellarde80cfcf2004-12-19 23:18:01 +0000314}
315
316static void slavio_serial_reset(void *opaque)
317{
318 SerialState *s = opaque;
319 slavio_serial_reset_chn(&s->chn[0]);
320 slavio_serial_reset_chn(&s->chn[1]);
321}
322
bellardba3c64f2005-12-05 20:31:52 +0000323static inline void set_rxint(ChannelState *s)
324{
325 s->rxint = 1;
bellarde4a89052006-09-09 11:38:11 +0000326 if (!s->txint_under_svc) {
327 s->rxint_under_svc = 1;
blueswir167deb562007-04-18 19:21:38 +0000328 if (s->chn == chn_a) {
blueswir112abac82007-12-10 20:05:09 +0000329 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
330 s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
blueswir167deb562007-04-18 19:21:38 +0000331 else
blueswir112abac82007-12-10 20:05:09 +0000332 s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
blueswir167deb562007-04-18 19:21:38 +0000333 } else {
blueswir112abac82007-12-10 20:05:09 +0000334 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
335 s->rregs[R_IVEC] = IVEC_HIRXINTB;
blueswir167deb562007-04-18 19:21:38 +0000336 else
blueswir112abac82007-12-10 20:05:09 +0000337 s->rregs[R_IVEC] = IVEC_LORXINTB;
blueswir167deb562007-04-18 19:21:38 +0000338 }
bellardba3c64f2005-12-05 20:31:52 +0000339 }
blueswir1b9652ca2007-04-20 19:35:25 +0000340 if (s->chn == chn_a)
blueswir112abac82007-12-10 20:05:09 +0000341 s->rregs[R_INTR] |= INTR_RXINTA;
blueswir1b9652ca2007-04-20 19:35:25 +0000342 else
blueswir112abac82007-12-10 20:05:09 +0000343 s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
blueswir1b9652ca2007-04-20 19:35:25 +0000344 slavio_serial_update_irq(s);
bellardba3c64f2005-12-05 20:31:52 +0000345}
346
blueswir180637a62008-01-17 21:07:04 +0000347static inline void set_txint(ChannelState *s)
348{
349 s->txint = 1;
350 if (!s->rxint_under_svc) {
351 s->txint_under_svc = 1;
352 if (s->chn == chn_a) {
353 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
354 s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
355 else
356 s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
357 } else {
358 s->rregs[R_IVEC] = IVEC_TXINTB;
359 }
360 }
361 if (s->chn == chn_a)
362 s->rregs[R_INTR] |= INTR_TXINTA;
363 else
364 s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
365 slavio_serial_update_irq(s);
366}
367
368static inline void clr_rxint(ChannelState *s)
369{
370 s->rxint = 0;
371 s->rxint_under_svc = 0;
372 if (s->chn == chn_a) {
373 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
374 s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
375 else
376 s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
377 s->rregs[R_INTR] &= ~INTR_RXINTA;
378 } else {
379 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
380 s->rregs[R_IVEC] = IVEC_HINOINT;
381 else
382 s->rregs[R_IVEC] = IVEC_LONOINT;
383 s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
384 }
385 if (s->txint)
386 set_txint(s);
387 slavio_serial_update_irq(s);
388}
389
bellardba3c64f2005-12-05 20:31:52 +0000390static inline void clr_txint(ChannelState *s)
391{
392 s->txint = 0;
bellarde4a89052006-09-09 11:38:11 +0000393 s->txint_under_svc = 0;
blueswir1b9652ca2007-04-20 19:35:25 +0000394 if (s->chn == chn_a) {
blueswir112abac82007-12-10 20:05:09 +0000395 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
396 s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
blueswir1b9652ca2007-04-20 19:35:25 +0000397 else
blueswir112abac82007-12-10 20:05:09 +0000398 s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
399 s->rregs[R_INTR] &= ~INTR_TXINTA;
blueswir1b9652ca2007-04-20 19:35:25 +0000400 } else {
blueswir112abac82007-12-10 20:05:09 +0000401 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
402 s->rregs[R_IVEC] = IVEC_HINOINT;
blueswir1b9652ca2007-04-20 19:35:25 +0000403 else
blueswir112abac82007-12-10 20:05:09 +0000404 s->rregs[R_IVEC] = IVEC_LONOINT;
405 s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
blueswir1b9652ca2007-04-20 19:35:25 +0000406 }
bellarde4a89052006-09-09 11:38:11 +0000407 if (s->rxint)
408 set_rxint(s);
bellardba3c64f2005-12-05 20:31:52 +0000409 slavio_serial_update_irq(s);
410}
411
bellard35db0992006-09-09 12:17:15 +0000412static void slavio_serial_update_parameters(ChannelState *s)
413{
414 int speed, parity, data_bits, stop_bits;
415 QEMUSerialSetParams ssp;
416
417 if (!s->chr || s->type != ser)
418 return;
419
blueswir112abac82007-12-10 20:05:09 +0000420 if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
421 if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)
bellard35db0992006-09-09 12:17:15 +0000422 parity = 'E';
423 else
424 parity = 'O';
425 } else {
426 parity = 'N';
427 }
blueswir112abac82007-12-10 20:05:09 +0000428 if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)
bellard35db0992006-09-09 12:17:15 +0000429 stop_bits = 2;
430 else
431 stop_bits = 1;
blueswir112abac82007-12-10 20:05:09 +0000432 switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
433 case TXCTRL2_5BITS:
bellard35db0992006-09-09 12:17:15 +0000434 data_bits = 5;
435 break;
blueswir112abac82007-12-10 20:05:09 +0000436 case TXCTRL2_7BITS:
bellard35db0992006-09-09 12:17:15 +0000437 data_bits = 7;
438 break;
blueswir112abac82007-12-10 20:05:09 +0000439 case TXCTRL2_6BITS:
bellard35db0992006-09-09 12:17:15 +0000440 data_bits = 6;
441 break;
442 default:
blueswir112abac82007-12-10 20:05:09 +0000443 case TXCTRL2_8BITS:
bellard35db0992006-09-09 12:17:15 +0000444 data_bits = 8;
445 break;
446 }
blueswir112abac82007-12-10 20:05:09 +0000447 speed = 2457600 / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
448 switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {
449 case TXCTRL1_CLK1X:
bellard35db0992006-09-09 12:17:15 +0000450 break;
blueswir112abac82007-12-10 20:05:09 +0000451 case TXCTRL1_CLK16X:
bellard35db0992006-09-09 12:17:15 +0000452 speed /= 16;
453 break;
blueswir112abac82007-12-10 20:05:09 +0000454 case TXCTRL1_CLK32X:
bellard35db0992006-09-09 12:17:15 +0000455 speed /= 32;
456 break;
457 default:
blueswir112abac82007-12-10 20:05:09 +0000458 case TXCTRL1_CLK64X:
bellard35db0992006-09-09 12:17:15 +0000459 speed /= 64;
460 break;
461 }
462 ssp.speed = speed;
463 ssp.parity = parity;
464 ssp.data_bits = data_bits;
465 ssp.stop_bits = stop_bits;
466 SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s),
467 speed, parity, data_bits, stop_bits);
468 qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
469}
470
blueswir112abac82007-12-10 20:05:09 +0000471static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr,
472 uint32_t val)
bellarde80cfcf2004-12-19 23:18:01 +0000473{
blueswir1b3ceef22007-06-25 19:56:13 +0000474 SerialState *serial = opaque;
bellarde80cfcf2004-12-19 23:18:01 +0000475 ChannelState *s;
476 uint32_t saddr;
477 int newreg, channel;
478
479 val &= 0xff;
480 saddr = (addr & 3) >> 1;
481 channel = (addr & SERIAL_MAXADDR) >> 2;
blueswir1b3ceef22007-06-25 19:56:13 +0000482 s = &serial->chn[channel];
bellarde80cfcf2004-12-19 23:18:01 +0000483 switch (saddr) {
blueswir112abac82007-12-10 20:05:09 +0000484 case SERIAL_CTRL:
485 SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg,
486 val & 0xff);
blueswir1f930d072007-10-06 11:28:21 +0000487 newreg = 0;
488 switch (s->reg) {
blueswir112abac82007-12-10 20:05:09 +0000489 case W_CMD:
490 newreg = val & CMD_PTR_MASK;
491 val &= CMD_CMD_MASK;
blueswir1f930d072007-10-06 11:28:21 +0000492 switch (val) {
blueswir112abac82007-12-10 20:05:09 +0000493 case CMD_HI:
494 newreg |= CMD_HI;
blueswir1f930d072007-10-06 11:28:21 +0000495 break;
blueswir112abac82007-12-10 20:05:09 +0000496 case CMD_CLR_TXINT:
bellardba3c64f2005-12-05 20:31:52 +0000497 clr_txint(s);
blueswir1f930d072007-10-06 11:28:21 +0000498 break;
blueswir112abac82007-12-10 20:05:09 +0000499 case CMD_CLR_IUS:
bellarde4a89052006-09-09 11:38:11 +0000500 if (s->rxint_under_svc)
501 clr_rxint(s);
502 else if (s->txint_under_svc)
503 clr_txint(s);
blueswir1f930d072007-10-06 11:28:21 +0000504 break;
505 default:
506 break;
507 }
508 break;
blueswir112abac82007-12-10 20:05:09 +0000509 case W_INTR ... W_RXCTRL:
510 case W_SYNC1 ... W_TXBUF:
511 case W_MISC1 ... W_CLOCK:
512 case W_MISC2 ... W_EXTINT:
blueswir1f930d072007-10-06 11:28:21 +0000513 s->wregs[s->reg] = val;
514 break;
blueswir112abac82007-12-10 20:05:09 +0000515 case W_TXCTRL1:
516 case W_TXCTRL2:
blueswir1796d8282008-04-12 08:47:27 +0000517 s->wregs[s->reg] = val;
518 slavio_serial_update_parameters(s);
519 break;
blueswir112abac82007-12-10 20:05:09 +0000520 case W_BRGLO:
521 case W_BRGHI:
blueswir1f930d072007-10-06 11:28:21 +0000522 s->wregs[s->reg] = val;
blueswir1796d8282008-04-12 08:47:27 +0000523 s->rregs[s->reg] = val;
bellard35db0992006-09-09 12:17:15 +0000524 slavio_serial_update_parameters(s);
blueswir1f930d072007-10-06 11:28:21 +0000525 break;
blueswir112abac82007-12-10 20:05:09 +0000526 case W_MINTR:
527 switch (val & MINTR_RST_MASK) {
blueswir1f930d072007-10-06 11:28:21 +0000528 case 0:
529 default:
530 break;
blueswir112abac82007-12-10 20:05:09 +0000531 case MINTR_RST_B:
blueswir1f930d072007-10-06 11:28:21 +0000532 slavio_serial_reset_chn(&serial->chn[1]);
533 return;
blueswir112abac82007-12-10 20:05:09 +0000534 case MINTR_RST_A:
blueswir1f930d072007-10-06 11:28:21 +0000535 slavio_serial_reset_chn(&serial->chn[0]);
536 return;
blueswir112abac82007-12-10 20:05:09 +0000537 case MINTR_RST_ALL:
blueswir1f930d072007-10-06 11:28:21 +0000538 slavio_serial_reset(serial);
539 return;
540 }
541 break;
542 default:
543 break;
544 }
545 if (s->reg == 0)
546 s->reg = newreg;
547 else
548 s->reg = 0;
549 break;
blueswir112abac82007-12-10 20:05:09 +0000550 case SERIAL_DATA:
blueswir1f930d072007-10-06 11:28:21 +0000551 SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
blueswir196c4f562007-08-11 07:54:26 +0000552 s->tx = val;
blueswir112abac82007-12-10 20:05:09 +0000553 if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
blueswir1f930d072007-10-06 11:28:21 +0000554 if (s->chr)
555 qemu_chr_write(s->chr, &s->tx, 1);
blueswir1577390f2007-12-04 20:58:31 +0000556 else if (s->type == kbd && !s->disabled) {
blueswir1f930d072007-10-06 11:28:21 +0000557 handle_kbd_command(s, val);
558 }
559 }
blueswir112abac82007-12-10 20:05:09 +0000560 s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty
561 s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent
blueswir196c4f562007-08-11 07:54:26 +0000562 set_txint(s);
blueswir1f930d072007-10-06 11:28:21 +0000563 break;
bellarde80cfcf2004-12-19 23:18:01 +0000564 default:
blueswir1f930d072007-10-06 11:28:21 +0000565 break;
bellarde80cfcf2004-12-19 23:18:01 +0000566 }
567}
568
bellard3a5c3132005-01-30 22:39:56 +0000569static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
bellarde80cfcf2004-12-19 23:18:01 +0000570{
blueswir1b3ceef22007-06-25 19:56:13 +0000571 SerialState *serial = opaque;
bellarde80cfcf2004-12-19 23:18:01 +0000572 ChannelState *s;
573 uint32_t saddr;
574 uint32_t ret;
575 int channel;
576
577 saddr = (addr & 3) >> 1;
578 channel = (addr & SERIAL_MAXADDR) >> 2;
blueswir1b3ceef22007-06-25 19:56:13 +0000579 s = &serial->chn[channel];
bellarde80cfcf2004-12-19 23:18:01 +0000580 switch (saddr) {
blueswir112abac82007-12-10 20:05:09 +0000581 case SERIAL_CTRL:
582 SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg,
583 s->rregs[s->reg]);
blueswir1f930d072007-10-06 11:28:21 +0000584 ret = s->rregs[s->reg];
585 s->reg = 0;
586 return ret;
blueswir112abac82007-12-10 20:05:09 +0000587 case SERIAL_DATA:
588 s->rregs[R_STATUS] &= ~STATUS_RXAV;
bellardba3c64f2005-12-05 20:31:52 +0000589 clr_rxint(s);
blueswir1f930d072007-10-06 11:28:21 +0000590 if (s->type == kbd || s->type == mouse)
591 ret = get_queue(s);
592 else
593 ret = s->rx;
594 SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
blueswir1b76482e2007-11-25 08:48:16 +0000595 if (s->chr)
596 qemu_chr_accept_input(s->chr);
blueswir1f930d072007-10-06 11:28:21 +0000597 return ret;
bellarde80cfcf2004-12-19 23:18:01 +0000598 default:
blueswir1f930d072007-10-06 11:28:21 +0000599 break;
bellarde80cfcf2004-12-19 23:18:01 +0000600 }
601 return 0;
602}
603
604static int serial_can_receive(void *opaque)
605{
606 ChannelState *s = opaque;
bellarde4a89052006-09-09 11:38:11 +0000607 int ret;
608
blueswir112abac82007-12-10 20:05:09 +0000609 if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) // Rx not enabled
610 || ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV))
611 // char already available
blueswir1f930d072007-10-06 11:28:21 +0000612 ret = 0;
bellarde80cfcf2004-12-19 23:18:01 +0000613 else
blueswir1f930d072007-10-06 11:28:21 +0000614 ret = 1;
bellarde4a89052006-09-09 11:38:11 +0000615 return ret;
bellarde80cfcf2004-12-19 23:18:01 +0000616}
617
618static void serial_receive_byte(ChannelState *s, int ch)
619{
bellard35db0992006-09-09 12:17:15 +0000620 SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
blueswir112abac82007-12-10 20:05:09 +0000621 s->rregs[R_STATUS] |= STATUS_RXAV;
bellarde80cfcf2004-12-19 23:18:01 +0000622 s->rx = ch;
bellardba3c64f2005-12-05 20:31:52 +0000623 set_rxint(s);
bellarde80cfcf2004-12-19 23:18:01 +0000624}
625
626static void serial_receive_break(ChannelState *s)
627{
blueswir112abac82007-12-10 20:05:09 +0000628 s->rregs[R_STATUS] |= STATUS_BRK;
bellarde80cfcf2004-12-19 23:18:01 +0000629 slavio_serial_update_irq(s);
630}
631
632static void serial_receive1(void *opaque, const uint8_t *buf, int size)
633{
634 ChannelState *s = opaque;
635 serial_receive_byte(s, buf[0]);
636}
637
638static void serial_event(void *opaque, int event)
639{
640 ChannelState *s = opaque;
641 if (event == CHR_EVENT_BREAK)
642 serial_receive_break(s);
643}
644
645static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
646 slavio_serial_mem_readb,
blueswir17c560452008-01-01 17:06:38 +0000647 NULL,
648 NULL,
bellarde80cfcf2004-12-19 23:18:01 +0000649};
650
651static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
652 slavio_serial_mem_writeb,
blueswir17c560452008-01-01 17:06:38 +0000653 NULL,
654 NULL,
bellarde80cfcf2004-12-19 23:18:01 +0000655};
656
657static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
658{
blueswir122548762008-05-10 10:12:00 +0000659 uint32_t tmp = 0;
660
pbrookd537cf62007-04-07 18:14:41 +0000661 qemu_put_be32s(f, &tmp); /* unused, was IRQ. */
bellarde80cfcf2004-12-19 23:18:01 +0000662 qemu_put_be32s(f, &s->reg);
663 qemu_put_be32s(f, &s->rxint);
664 qemu_put_be32s(f, &s->txint);
bellarde4a89052006-09-09 11:38:11 +0000665 qemu_put_be32s(f, &s->rxint_under_svc);
666 qemu_put_be32s(f, &s->txint_under_svc);
bellarde80cfcf2004-12-19 23:18:01 +0000667 qemu_put_8s(f, &s->rx);
668 qemu_put_8s(f, &s->tx);
blueswir112abac82007-12-10 20:05:09 +0000669 qemu_put_buffer(f, s->wregs, SERIAL_REGS);
670 qemu_put_buffer(f, s->rregs, SERIAL_REGS);
bellarde80cfcf2004-12-19 23:18:01 +0000671}
672
673static void slavio_serial_save(QEMUFile *f, void *opaque)
674{
675 SerialState *s = opaque;
676
677 slavio_serial_save_chn(f, &s->chn[0]);
678 slavio_serial_save_chn(f, &s->chn[1]);
679}
680
681static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
682{
blueswir122548762008-05-10 10:12:00 +0000683 uint32_t tmp;
pbrookd537cf62007-04-07 18:14:41 +0000684
bellarde4a89052006-09-09 11:38:11 +0000685 if (version_id > 2)
bellarde80cfcf2004-12-19 23:18:01 +0000686 return -EINVAL;
687
pbrookd537cf62007-04-07 18:14:41 +0000688 qemu_get_be32s(f, &tmp); /* unused */
bellarde80cfcf2004-12-19 23:18:01 +0000689 qemu_get_be32s(f, &s->reg);
690 qemu_get_be32s(f, &s->rxint);
691 qemu_get_be32s(f, &s->txint);
bellarde4a89052006-09-09 11:38:11 +0000692 if (version_id >= 2) {
693 qemu_get_be32s(f, &s->rxint_under_svc);
694 qemu_get_be32s(f, &s->txint_under_svc);
695 }
bellarde80cfcf2004-12-19 23:18:01 +0000696 qemu_get_8s(f, &s->rx);
697 qemu_get_8s(f, &s->tx);
blueswir112abac82007-12-10 20:05:09 +0000698 qemu_get_buffer(f, s->wregs, SERIAL_REGS);
699 qemu_get_buffer(f, s->rregs, SERIAL_REGS);
bellarde80cfcf2004-12-19 23:18:01 +0000700 return 0;
701}
702
703static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
704{
705 SerialState *s = opaque;
706 int ret;
707
708 ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
709 if (ret != 0)
blueswir1f930d072007-10-06 11:28:21 +0000710 return ret;
bellarde80cfcf2004-12-19 23:18:01 +0000711 ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
712 return ret;
713
714}
715
blueswir15dcb6b92007-05-19 12:58:30 +0000716SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
717 CharDriverState *chr1, CharDriverState *chr2)
bellarde80cfcf2004-12-19 23:18:01 +0000718{
bellard8be1f5c2005-04-06 20:42:35 +0000719 int slavio_serial_io_memory, i;
bellarde80cfcf2004-12-19 23:18:01 +0000720 SerialState *s;
721
722 s = qemu_mallocz(sizeof(SerialState));
723 if (!s)
724 return NULL;
bellarde80cfcf2004-12-19 23:18:01 +0000725
blueswir112abac82007-12-10 20:05:09 +0000726 slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read,
727 slavio_serial_mem_write,
728 s);
blueswir15aca8c32007-05-26 17:39:43 +0000729 cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
bellarde80cfcf2004-12-19 23:18:01 +0000730
bellard8be1f5c2005-04-06 20:42:35 +0000731 s->chn[0].chr = chr1;
732 s->chn[1].chr = chr2;
blueswir1577390f2007-12-04 20:58:31 +0000733 s->chn[0].disabled = 0;
734 s->chn[1].disabled = 0;
bellard8be1f5c2005-04-06 20:42:35 +0000735
736 for (i = 0; i < 2; i++) {
blueswir1f930d072007-10-06 11:28:21 +0000737 s->chn[i].irq = irq;
738 s->chn[i].chn = 1 - i;
739 s->chn[i].type = ser;
740 if (s->chn[i].chr) {
741 qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
pbrooke5b0bc42007-01-27 23:46:43 +0000742 serial_receive1, serial_event, &s->chn[i]);
blueswir1f930d072007-10-06 11:28:21 +0000743 }
bellarde80cfcf2004-12-19 23:18:01 +0000744 }
bellard8be1f5c2005-04-06 20:42:35 +0000745 s->chn[0].otherchn = &s->chn[1];
746 s->chn[1].otherchn = &s->chn[0];
blueswir112abac82007-12-10 20:05:09 +0000747 register_savevm("slavio_serial", base, 2, slavio_serial_save,
748 slavio_serial_load, s);
bellarde80cfcf2004-12-19 23:18:01 +0000749 qemu_register_reset(slavio_serial_reset, s);
750 slavio_serial_reset(s);
751 return s;
752}
753
bellard8be1f5c2005-04-06 20:42:35 +0000754static const uint8_t keycodes[128] = {
755 127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
756 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
757 79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
758 104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
759 14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
760 113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
761 90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
762 0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
763};
764
blueswir143febf42007-09-21 19:09:35 +0000765static const uint8_t e0_keycodes[128] = {
766 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
767 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0,
768 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
769 0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
770 0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112,
771 113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
772 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
773 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
774};
775
bellarde80cfcf2004-12-19 23:18:01 +0000776static void sunkbd_event(void *opaque, int ch)
777{
778 ChannelState *s = opaque;
bellard8be1f5c2005-04-06 20:42:35 +0000779 int release = ch & 0x80;
780
blueswir112abac82007-12-10 20:05:09 +0000781 KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" :
782 "press");
blueswir1bbbb2f02007-09-23 11:48:47 +0000783 switch (ch) {
784 case 58: // Caps lock press
785 s->caps_lock_mode ^= 1;
786 if (s->caps_lock_mode == 2)
787 return; // Drop second press
788 break;
789 case 69: // Num lock press
790 s->num_lock_mode ^= 1;
791 if (s->num_lock_mode == 2)
792 return; // Drop second press
793 break;
794 case 186: // Caps lock release
795 s->caps_lock_mode ^= 2;
796 if (s->caps_lock_mode == 3)
797 return; // Drop first release
798 break;
799 case 197: // Num lock release
800 s->num_lock_mode ^= 2;
801 if (s->num_lock_mode == 3)
802 return; // Drop first release
803 break;
804 case 0xe0:
blueswir143febf42007-09-21 19:09:35 +0000805 s->e0_mode = 1;
806 return;
blueswir1bbbb2f02007-09-23 11:48:47 +0000807 default:
808 break;
blueswir143febf42007-09-21 19:09:35 +0000809 }
810 if (s->e0_mode) {
811 s->e0_mode = 0;
812 ch = e0_keycodes[ch & 0x7f];
813 } else {
814 ch = keycodes[ch & 0x7f];
815 }
816 KBD_DPRINTF("Translated keycode %2.2x\n", ch);
bellard8be1f5c2005-04-06 20:42:35 +0000817 put_queue(s, ch | release);
818}
819
820static void handle_kbd_command(ChannelState *s, int val)
821{
822 KBD_DPRINTF("Command %d\n", val);
blueswir143febf42007-09-21 19:09:35 +0000823 if (s->led_mode) { // Ignore led byte
824 s->led_mode = 0;
825 return;
826 }
bellard8be1f5c2005-04-06 20:42:35 +0000827 switch (val) {
828 case 1: // Reset, return type code
blueswir167deb562007-04-18 19:21:38 +0000829 clear_queue(s);
blueswir1f930d072007-10-06 11:28:21 +0000830 put_queue(s, 0xff);
831 put_queue(s, 4); // Type 4
832 put_queue(s, 0x7f);
833 break;
blueswir143febf42007-09-21 19:09:35 +0000834 case 0xe: // Set leds
835 s->led_mode = 1;
836 break;
bellard8be1f5c2005-04-06 20:42:35 +0000837 case 7: // Query layout
blueswir167deb562007-04-18 19:21:38 +0000838 case 0xf:
839 clear_queue(s);
blueswir1f930d072007-10-06 11:28:21 +0000840 put_queue(s, 0xfe);
841 put_queue(s, 0); // XXX, layout?
842 break;
bellard8be1f5c2005-04-06 20:42:35 +0000843 default:
blueswir1f930d072007-10-06 11:28:21 +0000844 break;
bellard8be1f5c2005-04-06 20:42:35 +0000845 }
bellarde80cfcf2004-12-19 23:18:01 +0000846}
847
ths5fafdf22007-09-16 21:08:06 +0000848static void sunmouse_event(void *opaque,
bellarde80cfcf2004-12-19 23:18:01 +0000849 int dx, int dy, int dz, int buttons_state)
850{
851 ChannelState *s = opaque;
852 int ch;
853
bellard715748f2006-09-09 11:35:47 +0000854 MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state);
855
856 ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
857
858 if (buttons_state & MOUSE_EVENT_LBUTTON)
859 ch ^= 0x4;
860 if (buttons_state & MOUSE_EVENT_MBUTTON)
861 ch ^= 0x2;
862 if (buttons_state & MOUSE_EVENT_RBUTTON)
863 ch ^= 0x1;
864
865 put_queue(s, ch);
866
867 ch = dx;
868
869 if (ch > 127)
870 ch=127;
871 else if (ch < -127)
872 ch=-127;
873
874 put_queue(s, ch & 0xff);
875
876 ch = -dy;
877
878 if (ch > 127)
879 ch=127;
880 else if (ch < -127)
881 ch=-127;
882
883 put_queue(s, ch & 0xff);
884
885 // MSC protocol specify two extra motion bytes
886
887 put_queue(s, 0);
888 put_queue(s, 0);
bellarde80cfcf2004-12-19 23:18:01 +0000889}
890
blueswir1577390f2007-12-04 20:58:31 +0000891void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
892 int disabled)
bellarde80cfcf2004-12-19 23:18:01 +0000893{
bellard8be1f5c2005-04-06 20:42:35 +0000894 int slavio_serial_io_memory, i;
bellarde80cfcf2004-12-19 23:18:01 +0000895 SerialState *s;
896
897 s = qemu_mallocz(sizeof(SerialState));
898 if (!s)
899 return;
bellard8be1f5c2005-04-06 20:42:35 +0000900 for (i = 0; i < 2; i++) {
blueswir1f930d072007-10-06 11:28:21 +0000901 s->chn[i].irq = irq;
902 s->chn[i].chn = 1 - i;
903 s->chn[i].chr = NULL;
bellard8be1f5c2005-04-06 20:42:35 +0000904 }
905 s->chn[0].otherchn = &s->chn[1];
906 s->chn[1].otherchn = &s->chn[0];
907 s->chn[0].type = mouse;
908 s->chn[1].type = kbd;
blueswir1577390f2007-12-04 20:58:31 +0000909 s->chn[0].disabled = disabled;
910 s->chn[1].disabled = disabled;
bellarde80cfcf2004-12-19 23:18:01 +0000911
blueswir112abac82007-12-10 20:05:09 +0000912 slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read,
913 slavio_serial_mem_write,
914 s);
blueswir15aca8c32007-05-26 17:39:43 +0000915 cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
bellarde80cfcf2004-12-19 23:18:01 +0000916
blueswir112abac82007-12-10 20:05:09 +0000917 qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
918 "QEMU Sun Mouse");
bellard8be1f5c2005-04-06 20:42:35 +0000919 qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
blueswir112abac82007-12-10 20:05:09 +0000920 register_savevm("slavio_serial_mouse", base, 2, slavio_serial_save,
921 slavio_serial_load, s);
bellarde80cfcf2004-12-19 23:18:01 +0000922 qemu_register_reset(slavio_serial_reset, s);
923 slavio_serial_reset(s);
924}