Advertisement
Guest User

new aha1540.c

a guest
May 30th, 2016
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.43 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <assert.h>
  4. #include "ibm.h"
  5. #include "device.h"
  6.  
  7. #include "io.h"
  8. #include "mem.h"
  9. #include "rom.h"
  10.  
  11. #include "aha1540.h"
  12. #include "pic.h"
  13. #include "dma.h"
  14. #include "scsi.h"
  15. #include "timer.h"
  16. #include "sg.h"
  17.  
  18. #define elements(a) (sizeof(a) / sizeof(a[0]))
  19.  
  20. #define ADDR_TO_U32(x) (((x[0]) << 16) | ((x[1]) << 8) | (x[2]))
  21. #define U32_TO_ADDR(a, x) do {(a[0]) = (x) >> 16; (a[1]) = (x) >> 8; (a[2]) = (x);} while(0)
  22.  
  23. ///////////////////////////////////////////////////////////////////////////////
  24. //
  25. // CCB - Adaptec SCSI Command Control Block
  26. //
  27. // The CCB is a superset of the CDB (Command Descriptor Block)
  28. // and specifies detailed information about a SCSI command.
  29. //
  30. ///////////////////////////////////////////////////////////////////////////////
  31.  
  32. //
  33. // Byte 0 Command Control Block Operation Code
  34. //
  35.  
  36. #define SCSI_INITIATOR_OLD_COMMAND 0x00
  37. #define TARGET_MODE_COMMAND 0x01
  38. #define SCATTER_GATHER_OLD_COMMAND 0x02
  39. #define SCSI_INITIATOR_COMMAND 0x03
  40. #define SCATTER_GATHER_COMMAND 0x04
  41.  
  42. //
  43. // Byte 1 Address and Direction Control
  44. //
  45.  
  46. #define CCB_TARGET_ID_SHIFT 0x06 // CCB Op Code = 00, 02
  47. #define CCB_INITIATOR_ID_SHIFT 0x06 // CCB Op Code = 01
  48. #define CCB_DATA_XFER_NONE 3 // No Data
  49. #define CCB_DATA_XFER_OUT 2 // Write
  50. #define CCB_DATA_XFER_IN 1 // Read
  51. #define CCB_LUN_MASK 0x07 // Logical Unit Number
  52.  
  53. //
  54. // Byte 2 SCSI_Command_Length - Length of SCSI CDB
  55. //
  56. // Byte 3 Request Sense Allocation Length
  57. //
  58.  
  59. #define FOURTEEN_BYTES 0x00 // Request Sense Buffer size
  60. #define NO_AUTO_REQUEST_SENSE 0x01 // No Request Sense Buffer
  61.  
  62. //
  63. // Bytes 4, 5 and 6 Data Length // Data transfer byte count
  64. //
  65. // Bytes 7, 8 and 9 Data Pointer // SGD List or Data Buffer
  66. //
  67. // Bytes 10, 11 and 12 Link Pointer // Next CCB in Linked List
  68. //
  69. // Byte 13 Command Link ID // TBD (I don't know yet)
  70. //
  71. // Byte 14 Host Status // Host Adapter status
  72. //
  73.  
  74. #define CCB_COMPLETE 0x00 // CCB completed without error
  75. #define CCB_LINKED_COMPLETE 0x0A // Linked command completed
  76. #define CCB_LINKED_COMPLETE_INT 0x0B // Linked complete with interrupt
  77. #define CCB_SELECTION_TIMEOUT 0x11 // Set SCSI selection timed out
  78. #define CCB_DATA_OVER_UNDER_RUN 0x12
  79. #define CCB_UNEXPECTED_BUS_FREE 0x13 // Target dropped SCSI BSY
  80. #define CCB_PHASE_SEQUENCE_FAIL 0x14 // Target bus phase sequence failure
  81. #define CCB_BAD_MBO_COMMAND 0x15 // MBO command not 0, 1 or 2
  82. #define CCB_INVALID_OP_CODE 0x16 // CCB invalid operation code
  83. #define CCB_BAD_LINKED_LUN 0x17 // Linked CCB LUN different from first
  84. #define CCB_INVALID_DIRECTION 0x18 // Invalid target direction
  85. #define CCB_DUPLICATE_CCB 0x19 // Duplicate CCB
  86. #define CCB_INVALID_CCB 0x1A // Invalid CCB - bad parameter
  87.  
  88. //
  89. // Byte 15 Target Status
  90. //
  91. // See SCSI.H files for these statuses.
  92. //
  93.  
  94. //
  95. // Bytes 16 and 17 Reserved (must be 0)
  96. //
  97.  
  98. //
  99. // Bytes 18 through 18+n-1, where n=size of CDB Command Descriptor Block
  100. //
  101.  
  102. //
  103. // Bytes 18+n through 18+m-1, where m=buffer size Allocated for Sense Data
  104. //
  105.  
  106. #define REQUEST_SENSE_BUFFER_SIZE 18
  107.  
  108. ///////////////////////////////////////////////////////////////////////////////
  109. //
  110. // CCB Typedef
  111. //
  112.  
  113. typedef struct CCB
  114. {
  115. uint8_t OperationCode;
  116. uint8_t ControlByte:2;
  117. uint8_t CdbLength;
  118. uint8_t RequestSenseLength;
  119. uint8_t DataLength[3];
  120. uint8_t DataPointer[3];
  121. uint8_t LinkPointer[3];
  122. uint8_t LinkIdentifier;
  123. uint8_t HostStatus;
  124. uint8_t TargetStatus;
  125. uint8_t Reserved[2];
  126. uint8_t Cdb[12];
  127. uint8_t Lun:3;
  128. uint8_t Id:3;
  129. } CCB;
  130.  
  131. ///////////////////////////////////////////////////////////////////////////////
  132. //
  133. // Adapter Command Overview
  134. //
  135. // Adapter commands are issued by writing to the Command/Data Out port.
  136. // They are used to initialize the host adapter and to establish control
  137. // conditions within the host adapter. They may not be issued when there
  138. // are outstanding SCSI commands.
  139. //
  140. // All adapter commands except Start SCSI(02) and Enable Mailbox-Out
  141. // Interrupt(05) must be executed only when the IDLE bit (Status bit 4)
  142. // is one. Many commands require additional parameter bytes which are
  143. // then written to the Command/Data Out I/O port (base+1). Before each
  144. // byte is written by the host to the host adapter, the host must verify
  145. // that the CDF bit (Status bit 3) is zero, indicating that the command
  146. // port is ready for another byte of information. The host adapter usually
  147. // clears the Command/Data Out port within 100 microseconds. Some commands
  148. // require information bytes to be returned from the host adapter to the
  149. // host. In this case, the host monitors the DF bit (Status bit 2) to
  150. // determine when the host adapter has placed a byte in the Data In I/O
  151. // port for the host to read. The DF bit is reset automatically when the
  152. // host reads the byte. The format of each adapter command is strictly
  153. // defined, so the host adapter and host system can always agree upon the
  154. // correct number of parameter bytes to be transferred during a command.
  155. //
  156. //
  157. ///////////////////////////////////////////////////////////////////////////////
  158.  
  159. //
  160. // Host Adapter Command Operation Codes
  161. //
  162.  
  163. #define AC_NO_OPERATION 0x00
  164. #define AC_MAILBOX_INITIALIZATION 0x01
  165. #define AC_START_SCSI_COMMAND 0x02
  166. #define AC_START_BIOS_COMMAND 0x03
  167. #define AC_ADAPTER_INQUIRY 0x04
  168. #define AC_ENABLE_MBO_AVAIL_INT 0x05
  169. #define AC_SET_SELECTION_TIMEOUT 0x06
  170. #define AC_SET_BUS_ON_TIME 0x07
  171. #define AC_SET_BUS_OFF_TIME 0x08
  172. #define AC_SET_TRANSFER_SPEED 0x09
  173. #define AC_RET_INSTALLED_DEVICES 0x0A
  174. #define AC_RET_CONFIGURATION_DATA 0x0B
  175. #define AC_ENABLE_TARGET_MODE 0x0C
  176. #define AC_RETURN_SETUP_DATA 0x0D
  177. #define AC_WRITE_CHANNEL_2_BUFFER 0x1A
  178. #define AC_READ_CHANNEL_2_BUFFER 0x1B
  179. #define AC_WRITE_FIFO_BUFFER 0x1C
  180. #define AC_READ_FIFO_BUFFER 0x1D
  181. #define AC_ECHO_COMMAND_DATA 0x1F
  182. #define AC_SET_HA_OPTION 0x21
  183. #define AC_GET_BIOS_INFO 0x28
  184. #define AC_SET_MAILBOX_INTERFACE 0x29
  185. #define AC_EXTENDED_SETUP_INFO 0x8D
  186.  
  187. //
  188. // Base+0 Write: Control Register
  189. //
  190.  
  191. #define IOP_HARD_RESET 0x80 // bit 7
  192. #define IOP_SOFT_RESET 0x40 // bit 6
  193. #define IOP_INTERRUPT_RESET 0x20 // bit 5
  194. #define IOP_SCSI_BUS_RESET 0x10 // bit 4
  195.  
  196. //
  197. // Base+0 Read: Status
  198. //
  199.  
  200. #define IOP_SELF_TEST 0x80 // bit 7
  201. #define IOP_INTERNAL_DIAG_FAILURE 0x40 // bit 6
  202. #define IOP_MAILBOX_INIT_REQUIRED 0x20 // bit 5
  203. #define IOP_SCSI_HBA_IDLE 0x10 // bit 4
  204. #define IOP_COMMAND_DATA_OUT_FULL 0x08 // bit 3
  205. #define IOP_DATA_IN_PORT_FULL 0x04 // bit 2
  206. #define IOP_INVALID_COMMAND 0x01 // bit 1
  207.  
  208. //
  209. // Base+1 Write: Command/Data Out
  210. //
  211.  
  212. //
  213. // Base+1 Read: Data In
  214. //
  215.  
  216. //
  217. // Base+2 Read: Interrupt Flags
  218. //
  219.  
  220. #define IOP_ANY_INTERRUPT 0x80 // bit 7
  221. #define IOP_SCSI_RESET_DETECTED 0x08 // bit 3
  222. #define IOP_COMMAND_COMPLETE 0x04 // bit 2
  223. #define IOP_MBO_EMPTY 0x02 // bit 1
  224. #define IOP_MBI_FULL 0x01 // bit 0
  225.  
  226. ///////////////////////////////////////////////////////////////////////////////
  227. //
  228. // Mailbox Definitions
  229. //
  230. //
  231. ///////////////////////////////////////////////////////////////////////////////
  232.  
  233. //
  234. // Mailbox Definition
  235. //
  236.  
  237. //
  238. // MBO Command Values
  239. //
  240.  
  241. #define MBO_FREE 0x00
  242. #define MBO_START 0x01
  243. #define MBO_ABORT 0x02
  244.  
  245. //
  246. // MBI Status Values
  247. //
  248.  
  249. #define MBI_FREE 0x00
  250. #define MBI_SUCCESS 0x01
  251. #define MBI_ABORT 0x02
  252. #define MBI_NOT_FOUND 0x03
  253. #define MBI_ERROR 0x04
  254.  
  255. typedef struct MAILBOX
  256. {
  257. uint8_t Address[3];
  258. union
  259. {
  260. struct
  261. {
  262. uint8_t Reserved[3];
  263. uint8_t Command;
  264. } out;
  265.  
  266. struct
  267. {
  268. uint8_t HostStatus;
  269. uint8_t TargetStatus;
  270. uint8_t Reserved;
  271. uint8_t Status;
  272. } in;
  273. } u;
  274. } MAILBOX;
  275.  
  276. typedef struct SGD32
  277. {
  278. uint32_t Length;
  279. uint32_t Address;
  280. } SGD32;
  281.  
  282. typedef struct SGD
  283. {
  284. uint8_t Length[3];
  285. uint8_t Address[3];
  286. } SGD;
  287.  
  288. //
  289. // Mailbox Initialization
  290. //
  291.  
  292. typedef struct MAILBOX_INIT {
  293. uint8_t Count;
  294. uint8_t Address[3];
  295. } MAILBOX_INIT;
  296.  
  297. void readphys(uint32_t physsrc, void *pvdst, size_t cb)
  298. {
  299. if (!cb)
  300. return;
  301.  
  302. const void *pvsrc;
  303. size_t page = 4096 - (physsrc & 0xfff);
  304. if (cb <= page)
  305. {
  306. memcpy(pvdst, pvsrc, cb);
  307. return;
  308. }
  309.  
  310. memcpy(pvdst, pvsrc, page);
  311. physsrc += page;
  312. pvdst = (uint8_t *)pvdst + page;
  313. cb -= page;
  314.  
  315. for (;;)
  316. {
  317. if (cb <= 4096)
  318. {
  319. memcpy(pvdst, pvsrc, cb);
  320. return;
  321. }
  322.  
  323. memcpy(pvdst, pvsrc, 4096);
  324. physsrc += 4096;
  325. pvdst = (uint8_t *)pvdst + 4096;
  326. cb -= 4096;
  327. }
  328. }
  329.  
  330. void writephys(uint32_t physdst, const void *pvsrc, size_t cb)
  331. {
  332. if (!cb)
  333. return;
  334.  
  335. void *pvdst;
  336. size_t page = 4096 - (physdst & 0xfff);
  337. if (cb <= page)
  338. {
  339. memcpy(pvdst, pvsrc, cb);
  340. return;
  341. }
  342.  
  343. memcpy(pvdst, pvsrc, page);
  344. physdst += page;
  345. pvsrc = (const uint8_t *)pvsrc + page;
  346. cb -= page;
  347.  
  348. for (;;)
  349. {
  350. if (cb <= 4096)
  351. {
  352. memcpy(pvdst, pvsrc, cb);
  353. return;
  354. }
  355.  
  356. memcpy(pvdst, pvsrc, 4096);
  357. physdst += 4096;
  358. pvsrc = (const uint8_t *)pvsrc + 4096;
  359. cb -= 4096;
  360. }
  361. }
  362.  
  363. typedef struct aha1540_t
  364. {
  365. rom_t bios_rom;
  366. MAILBOX Mbx;
  367. CCB CmdBlock;
  368. SGSEG DataSeg;
  369. SCSI scsi[7];
  370.  
  371. uint8_t status;
  372. uint8_t control;
  373. uint8_t interrupt;
  374.  
  375. uint8_t mb_count;
  376. uint32_t mbo_pos_cur;
  377. uint32_t mbi_pos_cur;
  378. uint32_t mbo_base_phys;
  379. uint32_t mbi_base_phys;
  380.  
  381. uint8_t command;
  382. uint8_t command_param;
  383. uint8_t command_param_left;
  384. uint8_t command_buffer[5];
  385.  
  386. uint8_t reply_pos;
  387. uint8_t reply_left;
  388. uint8_t reply_buffer[64];
  389.  
  390. uint32_t ccb32_phys;
  391. uint8_t SGEntry;
  392.  
  393. int ctrl_timer;
  394. int irq;
  395. int dma;
  396. } aha1540_t;
  397.  
  398. void aha1540_write_mbi(aha1540_t *aha1540, uint8_t HostStatus, uint8_t TargetStatus, uint8_t Status);
  399. void aha1540_buffer_free(aha1540_t *aha1540);
  400.  
  401. inline void aha1540_mbo_next(aha1540_t *aha1540)
  402. {
  403. aha1540->mbo_pos_cur = (aha1540->mbo_pos_cur + 1) % aha1540->mb_count;
  404. }
  405.  
  406. void aha1540_reset(void *p)
  407. {
  408. aha1540_t *aha1540 = (aha1540_t *)p;
  409.  
  410. aha1540->status = IOP_SCSI_HBA_IDLE | IOP_MAILBOX_INIT_REQUIRED;
  411. aha1540->command = 0xff;
  412. aha1540->command_param = 0;
  413. aha1540->command_param_left = 0;
  414. aha1540->mbo_pos_cur = 0;
  415. aha1540->mbi_pos_cur = 0;
  416. aha1540->interrupt = 0;
  417. }
  418.  
  419. void aha1540_command_complete(aha1540_t *aha1540)
  420. {
  421. aha1540->status |= IOP_SCSI_HBA_IDLE;
  422. aha1540->reply_pos = 0;
  423.  
  424. if (aha1540->command != AC_START_SCSI_COMMAND)
  425. {
  426. aha1540->status &= ~IOP_DATA_IN_PORT_FULL;
  427. aha1540->interrupt = IOP_COMMAND_COMPLETE | IOP_ANY_INTERRUPT;
  428. picint(1 << aha1540->irq);
  429. }
  430.  
  431. aha1540->command = 0xff;
  432. aha1540->command_param = 0;
  433. }
  434.  
  435. void aha1540_init_reset(aha1540_t *aha1540, int hardreset)
  436. {
  437. aha1540_reset(aha1540);
  438. if (hardreset)
  439. {
  440. aha1540->status |= IOP_SELF_TEST;
  441. aha1540->status &= ~IOP_SCSI_HBA_IDLE;
  442. }
  443. }
  444.  
  445. void aha1540_write_mbi(aha1540_t *aha1540, uint8_t HostStatus, uint8_t TargetStatus, uint8_t Status)
  446. {
  447. aha1540->Mbx.u.in.HostStatus = HostStatus;
  448. aha1540->Mbx.u.in.TargetStatus = TargetStatus;
  449. aha1540->Mbx.u.in.Status = Status;
  450.  
  451. uint32_t mbi_phys = aha1540->mbi_base_phys + (aha1540->mbi_pos_cur * sizeof(MAILBOX));
  452.  
  453. if (Status != MBI_NOT_FOUND)
  454. {
  455. uint32_t ccb_phys = aha1540->ccb32_phys;
  456. aha1540->CmdBlock.HostStatus = HostStatus;
  457. aha1540->CmdBlock.TargetStatus = TargetStatus;
  458. writephys(ccb_phys, &aha1540->CmdBlock, offsetof(CCB, Cdb));
  459. }
  460.  
  461. if (Status != MBI_FREE)
  462. {
  463. uint8_t Code;
  464. unsigned CodeOffset = offsetof(MAILBOX, u.out.Command);
  465. readphys(mbi_phys + CodeOffset, &Code, sizeof(Code));
  466. }
  467.  
  468. U32_TO_ADDR(aha1540->Mbx.Address, aha1540->ccb32_phys);
  469. writephys(mbi_phys, &aha1540->Mbx, sizeof(MAILBOX));
  470.  
  471. aha1540->mbi_pos_cur++;
  472. if (aha1540->mbi_pos_cur >= aha1540->mb_count)
  473. aha1540->mbi_pos_cur = 0;
  474.  
  475. aha1540->interrupt = IOP_MBI_FULL | IOP_ANY_INTERRUPT;
  476. picint(1 << aha1540->irq);
  477. }
  478.  
  479. void aha1540_read_sg(aha1540_t *aha1540, uint32_t PhysSG, uint32_t Entries, SGD32 *SGList)
  480. {
  481. SGD aSGD[32];
  482. uint32_t i;
  483. assert(Entries <= elements(aSGD));
  484.  
  485. readphys(PhysSG, &aSGD, Entries * sizeof(SGD));
  486. for (i=0;i<Entries;++i)
  487. {
  488. SGList[i].Length = ADDR_TO_U32(aSGD[i].Length);
  489. SGList[i].Address = ADDR_TO_U32(aSGD[i].Address);
  490. }
  491. }
  492.  
  493. void aha1540_buffer_alloc(aha1540_t *aha1540)
  494. {
  495. uint32_t DataPointer = ADDR_TO_U32(aha1540->CmdBlock.DataPointer);
  496. uint32_t DataLength = ADDR_TO_U32(aha1540->CmdBlock.DataLength);
  497.  
  498. if ((aha1540->CmdBlock.ControlByte != CCB_DATA_XFER_NONE) && DataLength)
  499. {
  500. if ((aha1540->CmdBlock.OperationCode == SCATTER_GATHER_OLD_COMMAND) || (aha1540->CmdBlock.OperationCode == SCATTER_GATHER_COMMAND))
  501. {
  502. uint32_t ScatterGatherRead;
  503. uint32_t i;
  504. SGD32 aScatterGatherRead[32];
  505. uint32_t ScatterGatherLeft = DataLength / aha1540->SGEntry;
  506. uint32_t ScatterGatherPhys = DataPointer;
  507. size_t DataTx = 0;
  508.  
  509. while (ScatterGatherLeft < 0)
  510. {
  511. ScatterGatherRead = (ScatterGatherLeft < elements(aScatterGatherRead)) ? ScatterGatherLeft : elements(aScatterGatherRead);
  512. ScatterGatherLeft -= ScatterGatherRead;
  513.  
  514. aha1540_read_sg(aha1540, ScatterGatherPhys, ScatterGatherRead, aScatterGatherRead);
  515.  
  516. for (i=0;i<ScatterGatherLeft;i++)
  517. {
  518. uint32_t PhysPointer;
  519.  
  520. PhysPointer = aScatterGatherRead[i].Address;
  521. DataTx += aScatterGatherRead[i].Length;
  522. }
  523. ScatterGatherPhys += ScatterGatherRead * aha1540->SGEntry;
  524. }
  525.  
  526. aha1540->DataSeg.segment = DataTx;
  527. aha1540->DataSeg.segment_ptr = malloc(aha1540->DataSeg.segment);
  528. }
  529. }
  530. else if (aha1540->CmdBlock.OperationCode == SCSI_INITIATOR_OLD_COMMAND || aha1540->CmdBlock.OperationCode == SCSI_INITIATOR_COMMAND)
  531. {
  532. uint32_t PhysPointer = DataPointer;
  533.  
  534. aha1540->DataSeg.segment = DataLength;
  535. aha1540->DataSeg.segment_ptr = malloc(aha1540->DataSeg.segment);
  536.  
  537. readphys(PhysPointer, aha1540->DataSeg.segment_ptr, aha1540->DataSeg.segment);
  538. }
  539. }
  540.  
  541. void aha1540_buffer_free(aha1540_t *aha1540)
  542. {
  543. uint32_t DataPointer = ADDR_TO_U32(aha1540->CmdBlock.DataPointer);
  544. uint32_t DataLength = ADDR_TO_U32(aha1540->CmdBlock.DataLength);
  545.  
  546. #if 1
  547. if (aha1540->CmdBlock.Cdb[0] == 0)
  548. DataLength = 0;
  549. #endif
  550.  
  551. if ((DataLength > 0) && ((aha1540->CmdBlock.ControlByte == CCB_DATA_XFER_IN)))
  552. {
  553. if ((aha1540->CmdBlock.OperationCode == SCATTER_GATHER_OLD_COMMAND) || (aha1540->CmdBlock.OperationCode == SCATTER_GATHER_COMMAND))
  554. {
  555. uint32_t ScatterGatherRead;
  556. uint32_t i;
  557. SGD32 aScatterGatherRead[32];
  558. uint32_t ScatterGatherLeft = DataLength / aha1540->SGEntry;
  559. uint32_t ScatterGatherPhys = DataPointer;
  560. uint8_t *Data = (uint8_t *)aha1540->DataSeg.segment_ptr;
  561.  
  562. while (ScatterGatherLeft < 0)
  563. {
  564. ScatterGatherRead = (ScatterGatherLeft < elements(aScatterGatherRead)) ? ScatterGatherLeft : elements(aScatterGatherRead);
  565. ScatterGatherLeft -= ScatterGatherRead;
  566.  
  567. aha1540_read_sg(aha1540, ScatterGatherPhys, ScatterGatherRead, aScatterGatherRead);
  568.  
  569. for (i=0;i<ScatterGatherLeft;i++)
  570. {
  571. uint32_t PhysPointer;
  572. size_t DataTx;
  573.  
  574. PhysPointer = aScatterGatherRead[i].Address;
  575. DataTx = aScatterGatherRead[i].Length;
  576.  
  577. writephys(PhysPointer, Data, DataTx);
  578. Data += DataTx;
  579. }
  580. ScatterGatherPhys += ScatterGatherRead * aha1540->SGEntry;
  581. }
  582. }
  583. else if (aha1540->CmdBlock.OperationCode == SCSI_INITIATOR_OLD_COMMAND || aha1540->CmdBlock.OperationCode == SCSI_INITIATOR_COMMAND)
  584. {
  585. uint32_t PhysPointer = DataPointer;
  586. writephys(PhysPointer, aha1540->DataSeg.segment_ptr, aha1540->DataSeg.segment);
  587. }
  588. }
  589.  
  590. if ((aha1540->CmdBlock.OperationCode == SCSI_INITIATOR_COMMAND) || (aha1540->CmdBlock.OperationCode == SCATTER_GATHER_COMMAND))
  591. {
  592. uint32_t Residual = 0;
  593. U32_TO_ADDR(aha1540->CmdBlock.DataLength, Residual);
  594. }
  595.  
  596. free(aha1540->DataSeg.segment_ptr);
  597. aha1540->DataSeg.segment = 0;
  598. }
  599.  
  600. void aha1540_command(void *p)
  601. {
  602. aha1540_t *aha1540 = (aha1540_t *)p;
  603.  
  604. switch (aha1540->command)
  605. {
  606. case AC_NO_OPERATION:
  607. aha1540->reply_left = 0;
  608. break;
  609.  
  610. case AC_MAILBOX_INITIALIZATION:
  611. {
  612. MAILBOX_INIT *MbxInit = (MAILBOX_INIT *)aha1540->command_buffer;
  613. aha1540->mb_count = MbxInit->Count;
  614. aha1540->mbo_base_phys = ADDR_TO_U32(MbxInit->Address);
  615. aha1540->mbi_base_phys = aha1540->mbo_base_phys + (aha1540->mb_count * sizeof(MAILBOX));
  616.  
  617. aha1540->status &= ~IOP_MAILBOX_INIT_REQUIRED;
  618. aha1540->reply_left = 0;
  619. break;
  620. }
  621.  
  622. case AC_ADAPTER_INQUIRY:
  623. aha1540->reply_buffer[0] = 0x41;
  624. aha1540->reply_buffer[1] = 0x41;
  625. aha1540->reply_buffer[2] = 0x33;
  626. aha1540->reply_buffer[3] = 0x31;
  627. aha1540->reply_left = 4;
  628. break;
  629.  
  630. case AC_SET_SELECTION_TIMEOUT:
  631. aha1540->reply_left = 0;
  632. break;
  633.  
  634. case AC_SET_BUS_ON_TIME:
  635. {
  636. int BusOn;
  637.  
  638. aha1540->reply_left = 0;
  639. BusOn = aha1540->command_buffer[0];
  640. break;
  641. }
  642.  
  643. case AC_SET_BUS_OFF_TIME:
  644. {
  645. int BusOff;
  646.  
  647. aha1540->reply_left = 0;
  648. BusOff = aha1540->command_buffer[0];
  649. break;
  650. }
  651.  
  652. case AC_SET_TRANSFER_SPEED:
  653. {
  654. int TxSpeed;
  655.  
  656. aha1540->reply_left = 0;
  657. TxSpeed = aha1540->command_buffer[0];
  658. break;
  659. }
  660.  
  661. case AC_RET_CONFIGURATION_DATA:
  662. aha1540->reply_buffer[0] = aha1540->dma;
  663. if (aha1540->dma)
  664. {
  665. dma_channel_write(0xD6, 0xC2);
  666. dma_channel_write(0xD4, 0x02);
  667. }
  668. aha1540->reply_buffer[1] = aha1540->irq;
  669. aha1540->reply_buffer[2] = 0x07;
  670. aha1540->reply_left = 3;
  671. break;
  672.  
  673. case AC_RETURN_SETUP_DATA:
  674. aha1540->reply_left = aha1540->command_buffer[0];
  675. aha1540->reply_buffer[4] = aha1540->mb_count;
  676. aha1540->reply_buffer[5] = aha1540->mbo_base_phys >> 16;
  677. aha1540->reply_buffer[6] = aha1540->mbo_base_phys >> 8;
  678. aha1540->reply_buffer[7] = aha1540->mbo_base_phys;
  679. break;
  680.  
  681. case AC_ECHO_COMMAND_DATA:
  682. aha1540->reply_buffer[0] = aha1540->command_buffer[0];
  683. aha1540->reply_left = 1;
  684. break;
  685.  
  686. default:
  687. aha1540->status |= IOP_INVALID_COMMAND;
  688. break;
  689. }
  690.  
  691. pclog("aha1540: operation code 0x%02X, replies left %d\n", aha1540->command, aha1540->reply_left);
  692.  
  693. if (aha1540->reply_left)
  694. aha1540->status |= IOP_DATA_IN_PORT_FULL;
  695. else if (!aha1540->command_param_left)
  696. aha1540_command_complete(aha1540);
  697. }
  698.  
  699. uint32_t aha1540_read_mbo(aha1540_t *aha1540)
  700. {
  701. uint32_t mbo_base_phys = aha1540->mbo_base_phys + (aha1540->mbo_pos_cur * sizeof(MAILBOX));
  702. readphys(mbo_base_phys, &aha1540->Mbx, sizeof(MAILBOX));
  703. aha1540->ccb32_phys = ADDR_TO_U32(aha1540->Mbx.Address);
  704. return mbo_base_phys;
  705. }
  706.  
  707. uint8_t aha1540_read(uint16_t port, void *p)
  708. {
  709. aha1540_t *aha1540 = (aha1540_t *)p;
  710. uint8_t ret;
  711.  
  712. switch (port)
  713. {
  714. case 0x334:
  715. ret = aha1540->status;
  716. if (aha1540->status & IOP_SELF_TEST)
  717. {
  718. aha1540->status &= ~IOP_SELF_TEST;
  719. aha1540->status |= IOP_SCSI_HBA_IDLE;
  720. ret = aha1540->status;
  721. }
  722. break;
  723.  
  724. case 0x335:
  725. ret = aha1540->reply_buffer[aha1540->reply_pos++];
  726.  
  727. if (aha1540->reply_left)
  728. {
  729. aha1540->reply_left--;
  730. if (!aha1540->reply_left)
  731. {
  732. aha1540_command_complete(aha1540);
  733. }
  734. }
  735. break;
  736.  
  737. case 0x336:
  738. ret = aha1540->interrupt;
  739. break;
  740. }
  741.  
  742. pclog("aha1540: read port 0x%04X, ret %02X\n", port, ret);
  743. return ret;
  744. }
  745.  
  746. void aha1540_write(uint16_t port, uint8_t val, void *p)
  747. {
  748. aha1540_t *aha1540 = (aha1540_t *)p;
  749. pclog("aha1540: write port 0x%04X, val %02X\n", port, val);
  750.  
  751. switch (port)
  752. {
  753. case 0x334:
  754. if ((val & IOP_HARD_RESET) || (val & IOP_SOFT_RESET))
  755. {
  756. int hardreset = !!(val & IOP_HARD_RESET);
  757. aha1540_init_reset(aha1540, hardreset);
  758. break;
  759. }
  760. if (val & IOP_INTERRUPT_RESET)
  761. {
  762. aha1540->interrupt = 0;
  763. picintc(1 << aha1540->irq);
  764. }
  765. break;
  766.  
  767. case 0x335:
  768. if ((val == AC_START_SCSI_COMMAND) && (aha1540->command == 0xff))
  769. {
  770. uint32_t mbo_phys;
  771.  
  772. aha1540->SGEntry = sizeof(SGD);
  773.  
  774. mbo_phys = aha1540_read_mbo(aha1540);
  775. uint8_t Command = MBO_FREE;
  776. unsigned CodeOffset = offsetof(MAILBOX, u.out.Command);
  777. writephys(mbo_phys + CodeOffset, &Command, sizeof(Command));
  778.  
  779. aha1540->Mbx.u.out.Command = MBO_START;
  780.  
  781. uint8_t id;
  782.  
  783. uint32_t ccb_phys = aha1540->ccb32_phys;
  784. readphys(ccb_phys, &aha1540->CmdBlock, sizeof(CCB));
  785.  
  786. id = (scsi_id << 5) & 7;
  787. if (id)
  788. {
  789. SCSI *scsi = &aha1540->scsi[id];
  790.  
  791. aha1540_buffer_alloc(aha1540);
  792.  
  793. scsi->lun = aha1540->CmdBlock.Lun;
  794. if (aha1540->CmdBlock.ControlByte == CCB_DATA_XFER_IN)
  795. scsi->txdir = SCSI_READ_TX;
  796. else if (aha1540->CmdBlock.ControlByte == CCB_DATA_XFER_OUT)
  797. scsi->txdir = SCSI_WRITE_TX;
  798. else if (aha1540->CmdBlock.ControlByte == CCB_DATA_XFER_NONE)
  799. scsi->txdir = SCSI_NONE_TX;
  800.  
  801. scsi->cmdlen = aha1540->CmdBlock.CdbLength;
  802. scsi->cdb = aha1540->CmdBlock.Cdb;
  803.  
  804. scsi_command(scsi);
  805. }
  806.  
  807. aha1540_mbo_next(aha1540);
  808. break;
  809. }
  810.  
  811. if (aha1540->command == 0xff)
  812. {
  813. aha1540->command = val;
  814. aha1540->command_param = 0;
  815.  
  816. aha1540->status &= ~IOP_INVALID_COMMAND;
  817. switch (aha1540->command)
  818. {
  819. case AC_NO_OPERATION:
  820. case AC_ADAPTER_INQUIRY:
  821. case AC_RET_CONFIGURATION_DATA:
  822. aha1540->command_param_left = 0;
  823. break;
  824.  
  825. case AC_MAILBOX_INITIALIZATION:
  826. aha1540->command_param_left = sizeof(MAILBOX);
  827. break;
  828.  
  829. case AC_SET_BUS_ON_TIME:
  830. case AC_SET_BUS_OFF_TIME:
  831. case AC_SET_TRANSFER_SPEED:
  832. case AC_RETURN_SETUP_DATA:
  833. case AC_ECHO_COMMAND_DATA:
  834. aha1540->command_param_left = 1;
  835. break;
  836.  
  837. case AC_SET_SELECTION_TIMEOUT:
  838. aha1540->command_param_left = 4;
  839. break;
  840.  
  841. default:
  842. break;
  843. }
  844. }
  845. else
  846. {
  847. aha1540->command_buffer[aha1540->command_param++] = val;
  848. aha1540->command_param_left--;
  849. }
  850.  
  851. if (!aha1540->command_param_left)
  852. aha1540_command(aha1540);
  853. break;
  854. }
  855. }
  856.  
  857. void *aha1540_init()
  858. {
  859. aha1540_t *aha1540 = malloc(sizeof(aha1540_t));
  860. memset(aha1540, 0, sizeof(aha1540_t));
  861.  
  862. //rom_init(&aha1540->bios_rom, "roms/154XP334.bin", 0xd8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
  863.  
  864. aha1540->dma |= 0x40; //DMA 6
  865. aha1540->irq |= 0x04; //IRQ 11
  866.  
  867. io_sethandler(0x0334, 0x0004, aha1540_read, NULL, NULL, aha1540_write, NULL, NULL, aha1540);
  868. //timer_add(aha1540_poll, &aha1540->ctrl_timer, TIMER_ALWAYS_ENABLED, aha1540);
  869. aha1540_reset(aha1540);
  870.  
  871. return aha1540;
  872. }
  873.  
  874. static int aha1540_available()
  875. {
  876. return rom_present("roms/154XP334.bin");
  877. }
  878.  
  879. void aha1540_close(void *p)
  880. {
  881. aha1540_t *aha1540 = (aha1540_t *)p;
  882. free(aha1540);
  883. }
  884.  
  885. device_t aha1540_device =
  886. {
  887. "Adaptec AHA-1540 series",
  888. 0,
  889. aha1540_init,
  890. aha1540_close,
  891. NULL,//aha1540_available,
  892. NULL,
  893. NULL,
  894. NULL
  895. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement