abcio.c 3.5 KB

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