2
0

abcio.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. * abcio.c
  3. *
  4. * Handle ABC-bus I/O operations
  5. */
  6. #include "common.h"
  7. #include "io.h"
  8. #include "irq.h"
  9. #include "abcio.h"
  10. #include "console.h"
  11. __sbss struct abc_dev *_abc_selected_dev;
  12. static __bss_hot struct abc_dev *abc_device[65]; /* 65 == post-RST# = always NULL */
  13. static __sdata uint8_t abc_devsel = 64;
  14. #define EVENT_MASK_ALWAYS 0x0082 /* RST# and CS# */
  15. static inline __attribute__((always_inline))
  16. uint16_t event_mask(const struct abc_dev *dev)
  17. {
  18. if (!dev)
  19. return EVENT_MASK_ALWAYS;
  20. return EVENT_MASK_ALWAYS | dev->callback_mask |
  21. (dev->out_cnt ? 1 : 0) | (dev->inp_cnt ? 0x100 : 0);
  22. }
  23. /* Not inlining this makes the code larger...! */
  24. static inline __attribute__((always_inline))
  25. void refresh_dev(struct abc_dev *dev)
  26. {
  27. if (dev == abc_selected_dev()) {
  28. ABC_BUSY_MASK = event_mask(dev);
  29. ABC_INP = dev ? dev->inp_data_w : 0;
  30. }
  31. }
  32. static inline __attribute__((always_inline))
  33. void abc_select(struct abc_dev *dev)
  34. {
  35. _abc_selected_dev = dev;
  36. refresh_dev(dev);
  37. }
  38. IRQHANDLER(abc,0)
  39. {
  40. unsigned int what = ABC_BUSY_STATUS;
  41. struct abc_dev *dev = abc_selected_dev();
  42. if (what & 0xff) {
  43. unsigned int addr = ABC_OUT_ADDR;
  44. unsigned int data = ABC_OUT_DATA;
  45. switch (addr) {
  46. case 0:
  47. if (!dev)
  48. break;
  49. if (dev->out_cnt) {
  50. *dev->out_buf++ = data;
  51. dev->inp_data[1] &= dev->status_first_out_mask;
  52. ABC_INP1_DATA = dev->inp_data[1];
  53. if (--dev->out_cnt)
  54. break; /* No callback, don't set out_data[] */
  55. }
  56. goto handle_out;
  57. case 1:
  58. dev = abc_device[abc_devsel = data & 0x3f];
  59. abc_select(dev);
  60. /* fall through */
  61. case 2 ... 5:
  62. if (!dev)
  63. break;
  64. goto handle_out;
  65. handle_out:
  66. dev->out_data[addr] = data;
  67. if (dev->callback_mask & (1 << addr))
  68. dev->callback_out[addr](dev, data, addr);
  69. break;
  70. case 7: /* Bus reset */
  71. {
  72. struct abc_dev **devp;
  73. uint8_t old_devsel = abc_devsel;
  74. abc_devsel = DEVSEL_NONE;
  75. abc_select(NULL);
  76. /* Broadcast to all interested devices */
  77. devp = &abc_device[0];
  78. while (devp <= &abc_device[63]) {
  79. dev = *devp++;
  80. if (dev && (dev->callback_mask & 0x0080))
  81. dev->callback_rst(dev, old_devsel, 7);
  82. }
  83. dev = NULL;
  84. break;
  85. }
  86. default:
  87. break;
  88. }
  89. }
  90. if (dev) {
  91. if (what & 0x100) {
  92. if (dev->inp_cnt && --dev->inp_cnt) {
  93. dev->inp_data[1] &= dev->status_first_inp_mask;
  94. ABC_INP1_DATA = dev->inp_data[1];
  95. ABC_INP0_DATA = dev->inp_data[0] = *dev->inp_buf++;
  96. /* No callback */
  97. } else {
  98. uint8_t old_data = ABC_INP0_DATA;
  99. ABC_INP0_DATA = dev->inp_data[0] = dev->inp_data_def;
  100. if (dev->callback_mask & 0x100)
  101. dev->callback_inp[0](dev, old_data, 0);
  102. }
  103. }
  104. if (what & 0x200) {
  105. uint8_t old_data = ABC_INP1_DATA;
  106. ABC_INP1_DATA = dev->inp_data[1];
  107. if (dev->callback_mask & 0x200)
  108. dev->callback_inp[1](dev, old_data, 1);
  109. }
  110. }
  111. /* May need to change event_mask here */
  112. ABC_BUSY = what | (event_mask(dev) << 16);
  113. }
  114. void __hot abc_setup_out_queue(struct abc_dev *dev, void *buf, size_t len,
  115. uint8_t status)
  116. {
  117. irqmask_t irqmask = mask_irq(ABC_IRQ);
  118. dev->out_buf = buf;
  119. dev->out_cnt = len;
  120. dev->inp_data[1] = status;
  121. refresh_dev(dev); /* Update registers as needed */
  122. restore_irq(irqmask, ABC_IRQ);
  123. }
  124. void __hot abc_setup_inp_queue(struct abc_dev *dev, const void *buf, size_t len,
  125. uint8_t status)
  126. {
  127. irqmask_t irqmask = mask_irq(ABC_IRQ);
  128. dev->inp_buf = buf;
  129. dev->inp_cnt = len;
  130. dev->inp_data[0] = *dev->inp_buf++;
  131. dev->inp_data[1] = status;
  132. refresh_dev(dev); /* Update registers as needed */
  133. restore_irq(irqmask, ABC_IRQ);
  134. }
  135. void __hot abc_set_inp_default(struct abc_dev *dev, uint8_t val)
  136. {
  137. irqmask_t irqmask = mask_irq(ABC_IRQ);
  138. dev->inp_data_def = val;
  139. if (!dev->inp_cnt) {
  140. dev->inp_data[0] = val;
  141. if (dev == abc_selected_dev())
  142. ABC_INP0_DATA = val;
  143. }
  144. restore_irq(irqmask, ABC_IRQ);
  145. }
  146. void __hot abc_set_inp_status(struct abc_dev *dev, uint8_t val)
  147. {
  148. irqmask_t irqmask = mask_irq(ABC_IRQ);
  149. dev->inp_data[1] = val;
  150. if (dev == abc_selected_dev())
  151. ABC_INP1_DATA = val;
  152. restore_irq(irqmask, ABC_IRQ);
  153. }
  154. /*
  155. * This can be called before or after abc_init()!
  156. */
  157. void abc_register(struct abc_dev *dev, unsigned int devsel)
  158. {
  159. if (devsel >= DEVSEL_NONE)
  160. devsel = DEVSEL_NONE;
  161. irqmask_t irqmask = mask_irq(ABC_IRQ);
  162. unsigned int old_devsel = DEVSEL_NONE;
  163. struct abc_dev *old_dev = NULL;
  164. if (dev) {
  165. if (dev->devsel < DEVSEL_NONE && abc_device[dev->devsel] == dev) {
  166. old_devsel = dev->devsel;
  167. if (old_devsel == devsel)
  168. goto done; /* Already registered at this address */
  169. abc_device[old_devsel] = NULL;
  170. if (old_devsel == abc_devsel)
  171. abc_select(NULL);
  172. }
  173. dev->devsel = devsel;
  174. if (!dev->inp_cnt)
  175. dev->inp_data[0] = dev->inp_data_def;
  176. }
  177. if (devsel < DEVSEL_NONE) {
  178. old_dev = abc_device[devsel];
  179. if (old_dev)
  180. old_dev->devsel = DEVSEL_NONE;
  181. abc_device[devsel] = dev;
  182. if (devsel == abc_devsel)
  183. abc_select(dev);
  184. }
  185. done:
  186. restore_irq(irqmask, ABC_IRQ);
  187. if (dev) {
  188. if (old_dev) {
  189. con_printf("abcio: Unregistered device %s from devsel %u\n",
  190. old_dev->name, devsel);
  191. }
  192. if (old_devsel < DEVSEL_NONE) {
  193. if (devsel == old_devsel) {
  194. /* Print nothing */
  195. } else if (devsel < DEVSEL_NONE) {
  196. con_printf("abcio: Moved device %s from devsel %u to %u\n",
  197. dev->name, old_devsel, devsel);
  198. } else {
  199. con_printf("abcio: Unregistered device %s from devsel %u\n",
  200. dev->name, old_devsel);
  201. }
  202. } else {
  203. if (devsel < DEVSEL_NONE) {
  204. con_printf("abcio: Registered device %s on devsel %u\n",
  205. dev->name, devsel);
  206. } else {
  207. con_printf("abcio: Device %s is disabled\n", dev->name);
  208. }
  209. }
  210. }
  211. }
  212. void abc_init(void)
  213. {
  214. unsigned int devsel;
  215. mask_irq(ABC_IRQ);
  216. devsel = ABC_IOSEL;
  217. abc_devsel = (devsel & 0x100) ? DEVSEL_NONE : (devsel & 63);
  218. abc_select(abc_device[abc_devsel]);
  219. unmask_irq(ABC_IRQ); /* Start ABC bus unconditionally */
  220. }