2
0

abcio.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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. __sbss struct abc_dev *_abc_selected_dev;
  11. static __bss_hot struct abc_dev *abc_device[65]; /* 65 == post-RST# = always NULL */
  12. static __sdata uint8_t abc_devsel = 64;
  13. #define EVENT_MASK_ALWAYS 0x0082 /* RST# and CS# */
  14. static inline __attribute__((always_inline))
  15. uint16_t event_mask(const struct abc_dev *dev)
  16. {
  17. if (!dev)
  18. return EVENT_MASK_ALWAYS;
  19. return EVENT_MASK_ALWAYS | dev->callback_mask |
  20. (dev->out_cnt ? 1 : 0) | (dev->inp_cnt ? 0x100 : 0);
  21. }
  22. /* Not inlining this makes the code larger...! */
  23. static inline __attribute__((always_inline))
  24. void refresh_dev(struct abc_dev *dev)
  25. {
  26. if (dev == abc_selected_dev()) {
  27. ABC_BUSY_MASK = event_mask(dev);
  28. ABC_INP = dev ? dev->inp_data_w : 0;
  29. }
  30. }
  31. static inline __attribute__((always_inline))
  32. void abc_select(struct abc_dev *dev)
  33. {
  34. _abc_selected_dev = dev;
  35. refresh_dev(dev);
  36. }
  37. IRQHANDLER(abc,0)
  38. {
  39. unsigned int what = ABC_BUSY_STATUS;
  40. struct abc_dev *dev = abc_selected_dev();
  41. if (what & 0xff) {
  42. unsigned int addr = ABC_OUT_ADDR;
  43. unsigned int data = ABC_OUT_DATA;
  44. switch (addr) {
  45. case 0:
  46. if (!dev)
  47. break;
  48. if (dev->out_cnt) {
  49. *dev->out_buf++ = data;
  50. dev->inp_data[1] &= dev->status_first_out_mask;
  51. ABC_INP1_DATA = dev->inp_data[1];
  52. if (--dev->out_cnt)
  53. break; /* No callback, don't set out_data[] */
  54. }
  55. goto handle_out;
  56. case 1:
  57. dev = abc_device[abc_devsel = data & 0x3f];
  58. abc_select(dev);
  59. /* fall through */
  60. case 2 ... 5:
  61. if (!dev)
  62. break;
  63. goto handle_out;
  64. handle_out:
  65. dev->out_data[addr] = data;
  66. if (dev->callback_mask & (1 << addr))
  67. dev->callback_out[addr](dev, data, addr);
  68. break;
  69. case 7: /* Bus reset */
  70. {
  71. struct abc_dev **devp;
  72. uint8_t old_devsel = abc_devsel;
  73. abc_devsel = DEVSEL_NONE;
  74. abc_select(NULL);
  75. /* Broadcast to all interested devices */
  76. devp = &abc_device[0];
  77. while (devp <= &abc_device[63]) {
  78. dev = *devp++;
  79. if (dev && (dev->callback_mask & 0x0080))
  80. dev->callback_rst(dev, old_devsel, 7);
  81. }
  82. dev = NULL;
  83. break;
  84. }
  85. default:
  86. break;
  87. }
  88. }
  89. if (dev) {
  90. if (what & 0x100) {
  91. if (dev->inp_cnt && --dev->inp_cnt) {
  92. dev->inp_data[1] &= dev->status_first_inp_mask;
  93. ABC_INP1_DATA = dev->inp_data[1];
  94. ABC_INP0_DATA = dev->inp_data[0] = *dev->inp_buf++;
  95. /* No callback */
  96. } else {
  97. uint8_t old_data = ABC_INP0_DATA;
  98. ABC_INP0_DATA = dev->inp_data[0] = dev->inp_data_def;
  99. if (dev->callback_mask & 0x100)
  100. dev->callback_inp[0](dev, old_data, 0);
  101. }
  102. }
  103. if (what & 0x200) {
  104. uint8_t old_data = ABC_INP1_DATA;
  105. ABC_INP1_DATA = dev->inp_data[1];
  106. if (dev->callback_mask & 0x200)
  107. dev->callback_inp[1](dev, old_data, 1);
  108. }
  109. }
  110. /* May need to change event_mask here */
  111. ABC_BUSY = what | (event_mask(dev) << 16);
  112. }
  113. void __hot abc_setup_out_queue(struct abc_dev *dev, void *buf, size_t len,
  114. uint8_t status)
  115. {
  116. irqmask_t irqmask = mask_irq(ABC_IRQ);
  117. dev->out_buf = buf;
  118. dev->out_cnt = len;
  119. dev->inp_data[1] = status;
  120. refresh_dev(dev); /* Update registers as needed */
  121. restore_irq(irqmask, ABC_IRQ);
  122. }
  123. void __hot abc_setup_inp_queue(struct abc_dev *dev, const void *buf, size_t len,
  124. uint8_t status)
  125. {
  126. irqmask_t irqmask = mask_irq(ABC_IRQ);
  127. dev->inp_buf = buf;
  128. dev->inp_cnt = len;
  129. dev->inp_data[0] = *dev->inp_buf++;
  130. dev->inp_data[1] = status;
  131. refresh_dev(dev); /* Update registers as needed */
  132. restore_irq(irqmask, ABC_IRQ);
  133. }
  134. void __hot abc_set_inp_default(struct abc_dev *dev, uint8_t val)
  135. {
  136. irqmask_t irqmask = mask_irq(ABC_IRQ);
  137. dev->inp_data_def = val;
  138. if (!dev->inp_cnt) {
  139. dev->inp_data[0] = val;
  140. if (dev == abc_selected_dev())
  141. ABC_INP0_DATA = val;
  142. }
  143. restore_irq(irqmask, ABC_IRQ);
  144. }
  145. void __hot abc_set_inp_status(struct abc_dev *dev, uint8_t val)
  146. {
  147. irqmask_t irqmask = mask_irq(ABC_IRQ);
  148. dev->inp_data[1] = val;
  149. if (dev == abc_selected_dev())
  150. ABC_INP1_DATA = val;
  151. restore_irq(irqmask, ABC_IRQ);
  152. }
  153. /*
  154. * This can be called before or after abc_init()!
  155. */
  156. void abc_register(struct abc_dev *dev, unsigned int devsel)
  157. {
  158. if (devsel > 63)
  159. return;
  160. irqmask_t irqmask = mask_irq(ABC_IRQ);
  161. if (!dev->inp_cnt)
  162. dev->inp_data[0] = dev->inp_data_def;
  163. abc_device[devsel] = dev;
  164. if (devsel == abc_devsel)
  165. abc_select(dev);
  166. restore_irq(irqmask, ABC_IRQ);
  167. }
  168. void abc_init(void)
  169. {
  170. unsigned int devsel;
  171. mask_irq(ABC_IRQ);
  172. devsel = ABC_IOSEL;
  173. abc_devsel = (devsel & 0x100) ? DEVSEL_NONE : (devsel & 63);
  174. abc_select(abc_device[abc_devsel]);
  175. unmask_irq(ABC_IRQ); /* Start ABC bus unconditionally */
  176. }