home *** CD-ROM | disk | FTP | other *** search
-
- /*
- =====
- CRU.C
- =====
-
- Communications Register Unit routines
-
- */
-
- #define __CRU__
-
- #include <stdlib.h>
-
- #include "v9t9_common.h"
- #include "cru.h"
- #include "9901.h"
-
- #define _L LOG_CRU | LOG_INFO
-
- /************************************************************/
-
- /* In order to most efficiently handle CRU requests,
- we no longer support multi-bit CRU operations. */
- typedef struct crudevicelist {
- u32 addr; /* base address */
- crufunc *handler;
- struct crudevicelist *next;
- } crudevicelist;
-
- static crudevicelist *cruwritedevices, *crureaddevices;
-
- void
- cruinit(void)
- {
- cruwritedevices = crureaddevices = NULL;
- }
-
-
- /***************************************************/
-
- static void
- crudevicedump(void)
- {
- struct crudevicelist *ptr;
-
- logger(_L | 0, "crudevicedump:");
- logger(_L | 0, "\tREAD:\n");
- ptr = crureaddevices;
- while (ptr) {
- logger(_L | 0, "\t\tdevice = >%04X\n\n", ptr->addr);
- ptr = ptr->next;
- }
-
- logger(_L | 0, "\tWRITE:");
- ptr = cruwritedevices;
- while (ptr) {
- logger(_L | 0, "\t\tdevice = >%04X\n\n", ptr->addr);
- ptr = ptr->next;
- }
- }
-
- /*
- Insert an address into the CRU device list.
-
- Sorts entries by address.
-
- Returns 1 if success, or 0 if failure.
- */
- int
- cruadddevice(int rw, u32 addr, u32 bits, crufunc * handler)
- {
- crudevicelist **head, *ptr, *tmp;
- crudevicelist *new;
-
- if (addr >= 0x2000) {
- logger(_L | LOG_ERROR | LOG_USER, "cruadddevice: address 0x%x is invalid\n",
- addr);
- return 0;
- }
-
- if (bits > 1) {
- logger(_L | LOG_ERROR | LOG_USER,
- "cruadddevice: only single-bit ranges supported (0x%04X, %d)\n",
- addr, bits);
- return 0;
- }
-
- if (rw == CRU_READ)
- head = &crureaddevices;
- else if (rw == CRU_WRITE)
- head = &cruwritedevices;
- else {
- logger(_L | LOG_ERROR | LOG_USER,
- "cruadddevice: invalid 'rw' flag (%d) passed\n", rw);
- return 0;
- }
-
- new = (struct crudevicelist *) xmalloc(sizeof *new);
-
- new->addr = addr;
- new->handler = handler;
- new->next = NULL;
-
- if (*head) {
- ptr = *head;
- tmp = NULL;
- while (ptr && addr >= ptr->addr) {
- tmp = ptr;
- ptr = ptr->next;
- }
- if (ptr && addr == ptr->addr) {
- logger(_L | LOG_ERROR | LOG_USER,
- "cruadddevice: overlapping I/O (0x%x)\n", ptr->addr);
- return 0;
- }
- if (tmp) {
- new->next = tmp->next;
- tmp->next = new;
- } else {
- new->next = ptr;
- *head = new;
- }
- } else
- *head = new;
-
- if (log_level(LOG_CRU) >= 2)
- crudevicedump();
-
- return 1;
- }
-
- int
- crudeldevice(int rw, u32 addr, u32 bits, crufunc * handler)
- {
- crudevicelist **head, *ptr, *tmp;
-
- if (addr >= 0x2000) {
- logger(_L | LOG_ERROR | LOG_USER, "crudeldevice: address 0x%x is invalid\n",
- addr);
- return 0;
- }
-
- if (bits > 1) {
- logger(_L | LOG_ERROR | LOG_USER,
- "crudeldevice: only single-bit ranges supported (0x%04X, %d)\n",
- addr, bits);
- return 0;
- }
-
- if (rw == CRU_READ)
- head = &crureaddevices;
- else if (rw == CRU_WRITE)
- head = &cruwritedevices;
- else {
- logger(_L | LOG_ERROR | LOG_USER,
- "crudeldevice: invalid 'rw' flag (%d) passed\n", rw);
- return 0;
- }
-
- while (*head) {
- tmp = NULL;
-
- if ((*head)->addr == addr && handler == (*head)->handler) {
- ptr = *head;
- *head = (*head)->next;
- xfree(ptr);
- return 1;
- }
- head = &(*head)->next;
- }
-
- logger(_L | LOG_ERROR | LOG_USER, "crudeldevice: device not found (0x%x)\n",
- addr);
- return 0;
- }
-
-
- /***************************************************/
-
- void
- cruwrite(u32 addr, u32 val, u32 num)
- {
- crudevicelist *ptr = cruwritedevices;
-
- addr &= 0x1fff;
- logger(_L | L_2, "CRU write: >%04X[%d], %04X\n", addr, num, val & 0xffff);
-
- if (addr >= 0x30) {
- setclockmode9901(0);
- }
-
- while (ptr && num) {
- if (ptr->addr > addr) {
- /* if we've already passed a handler for addr,
- shift out the lost bits */
- int lost = (ptr->addr - addr) / 2;
-
- if (lost > num)
- lost = num;
-
-
- val >>= lost;
- num -= lost;
- addr = ptr->addr;
- logger(_L | L_2, "cruwrite: skipping bits, range is now %04X[%d]\n", addr,
- num);
- }
-
- if (addr == ptr->addr && num) {
- int used;
- u32 mask;
-
- logger(_L | L_2, "cruwrite: handling %04X[%d] with %04X\n",
- addr, num, ptr->addr);
-
- used = 1;
- mask = ~(~0 << used);
- (ptr->handler) (addr, val & mask, used);
-
- num -= used;
- addr += used * 2;
- val >>= used;
- }
- ptr = ptr->next;
-
- }
- }
-
- /*
- Routines write 1. Shift answer left into output.
- */
-
- #include "keyboard.h"
-
- u32 cruread(u32 addr, u32 num)
- {
- crudevicelist *ptr = crureaddevices;
- u32 orgaddr = addr;
- u32 val = 0;
-
- //(num >= 8) ? 0xff00 : 0xffff;
-
- addr &= 0x1fff;
- orgaddr = addr;
- logger(_L | L_2, "CRU read: >%04X[%d] = \n", addr, num);
-
- if (addr >= 0x30) {
- setclockmode9901(0);
- }
-
- while (ptr && num) {
-
- /* if we've already passed a handler for addr,
- shift out the lost bits */
- if (ptr->addr > addr) {
- int lost = (ptr->addr - addr) / 2;
-
- if (lost > num)
- lost = num;
-
- num -= lost;
- addr = ptr->addr;
- logger(_L | L_2, "cruread: skipping bits, range is now %04X[%d]\n", addr,
- num);
- }
-
- if (addr == ptr->addr && num) {
- int used;
- u32 mask, bits, shift;
-
- logger(_L | L_2, "cruread: handling %04X[%d] with %04X\n",
- addr, num, ptr->addr);
-
- used = 1;
- mask = ~((~0) << used);
- shift = (addr - orgaddr) / 2;
- bits = ((ptr->handler) (addr, val, used) & mask);
- val = (val & ~(mask << shift)) | (bits << shift);
- num -= used;
- addr += used * 2;
- }
- ptr = ptr->next;
-
- }
- if (orgaddr == 0x6 && 0xff != (val & 0xff))
- logger(_L | L_2, "keyrow: %2X/%04X\n", crukeyboardmap[crukeyboardcol],
- val & 0xffff);
- return val & 0xffff;
- }
-