abcio.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. ABC_BUSY_STATUS = what;
  85. }
  86. void abc_setup_out_queue(struct abc_dev *dev, void *buf, size_t len,
  87. uint8_t status)
  88. {
  89. mask_irq(ABC_IRQ);
  90. dev->out_buf = buf;
  91. dev->out_cnt = len;
  92. dev->inp_data[1] = status;
  93. dev->callback_mask |= (1 << 0);
  94. abc_select(selected_dev);
  95. unmask_irq(ABC_IRQ);
  96. }
  97. void abc_setup_inp_queue(struct abc_dev *dev, const void *buf, size_t len,
  98. uint8_t status)
  99. {
  100. mask_irq(ABC_IRQ);
  101. dev->inp_buf = buf;
  102. dev->inp_cnt = len;
  103. dev->inp_data[0] = *dev->inp_buf++;
  104. dev->inp_data[1] = status;
  105. dev->callback_mask |= (1 << 8);
  106. abc_select(selected_dev);
  107. unmask_irq(ABC_IRQ);
  108. }
  109. void abc_set_inp_default(struct abc_dev *dev, uint8_t val)
  110. {
  111. mask_irq(ABC_IRQ);
  112. dev->inp_data_def = val;
  113. if (!dev->inp_cnt) {
  114. dev->inp_data[0] = val;
  115. if (dev == selected_dev)
  116. ABC_INP0_DATA = val;
  117. }
  118. unmask_irq(ABC_IRQ);
  119. }
  120. void abc_set_inp_status(struct abc_dev *dev, uint8_t val)
  121. {
  122. mask_irq(ABC_IRQ);
  123. dev->inp_data[1] = val;
  124. if (dev == selected_dev)
  125. ABC_INP1_DATA = val;
  126. unmask_irq(ABC_IRQ);
  127. }
  128. void abc_register(struct abc_dev *dev, unsigned int devsel)
  129. {
  130. if (devsel > 63)
  131. return;
  132. mask_irq(ABC_IRQ);
  133. abc_device[devsel] = dev;
  134. if (devsel == abc_devsel)
  135. abc_select(dev);
  136. unmask_irq(ABC_IRQ);
  137. }
  138. void abc_init(void)
  139. {
  140. unsigned int devsel;
  141. mask_irq(ABC_IRQ);
  142. devsel = ABC_IOSEL;
  143. abc_devsel = (devsel & 0x100) ? -1U : devsel & 0x3f;
  144. abc_select(NULL);
  145. unmask_irq(ABC_IRQ);
  146. }