4 * Open Hack'Ware BIOS character devices drivers.
6 * Copyright (c) 2004-2005 Jocelyn Mayer
8 * cuda driver: Copyright (c) 2004-2005 Fabrice Bellard
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License V2
12 * as published by the Free Software Foundation
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 //#define DEBUG_CHARDEV
34 #define CHARDEV_DPRINTF(fmt, args...) \
35 do { dprintf("CHARDEV - %s: " fmt, __func__ , ##args); } while (0)
37 #define CHARDEV_DPRINTF(fmt, args...) do { } while (0)
40 /* Generic character device API */
48 static chardev_t
*char_devices
;
50 int chardev_register (int type
, cops_t
*ops
, void *private)
52 chardev_t
*dev
, **cur
;
54 CHARDEV_DPRINTF("Register char device of type %d\n", type
);
55 if (type
> CHARDEV_LAST
)
57 dev
= malloc(sizeof(chardev_t
));
62 dev
->private = private;
63 for (cur
= &char_devices
; *cur
!= NULL
; cur
= &((*cur
)->next
))
70 int chardev_open (chardev_t
*dev
)
74 if (dev
->ops
->open
== NULL
)
77 return (*dev
->ops
->open
)(dev
->private);
80 int chardev_close (chardev_t
*dev
)
84 if (dev
->ops
->close
== NULL
)
87 return (*dev
->ops
->close
)(dev
->private);
90 int chardev_read (chardev_t
*dev
, void *buffer
, int maxlen
)
96 if (dev
->ops
== NULL
|| dev
->ops
->read
== NULL
)
100 for (len
= 0; len
< maxlen
; len
++) {
101 c
= (*dev
->ops
->read
)(dev
->private);
110 int chardev_write (chardev_t
*dev
, const void *buffer
, int maxlen
)
112 const unsigned char *p
;
116 if (dev
->ops
== NULL
|| dev
->ops
->write
== NULL
)
120 for (len
= 0; len
< maxlen
; len
++) {
122 if ((*dev
->ops
->write
)(dev
->private, c
) < 0)
129 int chardev_type (chardev_t
*dev
)
135 static chardev_t
*console_in_devs
[17], *console_out_devs
[17];
136 static int console_last_in
;
138 int console_open (void)
141 int i
, j
, n
, register_outd
;
146 /* Check all character devices and register those which are usable
147 * as IO for the console
149 CHARDEV_DPRINTF("enter\n");
150 for (cur
= char_devices
; cur
!= NULL
; cur
= cur
->next
, n
++) {
154 CHARDEV_DPRINTF("one serial port\n");
158 CHARDEV_DPRINTF("one input port %d %d\n", n
, i
);
159 if (i
< 16 && chardev_open(cur
) == 0) {
160 console_in_devs
[i
++] = cur
;
165 case CHARDEV_DISPLAY
:
166 CHARDEV_DPRINTF("one output port %d %d\n", n
, j
);
167 if (j
< 16 && chardev_open(cur
) == 0) {
168 console_out_devs
[j
++] = cur
;
172 CHARDEV_DPRINTF("Skip device %d\n", n
);
180 int console_read (void *buffer
, int maxlen
)
185 CHARDEV_DPRINTF("enter\n");
186 /* Get data from the first in device responding to us */
187 cur
= console_in_devs
[console_last_in
];
188 for (i
= console_last_in
;;) {
189 CHARDEV_DPRINTF("read from device %d\n", i
);
190 in
= chardev_read(cur
, buffer
, maxlen
);
194 printf("Read %d chars '%c'...\n", in
, *((char *)buffer
));
198 cur
= console_in_devs
[++i
];
201 cur
= console_in_devs
[0];
203 if (i
== console_last_in
|| cur
== NULL
)
207 CHARDEV_DPRINTF("out\n");
212 int console_write (const void *buffer
, int len
)
217 /* Write data to all devices */
219 for (i
= 0; i
< 16; i
++) {
220 cur
= console_out_devs
[i
];
223 out
= chardev_write(cur
, buffer
, len
);
231 void console_close (void)
236 for (i
= 0; i
< 16; i
++) {
237 cur
= console_out_devs
[i
];
241 console_out_devs
[i
] = NULL
;
245 /* PC serial port "driver" */
246 #define PC_SERIAL_LSR_OFFSET (5)
247 typedef struct pc_serial_t
{
251 static int pc_serial_open (unused
void *private)
256 static int pc_serial_writeb (void *private, int data
)
258 pc_serial_t
*serial
= private;
260 /* Wait for the FIFO to be ready to accept more chars.
261 * Note: this is completely buggy and would never work on real hardware,
262 * as the serial port (especialy the FIFO) has not been programmed
265 if (!(inb(serial
->base
+ PC_SERIAL_LSR_OFFSET
) & 0x20))
267 outb(serial
->base
, data
);
272 static int pc_serial_readb (void *private)
274 pc_serial_t
*serial
= private;
276 if (!(inb(serial
->base
+ PC_SERIAL_LSR_OFFSET
) & 0x01))
279 return inb(serial
->base
);
282 static int pc_serial_close (unused
void *private)
287 static cops_t pc_serial_ops
= {
288 .open
= &pc_serial_open
,
289 .read
= &pc_serial_readb
,
290 .write
= &pc_serial_writeb
,
291 .close
= &pc_serial_close
,
294 /* XXX: debug stuff only ! (TOFIX with a generic debug console) */
295 int serial_write (const void *buffer
, int len
)
299 for (p
= buffer
; len
> 0; len
--) {
300 if (!(inb(0x3F8 + PC_SERIAL_LSR_OFFSET
) & 0x20))
308 int pc_serial_register (uint16_t base
)
312 serial
= malloc(sizeof(pc_serial_t
));
316 /* XXX: TODO: initialize the serial port (FIFO, speed, ...) */
318 return chardev_register(CHARDEV_SERIAL
, &pc_serial_ops
, serial
);
321 /* VGA console device */
322 static int vga_cons_open (unused
void *private)
327 static int vga_cons_writeb (unused
void *private, int data
)
334 static int vga_cons_close (unused
void *private)
339 static cops_t vga_cons_ops
= {
340 .open
= &vga_cons_open
,
342 .write
= &vga_cons_writeb
,
343 .close
= &vga_cons_close
,
346 int vga_console_register (void)
348 return chardev_register(CHARDEV_DISPLAY
, &vga_cons_ops
, NULL
);
351 /* Macintosh via-cuda driver */
353 #define CUDA_DPRINTF(fmt, args...) \
354 do { dprintf("CUDA - %s: " fmt, __func__ , ##args); } while (0)
356 #define CUDA_DPRINTF(fmt, args...) do { } while (0)
359 /* VIA registers - spaced 0x200 bytes apart */
360 #define RS 0x200 /* skip between registers */
361 #define B 0 /* B-side data */
362 #define A RS /* A-side data */
363 #define DIRB (2*RS) /* B-side direction (1=output) */
364 #define DIRA (3*RS) /* A-side direction (1=output) */
365 #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
366 #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
367 #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
368 #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
369 #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */
370 #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */
371 #define SR (10*RS) /* Shift register */
372 #define ACR (11*RS) /* Auxiliary control register */
373 #define PCR (12*RS) /* Peripheral control register */
374 #define IFR (13*RS) /* Interrupt flag register */
375 #define IER (14*RS) /* Interrupt enable register */
376 #define ANH (15*RS) /* A-side data, no handshake */
378 /* Bits in B data register: all active low */
379 #define TREQ 0x08 /* Transfer request (input) */
380 #define TACK 0x10 /* Transfer acknowledge (output) */
381 #define TIP 0x20 /* Transfer in progress (output) */
384 #define SR_CTRL 0x1c /* Shift register control bits */
385 #define SR_EXT 0x0c /* Shift on external clock */
386 #define SR_OUT 0x10 /* Shift out if 1 */
388 /* Bits in IFR and IER */
389 #define IER_SET 0x80 /* set bits in IER */
390 #define IER_CLR 0 /* clear bits in IER */
391 #define SR_INT 0x04 /* Shift register full/empty */
393 #define CUDA_BUF_SIZE 16
396 #define CUDA_PACKET 1
403 static uint8_t cuda_readb (cuda_t
*dev
, int reg
)
405 return *(volatile uint8_t *)(dev
->base
+ reg
);
408 static void cuda_writeb (cuda_t
*dev
, int reg
, uint8_t val
)
410 *(volatile uint8_t *)(dev
->base
+ reg
) = val
;
413 static void cuda_wait_irq (cuda_t
*dev
)
419 val
= cuda_readb(dev
, IFR
);
420 cuda_writeb(dev
, IFR
, val
& 0x7f);
426 static int cuda_request (cuda_t
*dev
, uint8_t pkt_type
, const uint8_t *buf
,
427 int buf_len
, uint8_t *obuf
)
429 int i
, obuf_len
, val
;
431 cuda_writeb(dev
, ACR
, cuda_readb(dev
, ACR
) | SR_OUT
);
432 cuda_writeb(dev
, SR
, pkt_type
);
433 cuda_writeb(dev
, B
, cuda_readb(dev
, B
) & ~TIP
);
435 CUDA_DPRINTF("Send buf len: %d\n", buf_len
);
437 for(i
= 0; i
< buf_len
; i
++) {
439 cuda_writeb(dev
, SR
, buf
[i
]);
440 cuda_writeb(dev
, B
, cuda_readb(dev
, B
) ^ TACK
);
444 cuda_writeb(dev
, ACR
, cuda_readb(dev
, ACR
) & ~SR_OUT
);
446 cuda_writeb(dev
, B
, cuda_readb(dev
, B
) | TIP
| TACK
);
452 cuda_writeb(dev
, B
, cuda_readb(dev
, B
) & ~TIP
);
455 val
= cuda_readb(dev
, SR
);
456 if (obuf_len
< CUDA_BUF_SIZE
)
457 obuf
[obuf_len
++] = val
;
458 if (cuda_readb(dev
, B
) & TREQ
)
460 cuda_writeb(dev
, B
, cuda_readb(dev
, B
) ^ TACK
);
462 cuda_writeb(dev
, B
, cuda_readb(dev
, B
) | TIP
| TACK
);
467 CUDA_DPRINTF("Got len: %d\n", obuf_len
);
476 printf("cuda test:\n");
477 cuda_init(0x80400000 + 0x16000);
479 keycode
= adb_read_key();
481 printf("keycode=%x\n", keycode
);
487 static int cuda_adb_req (void *host
, const uint8_t *snd_buf
, int len
,
490 uint8_t buffer
[CUDA_BUF_SIZE
], *pos
;
492 CUDA_DPRINTF("len: %d %02x\n", len
, snd_buf
[0]);
493 len
= cuda_request(host
, ADB_PACKET
, snd_buf
, len
, buffer
);
494 if (len
> 1 && buffer
[0] == ADB_PACKET
) {
501 memcpy(rcv_buf
, pos
, len
);
506 cuda_t
*cuda_init (uint32_t base
)
510 CUDA_DPRINTF(" base=%08x\n", base
);
511 cuda
= malloc(sizeof(cuda_t
));
515 cuda_writeb(cuda
, B
, cuda_readb(cuda
, B
) | TREQ
| TIP
);
520 /* enable auto poll */
523 len
= cuda_request(cuda
, CUDA_PACKET
, buf
, 2, obuf
);
524 if (len
!= 2 || obuf
[0] != CUDA_PACKET
|| obuf
[1] != 1) {
525 printf("cuda: invalid reply for auto poll request");
531 cuda
->adb_bus
= adb_bus_new(cuda
, &cuda_adb_req
);
532 if (cuda
->adb_bus
== NULL
) {
536 adb_bus_init(cuda
->adb_bus
);
541 void cuda_reset (cuda_t
*cuda
)
543 adb_bus_reset(cuda
->adb_bus
);
546 /* ADB generic driver */
548 #define ADB_DPRINTF(fmt, args...) \
549 do { dprintf("ADB - %s: " fmt, __func__ , ##args); } while (0)
551 #define ADB_DPRINTF(fmt, args...) do { } while (0)
554 int adb_cmd (adb_dev_t
*dev
, uint8_t cmd
, uint8_t reg
,
555 uint8_t *buf
, int len
)
557 uint8_t adb_send
[ADB_BUF_SIZE
], adb_rcv
[ADB_BUF_SIZE
];
559 ADB_DPRINTF("cmd: %d reg: %d len: %d\n", cmd
, reg
, len
);
560 if (dev
->bus
== NULL
|| dev
->bus
->req
== NULL
) {
561 ADB_DPRINTF("ERROR: invalid bus !\n");
565 if (cmd
!= ADB_LISTEN
&& len
!= 0) {
566 /* No buffer transmitted but for LISTEN command */
567 ADB_DPRINTF("in buffer for cmd %d\n", cmd
);
570 if (cmd
== ADB_LISTEN
&& ((len
< 2 || len
> 8) || buf
== NULL
)) {
571 /* Need a buffer with a regular register size for LISTEN command */
572 ADB_DPRINTF("no/invalid buffer for ADB_LISTEN (%d)\n", len
);
575 if ((cmd
== ADB_TALK
|| cmd
== ADB_LISTEN
) && reg
> 3) {
576 /* Need a valid register number for LISTEN and TALK commands */
577 ADB_DPRINTF("invalid reg for TALK/LISTEN command (%d %d)\n", cmd
, reg
);
582 adb_send
[0] = ADB_SEND_RESET
;
585 adb_send
[0] = (dev
->addr
<< 4) | ADB_FLUSH
;
588 memcpy(adb_send
+ 1, buf
, len
);
591 adb_send
[0] = (dev
->addr
<< 4) | cmd
| reg
;
594 memset(adb_rcv
, 0, ADB_BUF_SIZE
);
595 len
= (*dev
->bus
->req
)(dev
->bus
->host
, adb_send
, len
+ 1, adb_rcv
);
597 printf("%x %x %x %x\n", adb_rcv
[0], adb_rcv
[1], adb_rcv
[2], adb_rcv
[3]);
604 /* Register transmitted */
606 memcpy(buf
, adb_rcv
, len
);
609 /* Should never happen */
610 ADB_DPRINTF("Cmd %d returned %d bytes !\n", cmd
, len
);
613 ADB_DPRINTF("retlen: %d\n", len
);
618 void adb_bus_reset (adb_bus_t
*bus
)
623 adb_bus_t
*adb_bus_new (void *host
,
624 int (*req
)(void *host
, const uint8_t *snd_buf
,
625 int len
, uint8_t *rcv_buf
))
629 new = malloc(sizeof(adb_bus_t
));
639 void *adb_kbd_new (void *private);
641 static int adb_mouse_open (void *private);
642 static int adb_mouse_close (void *private);
643 static int adb_mouse_read (void *private);
645 static cops_t adb_mouse_ops
= {
652 /* Check and relocate all ADB devices as suggested in
653 * ADB_manager Apple documentation
655 int adb_bus_init (adb_bus_t
*bus
)
657 uint8_t buffer
[ADB_BUF_SIZE
];
658 uint8_t adb_addresses
[16] =
659 { 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, 0, };
660 adb_dev_t tmp_device
, **cur
;
662 int reloc
= 0, next_free
= 7;
669 memset(&tmp_device
, 0, sizeof(adb_dev_t
));
670 tmp_device
.bus
= bus
;
671 for (address
= 1; address
< 8 && adb_addresses
[reloc
] > 0;) {
672 if (address
== ADB_RES
) {
677 ADB_DPRINTF("Check device on ADB address %d\n", address
);
678 tmp_device
.addr
= address
;
679 switch (adb_reg_get(&tmp_device
, 3, buffer
)) {
681 ADB_DPRINTF("No device on ADB address %d\n", address
);
682 /* Register this address as free */
683 if (adb_addresses
[next_free
] != 0)
684 adb_addresses
[next_free
++] = address
;
685 /* Check next ADB address */
689 /* One device answered :
690 * make it available and relocate it to a free address
692 if (buffer
[0] == ADB_CHADDR
) {
693 /* device self test failed */
694 ADB_DPRINTF("device on ADB address %d self-test failed "
695 "%02x %02x %02x\n", address
,
696 buffer
[0], buffer
[1], buffer
[2]);
699 ADB_DPRINTF("device on ADB address %d self-test OK\n",
703 ADB_DPRINTF("Relocate device on ADB address %d to %d (%d)\n",
704 address
, adb_addresses
[reloc
], reloc
);
705 buffer
[0] = ((buffer
[0] & 0x40) & ~0x90) | adb_addresses
[reloc
];
708 buffer
[1] = ADB_CHADDR_NOCOLL
;
709 if (adb_reg_set(&tmp_device
, 3, buffer
, 2) < 0) {
710 ADB_DPRINTF("ADB device relocation failed\n");
714 *cur
= malloc(sizeof(adb_dev_t
));
718 (*cur
)->type
= address
;
720 (*cur
)->addr
= adb_addresses
[reloc
++];
723 switch ((*cur
)->type
) {
725 ADB_DPRINTF("Found one protected device\n");
728 ADB_DPRINTF("Found one keyboard\n");
732 ADB_DPRINTF("Found one mouse\n");
733 chardev_register(CHARDEV_MOUSE
, &adb_mouse_ops
, *cur
);
736 ADB_DPRINTF("Found one absolute positioning device\n");
739 ADB_DPRINTF("Found one modem\n");
742 ADB_DPRINTF("Found one ADB res device\n");
745 ADB_DPRINTF("Found one ADB misc device\n");
748 cur
= &((*cur
)->next
);
753 /* SHOULD NOT HAPPEN : register 3 is always two bytes long */
754 ADB_DPRINTF("Invalid returned len for ADB register 3\n");
758 ADB_DPRINTF("error gettting ADB register 3\n");
766 /* ADB mouse chardev interface (TODO) */
767 static int adb_mouse_open (unused
void *private)
772 static int adb_mouse_close (unused
void *private)
777 static int adb_mouse_read (unused
void *private)