diff options
Diffstat (limited to 'qemu/roms/openhackware/src/char.c')
-rw-r--r-- | qemu/roms/openhackware/src/char.c | 780 |
1 files changed, 0 insertions, 780 deletions
diff --git a/qemu/roms/openhackware/src/char.c b/qemu/roms/openhackware/src/char.c deleted file mode 100644 index 4e74ac6af..000000000 --- a/qemu/roms/openhackware/src/char.c +++ /dev/null @@ -1,780 +0,0 @@ -/* - * <char.c> - * - * Open Hack'Ware BIOS character devices drivers. - * - * Copyright (c) 2004-2005 Jocelyn Mayer - * - * cuda driver: Copyright (c) 2004-2005 Fabrice Bellard - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License V2 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <stdlib.h> -#include <stdio.h> -#include "bios.h" -#include "adb.h" - -//#define DEBUG_CHARDEV -//#define DEBUG_CUDA -//#define DEBUG_ADB - -#ifdef DEBUG_CHARDEV -#define CHARDEV_DPRINTF(fmt, args...) \ -do { dprintf("CHARDEV - %s: " fmt, __func__ , ##args); } while (0) -#else -#define CHARDEV_DPRINTF(fmt, args...) do { } while (0) -#endif - -/* Generic character device API */ -struct chardev_t { - chardev_t *next; - int type; - cops_t *ops; - void *private; -}; - -static chardev_t *char_devices; - -int chardev_register (int type, cops_t *ops, void *private) -{ - chardev_t *dev, **cur; - - CHARDEV_DPRINTF("Register char device of type %d\n", type); - if (type > CHARDEV_LAST) - return -1; - dev = malloc(sizeof(chardev_t)); - if (dev == NULL) - return -1; - dev->type = type; - dev->ops = ops; - dev->private = private; - for (cur = &char_devices; *cur != NULL; cur = &((*cur)->next)) - continue; - *cur = dev; - - return 0; -} - -int chardev_open (chardev_t *dev) -{ - if (dev->ops == NULL) - return -1; - if (dev->ops->open == NULL) - return 0; - - return (*dev->ops->open)(dev->private); -} - -int chardev_close (chardev_t *dev) -{ - if (dev->ops == NULL) - return -1; - if (dev->ops->close == NULL) - return 0; - - return (*dev->ops->close)(dev->private); -} - -int chardev_read (chardev_t *dev, void *buffer, int maxlen) -{ - unsigned char *p; - int len; - int c; - - if (dev->ops == NULL || dev->ops->read == NULL) - return -1; - - p = buffer; - for (len = 0; len < maxlen; len++) { - c = (*dev->ops->read)(dev->private); - if (c < 0) - break; - *p++ = c; - } - - return len; -} - -int chardev_write (chardev_t *dev, const void *buffer, int maxlen) -{ - const unsigned char *p; - int len; - int c; - - if (dev->ops == NULL || dev->ops->write == NULL) - return -1; - - p = buffer; - for (len = 0; len < maxlen; len++) { - c = *p++; - if ((*dev->ops->write)(dev->private, c) < 0) - break; - } - - return len; -} - -int chardev_type (chardev_t *dev) -{ - return dev->type; -} - -/* Console driver */ -static chardev_t *console_in_devs[17], *console_out_devs[17]; -static int console_last_in; - -int console_open (void) -{ - chardev_t *cur; - int i, j, n, register_outd; - - i = 0; - j = 0; - n = 0; - /* Check all character devices and register those which are usable - * as IO for the console - */ - CHARDEV_DPRINTF("enter\n"); - for (cur = char_devices; cur != NULL; cur = cur->next, n++) { - register_outd = 0; - switch (cur->type) { - case CHARDEV_SERIAL: - CHARDEV_DPRINTF("one serial port\n"); - register_outd = 1; - /* No break here */ - case CHARDEV_KBD: - CHARDEV_DPRINTF("one input port %d %d\n", n, i); - if (i < 16 && chardev_open(cur) == 0) { - console_in_devs[i++] = cur; - } - if (!register_outd) - break; - /* No break here */ - case CHARDEV_DISPLAY: - CHARDEV_DPRINTF("one output port %d %d\n", n, j); - if (j < 16 && chardev_open(cur) == 0) { - console_out_devs[j++] = cur; - } - break; - default: - CHARDEV_DPRINTF("Skip device %d\n", n); - break; - } - } - - return 0; -} - -int console_read (void *buffer, int maxlen) -{ - chardev_t *cur; - int i, in; - - CHARDEV_DPRINTF("enter\n"); - /* Get data from the first in device responding to us */ - cur = console_in_devs[console_last_in]; - for (i = console_last_in;;) { - CHARDEV_DPRINTF("read from device %d\n", i); - in = chardev_read(cur, buffer, maxlen); - if (in > 0) { - console_last_in = i; -#if 0 - printf("Read %d chars '%c'...\n", in, *((char *)buffer)); -#endif - return in; - } - cur = console_in_devs[++i]; - if (cur == NULL) { - i = 0; - cur = console_in_devs[0]; - } - if (i == console_last_in || cur == NULL) - break; - } - console_last_in = i; - CHARDEV_DPRINTF("out\n"); - - return 0; -} - -int console_write (const void *buffer, int len) -{ - chardev_t *cur; - int i, out, max; - - /* Write data to all devices */ - max = 0; - for (i = 0; i < 16; i++) { - cur = console_out_devs[i]; - if (cur == NULL) - break; - out = chardev_write(cur, buffer, len); - if (out > max) - max = out; - } - - return max; -} - -void console_close (void) -{ - chardev_t *cur; - int i; - - for (i = 0; i < 16; i++) { - cur = console_out_devs[i]; - if (cur == NULL) - break; - chardev_close(cur); - console_out_devs[i] = NULL; - } -} - -/* PC serial port "driver" */ -#define PC_SERIAL_LSR_OFFSET (5) -typedef struct pc_serial_t { - uint16_t base; -} pc_serial_t; - -static int pc_serial_open (unused void *private) -{ - return 0; -} - -static int pc_serial_writeb (void *private, int data) -{ - pc_serial_t *serial = private; - - /* Wait for the FIFO to be ready to accept more chars. - * Note: this is completely buggy and would never work on real hardware, - * as the serial port (especialy the FIFO) has not been programmed - * anywhere before ! - */ - if (!(inb(serial->base + PC_SERIAL_LSR_OFFSET) & 0x20)) - usleep(100); - outb(serial->base, data); - - return 0; -} - -static int pc_serial_readb (void *private) -{ - pc_serial_t *serial = private; - - if (!(inb(serial->base + PC_SERIAL_LSR_OFFSET) & 0x01)) - return -1; - - return inb(serial->base); -} - -static int pc_serial_close (unused void *private) -{ - return 0; -} - -static cops_t pc_serial_ops = { - .open = &pc_serial_open, - .read = &pc_serial_readb, - .write = &pc_serial_writeb, - .close = &pc_serial_close, -}; - -/* XXX: debug stuff only ! (TOFIX with a generic debug console) */ -int serial_write (const void *buffer, int len) -{ - const char *p; - - for (p = buffer; len > 0; len--) { - if (!(inb(0x3F8 + PC_SERIAL_LSR_OFFSET) & 0x20)) - usleep(100); - outb(0x3F8, *p++); - } - - return 0; -} - -int pc_serial_register (uint16_t base) -{ - pc_serial_t *serial; - - serial = malloc(sizeof(pc_serial_t)); - if (serial == NULL) - return -1; - serial->base = base; - /* XXX: TODO: initialize the serial port (FIFO, speed, ...) */ - - return chardev_register(CHARDEV_SERIAL, &pc_serial_ops, serial); -} - -/* VGA console device */ -static int vga_cons_open (unused void *private) -{ - return 0; -} - -static int vga_cons_writeb (unused void *private, int data) -{ - vga_putchar(data); - - return 0; -} - -static int vga_cons_close (unused void *private) -{ - return 0; -} - -static cops_t vga_cons_ops = { - .open = &vga_cons_open, - .read = NULL, - .write = &vga_cons_writeb, - .close = &vga_cons_close, -}; - -int vga_console_register (void) -{ - return chardev_register(CHARDEV_DISPLAY, &vga_cons_ops, NULL); -} - -/* Macintosh via-cuda driver */ -#ifdef DEBUG_CUDA -#define CUDA_DPRINTF(fmt, args...) \ -do { dprintf("CUDA - %s: " fmt, __func__ , ##args); } while (0) -#else -#define CUDA_DPRINTF(fmt, args...) do { } while (0) -#endif - -/* VIA registers - spaced 0x200 bytes apart */ -#define RS 0x200 /* skip between registers */ -#define B 0 /* B-side data */ -#define A RS /* A-side data */ -#define DIRB (2*RS) /* B-side direction (1=output) */ -#define DIRA (3*RS) /* A-side direction (1=output) */ -#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ -#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ -#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ -#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ -#define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ -#define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ -#define SR (10*RS) /* Shift register */ -#define ACR (11*RS) /* Auxiliary control register */ -#define PCR (12*RS) /* Peripheral control register */ -#define IFR (13*RS) /* Interrupt flag register */ -#define IER (14*RS) /* Interrupt enable register */ -#define ANH (15*RS) /* A-side data, no handshake */ - -/* Bits in B data register: all active low */ -#define TREQ 0x08 /* Transfer request (input) */ -#define TACK 0x10 /* Transfer acknowledge (output) */ -#define TIP 0x20 /* Transfer in progress (output) */ - -/* Bits in ACR */ -#define SR_CTRL 0x1c /* Shift register control bits */ -#define SR_EXT 0x0c /* Shift on external clock */ -#define SR_OUT 0x10 /* Shift out if 1 */ - -/* Bits in IFR and IER */ -#define IER_SET 0x80 /* set bits in IER */ -#define IER_CLR 0 /* clear bits in IER */ -#define SR_INT 0x04 /* Shift register full/empty */ - -#define CUDA_BUF_SIZE 16 - -#define ADB_PACKET 0 -#define CUDA_PACKET 1 - -struct cuda_t { - uint32_t base; - adb_bus_t *adb_bus; -}; - -static uint8_t cuda_readb (cuda_t *dev, int reg) -{ - return *(volatile uint8_t *)(dev->base + reg); -} - -static void cuda_writeb (cuda_t *dev, int reg, uint8_t val) -{ - *(volatile uint8_t *)(dev->base + reg) = val; -} - -static void cuda_wait_irq (cuda_t *dev) -{ - int val; - - CUDA_DPRINTF("\n"); - for(;;) { - val = cuda_readb(dev, IFR); - cuda_writeb(dev, IFR, val & 0x7f); - if (val & SR_INT) - break; - } -} - -static int cuda_request (cuda_t *dev, uint8_t pkt_type, const uint8_t *buf, - int buf_len, uint8_t *obuf) -{ - int i, obuf_len, val; - - cuda_writeb(dev, ACR, cuda_readb(dev, ACR) | SR_OUT); - cuda_writeb(dev, SR, pkt_type); - cuda_writeb(dev, B, cuda_readb(dev, B) & ~TIP); - if (buf) { - CUDA_DPRINTF("Send buf len: %d\n", buf_len); - /* send 'buf' */ - for(i = 0; i < buf_len; i++) { - cuda_wait_irq(dev); - cuda_writeb(dev, SR, buf[i]); - cuda_writeb(dev, B, cuda_readb(dev, B) ^ TACK); - } - } - cuda_wait_irq(dev); - cuda_writeb(dev, ACR, cuda_readb(dev, ACR) & ~SR_OUT); - cuda_readb(dev, SR); - cuda_writeb(dev, B, cuda_readb(dev, B) | TIP | TACK); - - obuf_len = 0; - if (obuf) { - cuda_wait_irq(dev); - cuda_readb(dev, SR); - cuda_writeb(dev, B, cuda_readb(dev, B) & ~TIP); - for(;;) { - cuda_wait_irq(dev); - val = cuda_readb(dev, SR); - if (obuf_len < CUDA_BUF_SIZE) - obuf[obuf_len++] = val; - if (cuda_readb(dev, B) & TREQ) - break; - cuda_writeb(dev, B, cuda_readb(dev, B) ^ TACK); - } - cuda_writeb(dev, B, cuda_readb(dev, B) | TIP | TACK); - - cuda_wait_irq(dev); - cuda_readb(dev, SR); - } - CUDA_DPRINTF("Got len: %d\n", obuf_len); - - return obuf_len; -} - -#if 0 -void cuda_test(void) -{ - int keycode; - printf("cuda test:\n"); - cuda_init(0x80400000 + 0x16000); - for(;;) { - keycode = adb_read_key(); - if (keycode >= 0) - printf("keycode=%x\n", keycode); - } -} -#endif - -/* Cuda ADB glue */ -static int cuda_adb_req (void *host, const uint8_t *snd_buf, int len, - uint8_t *rcv_buf) -{ - uint8_t buffer[CUDA_BUF_SIZE], *pos; - - CUDA_DPRINTF("len: %d %02x\n", len, snd_buf[0]); - len = cuda_request(host, ADB_PACKET, snd_buf, len, buffer); - if (len > 1 && buffer[0] == ADB_PACKET) { - pos = buffer + 2; - len -= 2; - } else { - pos = buffer + 1; - len = -1; - } - memcpy(rcv_buf, pos, len); - - return len; -} - -cuda_t *cuda_init (uint32_t base) -{ - cuda_t *cuda; - - CUDA_DPRINTF(" base=%08x\n", base); - cuda = malloc(sizeof(cuda_t)); - if (cuda == NULL) - return NULL; - cuda->base = base; - cuda_writeb(cuda, B, cuda_readb(cuda, B) | TREQ | TIP); -#if 0 - { - int len; - - /* enable auto poll */ - buf[0] = 0x01; - buf[1] = 1; - len = cuda_request(cuda, CUDA_PACKET, buf, 2, obuf); - if (len != 2 || obuf[0] != CUDA_PACKET || obuf[1] != 1) { - printf("cuda: invalid reply for auto poll request"); - free(cuda); - return NULL; - } - } -#endif - cuda->adb_bus = adb_bus_new(cuda, &cuda_adb_req); - if (cuda->adb_bus == NULL) { - free(cuda); - return NULL; - } - adb_bus_init(cuda->adb_bus); - - return cuda; -} - -void cuda_reset (cuda_t *cuda) -{ - adb_bus_reset(cuda->adb_bus); -} - -/* ADB generic driver */ -#ifdef DEBUG_ADB -#define ADB_DPRINTF(fmt, args...) \ -do { dprintf("ADB - %s: " fmt, __func__ , ##args); } while (0) -#else -#define ADB_DPRINTF(fmt, args...) do { } while (0) -#endif - -int adb_cmd (adb_dev_t *dev, uint8_t cmd, uint8_t reg, - uint8_t *buf, int len) -{ - uint8_t adb_send[ADB_BUF_SIZE], adb_rcv[ADB_BUF_SIZE]; - - ADB_DPRINTF("cmd: %d reg: %d len: %d\n", cmd, reg, len); - if (dev->bus == NULL || dev->bus->req == NULL) { - ADB_DPRINTF("ERROR: invalid bus !\n"); - bug(); - } - /* Sanity checks */ - if (cmd != ADB_LISTEN && len != 0) { - /* No buffer transmitted but for LISTEN command */ - ADB_DPRINTF("in buffer for cmd %d\n", cmd); - return -1; - } - if (cmd == ADB_LISTEN && ((len < 2 || len > 8) || buf == NULL)) { - /* Need a buffer with a regular register size for LISTEN command */ - ADB_DPRINTF("no/invalid buffer for ADB_LISTEN (%d)\n", len); - return -1; - } - if ((cmd == ADB_TALK || cmd == ADB_LISTEN) && reg > 3) { - /* Need a valid register number for LISTEN and TALK commands */ - ADB_DPRINTF("invalid reg for TALK/LISTEN command (%d %d)\n", cmd, reg); - return -1; - } - switch (cmd) { - case ADB_SEND_RESET: - adb_send[0] = ADB_SEND_RESET; - break; - case ADB_FLUSH: - adb_send[0] = (dev->addr << 4) | ADB_FLUSH; - break; - case ADB_LISTEN: - memcpy(adb_send + 1, buf, len); - /* No break here */ - case ADB_TALK: - adb_send[0] = (dev->addr << 4) | cmd | reg; - break; - } - memset(adb_rcv, 0, ADB_BUF_SIZE); - len = (*dev->bus->req)(dev->bus->host, adb_send, len + 1, adb_rcv); -#ifdef DEBUG_ADB - printf("%x %x %x %x\n", adb_rcv[0], adb_rcv[1], adb_rcv[2], adb_rcv[3]); -#endif - switch (len) { - case 0: - /* No data */ - break; - case 2 ... 8: - /* Register transmitted */ - if (buf != NULL) - memcpy(buf, adb_rcv, len); - break; - default: - /* Should never happen */ - ADB_DPRINTF("Cmd %d returned %d bytes !\n", cmd, len); - return -1; - } - ADB_DPRINTF("retlen: %d\n", len); - - return len; -} - -void adb_bus_reset (adb_bus_t *bus) -{ - adb_reset(bus); -} - -adb_bus_t *adb_bus_new (void *host, - int (*req)(void *host, const uint8_t *snd_buf, - int len, uint8_t *rcv_buf)) -{ - adb_bus_t *new; - - new = malloc(sizeof(adb_bus_t)); - if (new == NULL) - return NULL; - new->host = host; - new->req = req; - - return new; -} - -/* ADB */ -void *adb_kbd_new (void *private); - -static int adb_mouse_open (void *private); -static int adb_mouse_close (void *private); -static int adb_mouse_read (void *private); - -static cops_t adb_mouse_ops = { - &adb_mouse_open, - &adb_mouse_close, - &adb_mouse_read, - NULL, -}; - -/* Check and relocate all ADB devices as suggested in - * ADB_manager Apple documentation - */ -int adb_bus_init (adb_bus_t *bus) -{ - uint8_t buffer[ADB_BUF_SIZE]; - uint8_t adb_addresses[16] = - { 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, 0, }; - adb_dev_t tmp_device, **cur; - int address; - int reloc = 0, next_free = 7; - int keep; - - /* Reset the bus */ - ADB_DPRINTF("\n"); - adb_reset(bus); - cur = &bus->devices; - memset(&tmp_device, 0, sizeof(adb_dev_t)); - tmp_device.bus = bus; - for (address = 1; address < 8 && adb_addresses[reloc] > 0;) { - if (address == ADB_RES) { - /* Reserved */ - address++; - continue; - } - ADB_DPRINTF("Check device on ADB address %d\n", address); - tmp_device.addr = address; - switch (adb_reg_get(&tmp_device, 3, buffer)) { - case 0: - ADB_DPRINTF("No device on ADB address %d\n", address); - /* Register this address as free */ - if (adb_addresses[next_free] != 0) - adb_addresses[next_free++] = address; - /* Check next ADB address */ - address++; - break; - case 2: - /* One device answered : - * make it available and relocate it to a free address - */ - if (buffer[0] == ADB_CHADDR) { - /* device self test failed */ - ADB_DPRINTF("device on ADB address %d self-test failed " - "%02x %02x %02x\n", address, - buffer[0], buffer[1], buffer[2]); - keep = 0; - } else { - ADB_DPRINTF("device on ADB address %d self-test OK\n", - address); - keep = 1; - } - ADB_DPRINTF("Relocate device on ADB address %d to %d (%d)\n", - address, adb_addresses[reloc], reloc); - buffer[0] = ((buffer[0] & 0x40) & ~0x90) | adb_addresses[reloc]; - if (keep == 1) - buffer[0] |= 0x20; - buffer[1] = ADB_CHADDR_NOCOLL; - if (adb_reg_set(&tmp_device, 3, buffer, 2) < 0) { - ADB_DPRINTF("ADB device relocation failed\n"); - return -1; - } - if (keep == 1) { - *cur = malloc(sizeof(adb_dev_t)); - if (*cur == NULL) { - return -1; - } - (*cur)->type = address; - (*cur)->bus = bus; - (*cur)->addr = adb_addresses[reloc++]; - /* Flush buffers */ - adb_flush(*cur); - switch ((*cur)->type) { - case ADB_PROTECT: - ADB_DPRINTF("Found one protected device\n"); - break; - case ADB_KEYBD: - ADB_DPRINTF("Found one keyboard\n"); - adb_kbd_new(*cur); - break; - case ADB_MOUSE: - ADB_DPRINTF("Found one mouse\n"); - chardev_register(CHARDEV_MOUSE, &adb_mouse_ops, *cur); - break; - case ADB_ABS: - ADB_DPRINTF("Found one absolute positioning device\n"); - break; - case ADB_MODEM: - ADB_DPRINTF("Found one modem\n"); - break; - case ADB_RES: - ADB_DPRINTF("Found one ADB res device\n"); - break; - case ADB_MISC: - ADB_DPRINTF("Found one ADB misc device\n"); - break; - } - cur = &((*cur)->next); - } - break; - case 1: - case 3 ... 7: - /* SHOULD NOT HAPPEN : register 3 is always two bytes long */ - ADB_DPRINTF("Invalid returned len for ADB register 3\n"); - return -1; - case -1: - /* ADB ERROR */ - ADB_DPRINTF("error gettting ADB register 3\n"); - return -1; - } - } - - return 0; -} - -/* ADB mouse chardev interface (TODO) */ -static int adb_mouse_open (unused void *private) -{ - return 0; -} - -static int adb_mouse_close (unused void *private) -{ - return 0; -} - -static int adb_mouse_read (unused void *private) -{ - return -1; -} |