2
0

abcpun80.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /*
  2. * abcpun80.c
  3. *
  4. * Emulate a PUN80 network card
  5. */
  6. #include "compiler.h"
  7. #include "fw.h"
  8. #include "io.h"
  9. #include "abcio.h"
  10. #define PUN_IOSEL 60
  11. #define PUN_TTY_CHAN 1
  12. #if PUN_TTY_CHAN >= TTY_CHANNELS
  13. # error "PUN_TTY_CHAN out of range"
  14. #endif
  15. #define PUN_DATA TTY_DATA(PUN_TTY_CHAN)
  16. #define PUN_WATERCTL TTY_WATERCTL(PUN_TTY_CHAN)
  17. #define PUN_STATUS TTY_STATUS(PUN_TTY_CHAN)
  18. #define PUN_IRQEN TTY_IRQEN(PUN_TTY_CHAN)
  19. #define PUN_IRQPOL TTY_IRQPOL(PUN_TTY_CHAN)
  20. #define PUN_IRQ TTY_NIRQ(PUN_TTY_CHAN)
  21. #define PUN_IRQ_MASK (TTY_STATUS_TX_FULL|TTY_STATUS_RX_EMPTY|\
  22. TTY_STATUS_DTR_IN)
  23. static struct abc_dev pun80_iodev;
  24. /*
  25. * Convert to FT232H-compatible status codes, and advance
  26. * the receive FIFO if applicable.
  27. */
  28. static __hot void
  29. pun80_refresh_input(struct abc_dev *dev, bool advance)
  30. {
  31. static bool data_loaded;
  32. unsigned int status;
  33. uint8_t pun80_status;
  34. status = PUN_STATUS;
  35. if (!data_loaded || advance) {
  36. data_loaded = !(status & TTY_STATUS_RX_EMPTY);
  37. if (data_loaded) {
  38. dev->inp_data_def = dev->inp_data[0] = PUN_DATA;
  39. status = PUN_STATUS;
  40. }
  41. }
  42. PUN_IRQPOL = status;
  43. pun80_status = ~15 | data_loaded;
  44. if (status & TTY_STATUS_DTR_IN)
  45. pun80_status |= 8;
  46. if (!(status & TTY_STATUS_TX_FULL))
  47. pun80_status |= 2;
  48. dev->inp_data[1] = pun80_status;
  49. if (abc_selected_dev() == dev)
  50. ABC_INP = dev->inp_data_w;
  51. }
  52. static ABC_CALLBACK(pun80_callback_out)
  53. {
  54. PUN_DATA = data;
  55. pun80_refresh_input(dev, false);
  56. }
  57. static ABC_CALLBACK(pun80_callback_inp)
  58. {
  59. pun80_refresh_input(dev, true);
  60. }
  61. IRQHANDLER(tty,PUN_TTY_CHAN)
  62. {
  63. CON_DATA = '#';
  64. pun80_refresh_input(&pun80_iodev, false);
  65. }
  66. /* The "flush" command in FT232H (C1#) is not needed with our USB stack */
  67. static struct abc_dev pun80_iodev = {
  68. .callback_mask = (1 << 0)|(1 << 8),
  69. .inp_en = 3,
  70. .inp_data[1] = 0xf0,
  71. .status_first_out_mask = ~0,
  72. .status_first_inp_mask = ~0,
  73. .callback_out[0] = pun80_callback_out,
  74. .callback_inp[0] = pun80_callback_inp
  75. };
  76. void pun80_init(void)
  77. {
  78. mask_irq(PUN_IRQ);
  79. /*
  80. * Immediately interrupt on:
  81. *
  82. * USB configured
  83. * TX full
  84. * RX not empty
  85. */
  86. PUN_IRQPOL = TTY_STATUS_RX_EMPTY;
  87. PUN_IRQEN = PUN_IRQ_MASK;
  88. unmask_irq(PUN_IRQ);
  89. abc_register(&pun80_iodev, PUN_IOSEL);
  90. }