scsi_accel_sync.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* Synchronous mode SCSI implementation.
  2. *
  3. * In synchronous mode, the handshake mechanism is not used. Instead
  4. * either end of the communication will just send a bunch of bytes
  5. * and only afterwards checks that the number of acknowledgement
  6. * pulses matches.
  7. *
  8. * The receiving end should latch in the data at the falling edge of
  9. * the request pulse (on either REQ or ACK pin). We use the GD32 EXMC
  10. * peripheral to implement this latching with the NWAIT pin when
  11. * reading data from the host. NOE is used to generate the REQ pulses.
  12. *
  13. * Writing data to the host is simpler, as we can just write it out
  14. * from the GPIO port at our own pace. A timer is used for generating
  15. * the output pulses on REQ pin.
  16. */
  17. #include "scsi_accel_sync.h"
  18. #include <AzulSCSI_log.h>
  19. #include <gd32f20x_exmc.h>
  20. #ifndef SCSI_SYNC_MODE_AVAILABLE
  21. void scsi_accel_sync_init() {}
  22. void scsi_accel_sync_read(uint8_t *data, uint32_t count, int* parityError, volatile int *resetFlag) {}
  23. void scsi_accel_sync_startWrite(const uint8_t* data, uint32_t count, volatile int *resetFlag) {}
  24. void scsi_accel_sync_stopWrite() {}
  25. void scsi_accel_sync_finishWrite(volatile int *resetFlag) {}
  26. bool scsi_accel_sync_isWriteFinished(const uint8_t* data) { return true; }
  27. #else
  28. void scsi_accel_sync_init()
  29. {
  30. rcu_periph_clock_enable(RCU_EXMC);
  31. rcu_periph_clock_enable(SCSI_TIMER_RCU);
  32. exmc_norsram_timing_parameter_struct timing_param = {
  33. .asyn_access_mode = EXMC_ACCESS_MODE_A,
  34. .syn_data_latency = EXMC_DATALAT_2_CLK,
  35. .syn_clk_division = EXMC_SYN_CLOCK_RATIO_2_CLK,
  36. .bus_latency = 1,
  37. .asyn_data_setuptime = 2,
  38. .asyn_address_holdtime = 2,
  39. .asyn_address_setuptime = 1
  40. };
  41. exmc_norsram_parameter_struct sram_param = {
  42. .norsram_region = EXMC_BANK0_NORSRAM_REGION0,
  43. .write_mode = EXMC_ASYN_WRITE,
  44. .extended_mode = DISABLE,
  45. .asyn_wait = ENABLE,
  46. .nwait_signal = ENABLE,
  47. .memory_write = DISABLE,
  48. .nwait_config = EXMC_NWAIT_CONFIG_DURING,
  49. .wrap_burst_mode = DISABLE,
  50. .nwait_polarity = EXMC_NWAIT_POLARITY_HIGH,
  51. .burst_mode = DISABLE,
  52. .databus_width = EXMC_NOR_DATABUS_WIDTH_16B,
  53. .memory_type = EXMC_MEMORY_TYPE_SRAM,
  54. .address_data_mux = DISABLE,
  55. .read_write_timing = &timing_param
  56. };
  57. exmc_norsram_init(&sram_param);
  58. gpio_init(SCSI_IN_ACK_EXMC_NWAIT_PORT, GPIO_MODE_IN_FLOATING, 0, SCSI_IN_ACK_EXMC_NWAIT_PIN);
  59. }
  60. void scsi_accel_sync_read(uint8_t *data, uint32_t count, int* parityError, volatile int *resetFlag)
  61. {
  62. exmc_norsram_enable(EXMC_BANK0_NORSRAM_REGION0);
  63. gpio_init(SCSI_OUT_REQ_EXMC_NOE_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SCSI_OUT_REQ_EXMC_NOE_PIN);
  64. for (int i = 0; i < count; i++)
  65. {
  66. uint32_t value = *(volatile uint32_t*)EXMC_NOR_PSRAM;
  67. data[i] = ~(value >> SCSI_EXMC_DATA_SHIFT) & 0xFF;
  68. }
  69. gpio_init(SCSI_OUT_REQ_EXMC_NOE_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SCSI_OUT_REQ_EXMC_NOE_PIN);
  70. exmc_norsram_disable(EXMC_BANK0_NORSRAM_REGION0);
  71. }
  72. void scsi_accel_sync_startWrite(const uint8_t* data, uint32_t count, volatile int *resetFlag)
  73. {
  74. for (int i = 0; i < count; i++)
  75. {
  76. SCSI_OUT_DATA(data[i]);
  77. delay_100ns();
  78. SCSI_OUT(REQ, 1);
  79. delay_ns(200);
  80. SCSI_OUT(REQ, 0);
  81. delay_ns(500);
  82. }
  83. SCSI_RELEASE_DATA_REQ();
  84. }
  85. void scsi_accel_sync_stopWrite()
  86. {
  87. }
  88. void scsi_accel_sync_finishWrite(volatile int *resetFlag)
  89. {
  90. }
  91. bool scsi_accel_sync_isWriteFinished(const uint8_t* data)
  92. {
  93. return true;
  94. }
  95. #endif