scsi_accel_asm.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #include "scsi_accel_asm.h"
  2. #include "AzulSCSI_platform.h"
  3. // Optimized ASM blocks for the SCSI communication subroutine
  4. // Take 8 bits from d and format them for writing
  5. // d is name of data operand, b is bit offset, x is unique label
  6. #define ASM_LOAD_DATA(d, b, x) \
  7. " load_data1_" x "_%=: \n" \
  8. " ubfx %[tmp1], %[" d "], #" b ", #8 \n" \
  9. " ldr %[tmp1], [%[byte_lookup], %[tmp1], lsl #2] \n"
  10. // Write data to SCSI port and set REQ high
  11. #define ASM_SEND_DATA(x) \
  12. " send_data" x "_%=: \n" \
  13. " str %[tmp1], [%[out_port_bop]] \n"
  14. // Wait for ACK to be high, set REQ low, wait ACK low
  15. #define ASM_HANDSHAKE(x) \
  16. " ldr %[tmp2], [%[ack_pin_bb]] \n" \
  17. " str %[tmp2], [%[req_pin_bb]] \n" \
  18. " cbnz %[tmp2], req_is_low_now" x "_%= \n" \
  19. " ldr %[tmp2], [%[ack_pin_bb]] \n" \
  20. " str %[tmp2], [%[req_pin_bb]] \n" \
  21. " cbnz %[tmp2], req_is_low_now" x "_%= \n" \
  22. " ldr %[tmp2], [%[ack_pin_bb]] \n" \
  23. " str %[tmp2], [%[req_pin_bb]] \n" \
  24. " cbnz %[tmp2], req_is_low_now" x "_%= \n" \
  25. " wait_ack_inactive" x "_%=: \n" \
  26. " ldr %[tmp2], [%[ack_pin_bb]] \n" \
  27. " str %[tmp2], [%[req_pin_bb]] \n" \
  28. " cbnz %[tmp2], req_is_low_now" x "_%= \n" \
  29. " ldr %[tmp2], [%[reset_flag]] \n" \
  30. " cbnz %[tmp2], req_is_low_now" x "_%= \n" \
  31. " b.n wait_ack_inactive" x "_%= \n" \
  32. " req_is_low_now" x "_%=: \n" \
  33. " ldr %[tmp2], [%[ack_pin_bb]] \n" \
  34. " cbz %[tmp2], over_ack_active" x "_%= \n" \
  35. " ldr %[tmp2], [%[ack_pin_bb]] \n" \
  36. " cbz %[tmp2], over_ack_active" x "_%= \n" \
  37. " ldr %[tmp2], [%[ack_pin_bb]] \n" \
  38. " cbz %[tmp2], over_ack_active" x "_%= \n" \
  39. " ldr %[tmp2], [%[ack_pin_bb]] \n" \
  40. " cbz %[tmp2], over_ack_active" x "_%= \n" \
  41. " wait_ack_active" x "_%=: \n" \
  42. " ldr %[tmp2], [%[ack_pin_bb]] \n" \
  43. " cbz %[tmp2], over_ack_active" x "_%= \n" \
  44. " ldr %[tmp2], [%[reset_flag]] \n" \
  45. " cbnz %[tmp2], over_ack_active" x "_%= \n" \
  46. " b.n wait_ack_active" x "_%= \n" \
  47. " over_ack_active" x "_%=: \n" \
  48. // Send bytes to SCSI bus using the asynchronous handshake mechanism
  49. // Takes 4 bytes at a time for sending from buf.
  50. // Returns the next buffer pointer.
  51. void scsi_accel_asm_send(const uint32_t *buf, uint32_t num_words, volatile int *resetFlag)
  52. {
  53. volatile uint32_t *out_port_bop = (volatile uint32_t*)&GPIO_BOP(SCSI_OUT_PORT);
  54. const uint32_t *byte_lookup = g_scsi_out_byte_to_bop;
  55. uint32_t ack_pin_bb = PERIPH_BB_BASE + (((uint32_t)&GPIO_ISTAT(SCSI_ACK_PORT)) - APB1_BUS_BASE) * 32 + 12 * 4;
  56. uint32_t req_pin_bb = PERIPH_BB_BASE + (((uint32_t)out_port_bop) - APB1_BUS_BASE) * 32 + (9 + 16) * 4;
  57. register uint32_t tmp1 = 0;
  58. register uint32_t tmp2 = 0;
  59. register uint32_t data = 0;
  60. asm volatile (
  61. " ldr %[data], [%[buf]], #4 \n" \
  62. ASM_LOAD_DATA("data", "0", "first")
  63. "inner_loop_%=: \n" \
  64. ASM_SEND_DATA("0")
  65. ASM_LOAD_DATA("data", "8", "8")
  66. ASM_HANDSHAKE("0")
  67. ASM_SEND_DATA("8")
  68. ASM_LOAD_DATA("data", "16", "16")
  69. ASM_HANDSHAKE("8")
  70. ASM_SEND_DATA("16")
  71. ASM_LOAD_DATA("data", "24", "24")
  72. ASM_HANDSHAKE("16")
  73. ASM_SEND_DATA("24")
  74. " ldr %[data], [%[buf]], #4 \n" \
  75. ASM_LOAD_DATA("data", "0", "0")
  76. ASM_HANDSHAKE("24")
  77. " subs %[num_words], %[num_words], #1 \n" \
  78. " bne inner_loop_%= \n"
  79. : /* Output */ [tmp1] "+l" (tmp1), [tmp2] "+l" (tmp2), [data] "+r" (data),
  80. [buf] "+r" (buf), [num_words] "+r" (num_words)
  81. : /* Input */ [ack_pin_bb] "r" (ack_pin_bb),
  82. [req_pin_bb] "r" (req_pin_bb),
  83. [out_port_bop] "r"(out_port_bop),
  84. [byte_lookup] "r" (byte_lookup),
  85. [reset_flag] "r" (resetFlag)
  86. : /* Clobber */ );
  87. SCSI_RELEASE_DATA_REQ();
  88. }