992f28615a5e950156ae48b0b92b97be39cffca1
[SCSI2SD-V6.git] / software / SCSI2SD / src / main.c
1 //      Copyright (C) 2014 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 #pragma GCC push_options\r
18 #pragma GCC optimize("-flto")\r
19 \r
20 #include "device.h"\r
21 #include "scsi.h"\r
22 #include "scsiPhy.h"\r
23 #include "config.h"\r
24 #include "disk.h"\r
25 #include "led.h"\r
26 #include "time.h"\r
27 #include "trace.h"\r
28 \r
29 const char* Notice = "Copyright (C) 2015 Michael McMaster <michael@codesrc.com>";\r
30 \r
31 int main()\r
32 {\r
33         timeInit();\r
34         ledInit();\r
35         traceInit();\r
36 \r
37         // Enable global interrupts.\r
38         // Needed for RST and ATN interrupt handlers.\r
39         CyGlobalIntEnable;\r
40 \r
41         // Set interrupt handlers.\r
42         scsiPhyInit();\r
43 \r
44         configInit(&scsiDev.boardCfg);\r
45         debugInit();\r
46 \r
47         scsiInit();\r
48         scsiDiskInit();\r
49 \r
50         // Optional bootup delay\r
51         int delaySeconds = 0;\r
52         while (delaySeconds < scsiDev.boardCfg.startupDelay) {\r
53                 CyDelay(1000);\r
54                 ++delaySeconds;\r
55         }\r
56 \r
57         uint32_t lastSDPoll = getTime_ms();\r
58         sdCheckPresent();\r
59 \r
60 \r
61         while (1)\r
62         {\r
63                 scsiDev.watchdogTick++;\r
64 \r
65                 scsiPoll();\r
66                 scsiDiskPoll();\r
67                 configPoll();\r
68                 sdPoll();\r
69 \r
70                 if (unlikely(scsiDev.phase == BUS_FREE))\r
71                 {\r
72                         if (unlikely(elapsedTime_ms(lastSDPoll) > 200))\r
73                         {\r
74                                 lastSDPoll = getTime_ms();\r
75                                 sdCheckPresent();\r
76                         }\r
77                         else\r
78                         {\r
79                                 // Wait for our 1ms timer to save some power.\r
80                                 // There's an interrupt on the SEL signal to ensure we respond\r
81                                 // quickly to any SCSI commands. The selection abort time is\r
82                                 // only 250us, and new SCSI-3 controllers time-out very\r
83                                 // not long after that, so we need to ensure we wake up quickly.\r
84                                 uint8_t interruptState = CyEnterCriticalSection();\r
85                                 if (!SCSI_ReadFilt(SCSI_Filt_SEL))\r
86                                 {\r
87                                         __WFI(); // Will wake on interrupt, regardless of mask\r
88                                 }\r
89                                 CyExitCriticalSection(interruptState);\r
90                         }\r
91                 }\r
92                 else if (scsiDev.phase >= 0)\r
93                 {\r
94                         // don't waste time scanning SD cards while we're doing disk IO\r
95                         lastSDPoll = getTime_ms();\r
96                 }\r
97         }\r
98         return 0;\r
99 }\r
100 \r
101 #pragma GCC pop_options\r