abcio.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * abcio.c
  3. *
  4. * Handle ABC-bus I/O operations
  5. */
  6. #include "fw.h"
  7. #include "io.h"
  8. #include "irq.h"
  9. #include "abcio.h"
  10. static struct abc_dev *abc_device[64];
  11. static struct abc_dev *selected_dev;
  12. static uint8_t abc_devsel = -1;
  13. /* Not inlining this makes the code larger...! */
  14. static inline __attribute__((always_inline))
  15. void abc_select(struct abc_dev *dev)
  16. {
  17. selected_dev = dev;
  18. if (!dev) {
  19. ABC_BUSY_MASK = 0x0082; /* Only RST# and CS# */
  20. ABC_INP = 0;
  21. } else {
  22. ABC_BUSY_MASK = dev->callback_mask | 0x0082;
  23. ABC_INP = dev->inp_data_w | (3 << 16);
  24. }
  25. }
  26. IRQHANDLER(abc)
  27. {
  28. unsigned int what = ABC_BUSY_STATUS;
  29. unsigned int callback =
  30. selected_dev ? (what & selected_dev->callback_mask) : 0;
  31. struct abc_dev *dev = selected_dev;
  32. if (what & 0xff) {
  33. unsigned int addr = ABC_OUT_ADDR;
  34. unsigned int data = ABC_OUT_DATA;
  35. switch (addr) {
  36. case 0:
  37. dev->out_data[addr] = data;
  38. if (dev->out_cnt--) {
  39. *dev->out_buf++ = data;
  40. dev->inp_data[1] &= dev->status_first_out_mask;
  41. ABC_INP1_DATA = dev->inp_data[1];
  42. if (dev->out_cnt)
  43. break; /* No callback */
  44. }
  45. if (callback & 1)
  46. dev->callback_out(dev, data);
  47. break;
  48. case 2 ... 5:
  49. dev->out_data[addr] = data;
  50. if (callback & (1 << addr))
  51. dev->callback_cmd(dev, data, addr);
  52. break;
  53. case 1:
  54. dev = abc_device[abc_devsel = data & 0x3f];
  55. abc_select(dev);
  56. if (dev)
  57. dev->out_data[addr] = data;
  58. break;
  59. case 7:
  60. /* XXX: broadcast reset to devices? */
  61. abc_devsel = -1;
  62. abc_select(NULL);
  63. break;
  64. default:
  65. break;
  66. }
  67. }
  68. if (what & 0x100) {
  69. if (--dev->inp_cnt) {
  70. dev->inp_data[1] &= dev->status_first_inp_mask;
  71. ABC_INP1_DATA = dev->inp_data[1];
  72. ABC_INP0_DATA = dev->inp_data[0] = *dev->inp_buf++;
  73. } else {
  74. ABC_INP0_DATA = dev->inp_data[0] = dev->inp_data_def;
  75. if (callback & 0x100)
  76. dev->callback_inp(dev);
  77. }
  78. }
  79. if (what & 0x200) {
  80. ABC_INP1_DATA = dev->inp_data[1];
  81. if (callback & 0x200)
  82. dev->callback_status(dev);
  83. }
  84. /* callback_mask might have changed */
  85. ABC_BUSY = what | ((dev->callback_mask | 0x0082) << 16);
  86. }
  87. void abc_setup_out_queue(struct abc_dev *dev, void *buf, size_t len,
  88. uint8_t status)
  89. {
  90. mask_irq(ABC_IRQ);
  91. dev->out_buf = buf;
  92. dev->out_cnt = len;
  93. dev->inp_data[1] = status;
  94. dev->callback_mask |= (1 << 0);
  95. if (selected_dev == dev)
  96. abc_select(dev); /* Update registers */
  97. unmask_irq(ABC_IRQ);
  98. }
  99. void abc_setup_inp_queue(struct abc_dev *dev, const void *buf, size_t len,
  100. uint8_t status)
  101. {
  102. mask_irq(ABC_IRQ);
  103. dev->inp_buf = buf;
  104. dev->inp_cnt = len;
  105. dev->inp_data[0] = *dev->inp_buf++;
  106. dev->inp_data[1] = status;
  107. dev->callback_mask |= (1 << 8);
  108. if (selected_dev == dev)
  109. abc_select(dev); /* Update registers */
  110. unmask_irq(ABC_IRQ);
  111. }
  112. void abc_set_inp_default(struct abc_dev *dev, uint8_t val)
  113. {
  114. mask_irq(ABC_IRQ);
  115. dev->inp_data_def = val;
  116. if (!dev->inp_cnt) {
  117. dev->inp_data[0] = val;
  118. if (dev == selected_dev)
  119. ABC_INP0_DATA = val;
  120. }
  121. unmask_irq(ABC_IRQ);
  122. }
  123. void abc_set_inp_status(struct abc_dev *dev, uint8_t val)
  124. {
  125. mask_irq(ABC_IRQ);
  126. dev->inp_data[1] = val;
  127. if (dev == selected_dev)
  128. ABC_INP1_DATA = val;
  129. unmask_irq(ABC_IRQ);
  130. }
  131. void abc_register(struct abc_dev *dev, unsigned int devsel)
  132. {
  133. if (devsel > 63)
  134. return;
  135. mask_irq(ABC_IRQ);
  136. abc_device[devsel] = dev;
  137. if (devsel == abc_devsel)
  138. abc_select(dev);
  139. unmask_irq(ABC_IRQ);
  140. }
  141. void abc_init(void)
  142. {
  143. unsigned int devsel;
  144. mask_irq(ABC_IRQ);
  145. devsel = ABC_IOSEL;
  146. abc_devsel = (devsel & 0x100) ? -1U : devsel & 0x3f;
  147. abc_select(NULL);
  148. unmask_irq(ABC_IRQ);
  149. }