home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / cru.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  5.5 KB  |  291 lines

  1.  
  2. /*
  3.     =====
  4.     CRU.C
  5.     =====
  6.     
  7.     Communications Register Unit routines
  8.  
  9. */
  10.  
  11. #define __CRU__
  12.  
  13. #include <stdlib.h>
  14.  
  15. #include "v9t9_common.h"
  16. #include "cru.h"
  17. #include "9901.h"
  18.  
  19. #define _L     LOG_CRU | LOG_INFO
  20.  
  21. /************************************************************/
  22.  
  23. /*    In order to most efficiently handle CRU requests,
  24.     we no longer support multi-bit CRU operations.  */
  25. typedef struct crudevicelist {
  26.     u32         addr;        /*  base address */
  27.     crufunc    *handler;
  28.     struct crudevicelist *next;
  29. } crudevicelist;
  30.  
  31. static crudevicelist *cruwritedevices, *crureaddevices;
  32.  
  33. void        
  34. cruinit(void)
  35. {
  36.     cruwritedevices = crureaddevices = NULL;
  37. }
  38.  
  39.  
  40. /***************************************************/
  41.  
  42. static void
  43. crudevicedump(void)
  44. {
  45.     struct crudevicelist *ptr;
  46.  
  47.     logger(_L | 0, "crudevicedump:");
  48.     logger(_L | 0, "\tREAD:\n");
  49.     ptr = crureaddevices;
  50.     while (ptr) {
  51.         logger(_L | 0, "\t\tdevice = >%04X\n\n", ptr->addr);
  52.         ptr = ptr->next;
  53.     }
  54.  
  55.     logger(_L | 0, "\tWRITE:");
  56.     ptr = cruwritedevices;
  57.     while (ptr) {
  58.         logger(_L | 0, "\t\tdevice = >%04X\n\n", ptr->addr);
  59.         ptr = ptr->next;
  60.     }
  61. }
  62.  
  63. /*
  64.     Insert an address into the CRU device list.
  65.     
  66.     Sorts entries by address.
  67.  
  68.     Returns 1 if success, or 0 if failure.
  69. */
  70. int
  71. cruadddevice(int rw, u32 addr, u32 bits, crufunc * handler)
  72. {
  73.     crudevicelist **head, *ptr, *tmp;
  74.     crudevicelist *new;
  75.  
  76.     if (addr >= 0x2000) {
  77.         logger(_L | LOG_ERROR | LOG_USER, "cruadddevice:  address 0x%x is invalid\n",
  78.              addr);
  79.         return 0;
  80.     }
  81.  
  82.     if (bits > 1) {
  83.         logger(_L | LOG_ERROR | LOG_USER,
  84.              "cruadddevice:  only single-bit ranges supported (0x%04X, %d)\n",
  85.              addr, bits);
  86.         return 0;
  87.     }
  88.  
  89.     if (rw == CRU_READ)
  90.         head = &crureaddevices;
  91.     else if (rw == CRU_WRITE)
  92.         head = &cruwritedevices;
  93.     else {
  94.         logger(_L | LOG_ERROR | LOG_USER,
  95.              "cruadddevice:  invalid 'rw' flag (%d) passed\n", rw);
  96.         return 0;
  97.     }
  98.  
  99.     new = (struct crudevicelist *) xmalloc(sizeof *new);
  100.  
  101.     new->addr = addr;
  102.     new->handler = handler;
  103.     new->next = NULL;
  104.  
  105.     if (*head) {
  106.         ptr = *head;
  107.         tmp = NULL;
  108.         while (ptr && addr >= ptr->addr) {
  109.             tmp = ptr;
  110.             ptr = ptr->next;
  111.         }
  112.         if (ptr && addr == ptr->addr) {
  113.             logger(_L | LOG_ERROR | LOG_USER,
  114.                  "cruadddevice:  overlapping I/O (0x%x)\n", ptr->addr);
  115.             return 0;
  116.         }
  117.         if (tmp) {
  118.             new->next = tmp->next;
  119.             tmp->next = new;
  120.         } else {
  121.             new->next = ptr;
  122.             *head = new;
  123.         }
  124.     } else
  125.         *head = new;
  126.  
  127.     if (log_level(LOG_CRU) >= 2)
  128.         crudevicedump();
  129.  
  130.     return 1;
  131. }
  132.  
  133. int
  134. crudeldevice(int rw, u32 addr, u32 bits, crufunc * handler)
  135. {
  136.     crudevicelist **head, *ptr, *tmp;
  137.  
  138.     if (addr >= 0x2000) {
  139.         logger(_L | LOG_ERROR | LOG_USER, "crudeldevice:  address 0x%x is invalid\n",
  140.              addr);
  141.         return 0;
  142.     }
  143.  
  144.     if (bits > 1) {
  145.         logger(_L | LOG_ERROR | LOG_USER,
  146.              "crudeldevice:  only single-bit ranges supported (0x%04X, %d)\n",
  147.              addr, bits);
  148.         return 0;
  149.     }
  150.  
  151.     if (rw == CRU_READ)
  152.         head = &crureaddevices;
  153.     else if (rw == CRU_WRITE)
  154.         head = &cruwritedevices;
  155.     else {
  156.         logger(_L | LOG_ERROR | LOG_USER,
  157.              "crudeldevice:  invalid 'rw' flag (%d) passed\n", rw);
  158.         return 0;
  159.     }
  160.  
  161.     while (*head) {
  162.         tmp = NULL;
  163.  
  164.         if ((*head)->addr == addr && handler == (*head)->handler) {
  165.             ptr = *head;
  166.             *head = (*head)->next;
  167.             xfree(ptr);
  168.             return 1;
  169.         }
  170.         head = &(*head)->next;
  171.     }
  172.  
  173.     logger(_L | LOG_ERROR | LOG_USER, "crudeldevice:  device not found (0x%x)\n",
  174.          addr);
  175.     return 0;
  176. }
  177.  
  178.  
  179. /***************************************************/
  180.  
  181. void
  182. cruwrite(u32 addr, u32 val, u32 num)
  183. {
  184.     crudevicelist *ptr = cruwritedevices;
  185.  
  186.     addr &= 0x1fff;
  187.     logger(_L | L_2, "CRU write: >%04X[%d], %04X\n", addr, num, val & 0xffff);
  188.  
  189.     if (addr >= 0x30) {
  190.         setclockmode9901(0);
  191.     }
  192.  
  193.     while (ptr && num) {
  194.         if (ptr->addr > addr) {
  195.             /* if we've already passed a handler for addr,
  196.                shift out the lost bits */
  197.             int         lost = (ptr->addr - addr) / 2;
  198.  
  199.             if (lost > num)
  200.                 lost = num;
  201.  
  202.  
  203.             val >>= lost;
  204.             num -= lost;
  205.             addr = ptr->addr;
  206.             logger(_L | L_2, "cruwrite:  skipping bits, range is now %04X[%d]\n", addr,
  207.                  num);
  208.         }
  209.  
  210.         if (addr == ptr->addr && num) {
  211.             int         used;
  212.             u32         mask;
  213.  
  214.             logger(_L | L_2, "cruwrite:  handling %04X[%d] with %04X\n",
  215.                  addr, num, ptr->addr);
  216.  
  217.             used = 1;
  218.             mask = ~(~0 << used);
  219.             (ptr->handler) (addr, val & mask, used);
  220.  
  221.             num -= used;
  222.             addr += used * 2;
  223.             val >>= used;
  224.         }
  225.         ptr = ptr->next;
  226.  
  227.     }
  228. }
  229.  
  230. /*
  231.     Routines write 1.  Shift answer left into output.
  232. */
  233.  
  234. #include "keyboard.h"
  235.  
  236. u32 cruread(u32 addr, u32 num)
  237. {
  238.     crudevicelist *ptr = crureaddevices;
  239.     u32         orgaddr = addr;
  240.     u32         val = 0;
  241.  
  242.     //(num >= 8) ? 0xff00 : 0xffff;
  243.  
  244.     addr &= 0x1fff;
  245.     orgaddr = addr;
  246.     logger(_L | L_2, "CRU read: >%04X[%d] = \n", addr, num);
  247.  
  248.     if (addr >= 0x30) {
  249.         setclockmode9901(0);
  250.     }
  251.  
  252.     while (ptr && num) {
  253.  
  254.         /* if we've already passed a handler for addr,
  255.            shift out the lost bits */
  256.         if (ptr->addr > addr) {
  257.             int         lost = (ptr->addr - addr) / 2;
  258.  
  259.             if (lost > num)
  260.                 lost = num;
  261.  
  262.             num -= lost;
  263.             addr = ptr->addr;
  264.             logger(_L | L_2, "cruread:  skipping bits, range is now %04X[%d]\n", addr,
  265.                  num);
  266.         }
  267.  
  268.         if (addr == ptr->addr && num) {
  269.             int         used;
  270.             u32         mask, bits, shift;
  271.  
  272.             logger(_L | L_2, "cruread:  handling %04X[%d] with %04X\n",
  273.                  addr, num, ptr->addr);
  274.  
  275.             used = 1;
  276.             mask = ~((~0) << used);
  277.             shift = (addr - orgaddr) / 2;
  278.             bits = ((ptr->handler) (addr, val, used) & mask);
  279.             val = (val & ~(mask << shift)) | (bits << shift);
  280.             num -= used;
  281.             addr += used * 2;
  282.         }
  283.         ptr = ptr->next;
  284.  
  285.     }
  286.     if (orgaddr == 0x6 && 0xff != (val & 0xff))
  287.         logger(_L | L_2, "keyrow:  %2X/%04X\n", crukeyboardmap[crukeyboardcol],
  288.              val & 0xffff);
  289.     return val & 0xffff;
  290. }
  291.