Many bug fixes, including selection fixes.
[SCSI2SD.git] / software / SCSI2SD / SCSI2SD.cydsn / scsiPhy.c
1 //      Copyright (C) 2013 Michael McMaster <michael@codesrc.com>\r
2 //\r
3 //      This file is part of SCSI2SD.\r
4 //\r
5 //      SCSI2SD is free software: you can redistribute it and/or modify\r
6 //      it under the terms of the GNU General Public License as published by\r
7 //      the Free Software Foundation, either version 3 of the License, or\r
8 //      (at your option) any later version.\r
9 //\r
10 //      SCSI2SD is distributed in the hope that it will be useful,\r
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 //      GNU General Public License for more details.\r
14 //\r
15 //      You should have received a copy of the GNU General Public License\r
16 //      along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.\r
17 \r
18 #include "device.h"\r
19 #include "scsi.h"\r
20 #include "scsiPhy.h"\r
21 #include "bits.h"\r
22 \r
23 CY_ISR_PROTO(scsiResetISR);\r
24 CY_ISR(scsiResetISR)\r
25 {\r
26         scsiDev.resetFlag = 1;\r
27         SCSI_RST_ClearInterrupt();\r
28 }\r
29 \r
30 uint8 scsiReadDBxPins()\r
31 {\r
32         return\r
33                 (SCSI_ReadPin(SCSI_In_DBx_DB7) << 7) |\r
34                 (SCSI_ReadPin(SCSI_In_DBx_DB6) << 6) |\r
35                 (SCSI_ReadPin(SCSI_In_DBx_DB5) << 5) |\r
36                 (SCSI_ReadPin(SCSI_In_DBx_DB4) << 4) |\r
37                 (SCSI_ReadPin(SCSI_In_DBx_DB3) << 3) |\r
38                 (SCSI_ReadPin(SCSI_In_DBx_DB2) << 2) |\r
39                 (SCSI_ReadPin(SCSI_In_DBx_DB1) << 1) |\r
40                 SCSI_ReadPin(SCSI_In_DBx_DB0);          \r
41 }\r
42 \r
43 uint8 scsiReadByte(void)\r
44 {\r
45         while (!(CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG) & 1)) {}\r
46         CY_SET_REG8(scsiTarget_datapath__F0_REG, 0);\r
47         while (!(CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG) & 2)) {}\r
48         return CY_GET_REG8(scsiTarget_datapath__F1_REG);\r
49 }\r
50 \r
51 void scsiRead(uint8* data, uint32 count)\r
52 {\r
53         int prep = 0;\r
54         int i = 0;\r
55 \r
56         while (i < count)\r
57         {\r
58                 if (prep < count && (CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG) & 1))\r
59                 {\r
60                         CY_SET_REG8(scsiTarget_datapath__F0_REG, 0);\r
61                         ++prep;\r
62                 }\r
63                 if ((CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG) & 2))\r
64                 {\r
65                         data[i] =  CY_GET_REG8(scsiTarget_datapath__F1_REG);\r
66                         ++i;\r
67                 }\r
68         }\r
69 }\r
70 \r
71 void scsiWriteByte(uint8 value)\r
72 {\r
73         while (!(CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG) & 1)) {}\r
74         CY_SET_REG8(scsiTarget_datapath__F0_REG, value);\r
75 \r
76         // TODO maybe move this TX EMPTY check to scsiEnterPhase ?\r
77         //while (!(CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG) & 4)) {}\r
78         while (!(CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG) & 2)) {}\r
79         value = CY_GET_REG8(scsiTarget_datapath__F1_REG);       \r
80 }\r
81 \r
82 void scsiWrite(uint8* data, uint32 count)\r
83 {\r
84         int prep = 0;\r
85         int i = 0;\r
86 \r
87         while (i < count)\r
88         {\r
89                 if (prep < count && (CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG) & 1))\r
90                 {\r
91                         CY_SET_REG8(scsiTarget_datapath__F0_REG, data[prep]);\r
92                         ++prep;\r
93                 }\r
94                 if ((CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG) & 2))\r
95                 {\r
96                         CY_GET_REG8(scsiTarget_datapath__F1_REG);\r
97                         ++i;\r
98                 }\r
99         }\r
100 }\r
101 \r
102 static void busSettleDelay(void)\r
103 {\r
104         // Data Release time (switching IO) = 400ns\r
105         // + Bus Settle time (switching phase) = 400ns.\r
106         CyDelayUs(1); // Close enough.\r
107 }\r
108 \r
109 void scsiEnterPhase(int phase)\r
110 {\r
111         if (phase > 0)\r
112         {\r
113                 if (phase & __scsiphase_msg)\r
114                 {\r
115                         SCSI_SetPin(SCSI_Out_MSG);\r
116                 }\r
117                 else\r
118                 {\r
119                         SCSI_ClearPin(SCSI_Out_MSG);\r
120                 }\r
121 \r
122                 if (phase & __scsiphase_cd)\r
123                 {\r
124                         SCSI_SetPin(SCSI_Out_CD);\r
125                 }\r
126                 else\r
127                 {\r
128                         SCSI_ClearPin(SCSI_Out_CD);\r
129                 }\r
130 \r
131                 SCSI_CTL_IO_Write(phase & __scsiphase_io ? 1 : 0);\r
132         }\r
133         else\r
134         {\r
135                 SCSI_ClearPin(SCSI_Out_MSG);\r
136                 SCSI_ClearPin(SCSI_Out_CD);\r
137                 SCSI_CTL_IO_Write(0);\r
138         }\r
139         busSettleDelay();\r
140 }\r
141 \r
142 void scsiPhyInit()\r
143 {\r
144         SCSI_RST_ISR_StartEx(scsiResetISR);\r
145 \r
146         // Interrupts may have already been directed to the (empty)\r
147         // standard ISR generated by PSoC Creator.\r
148         SCSI_RST_ClearInterrupt();\r
149 }\r