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)