diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/ata.c | 5 | ||||
-rw-r--r-- | firmware/drivers/ata_mmc.c | 280 |
2 files changed, 285 insertions, 0 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 05000b02a8..21d97aa939 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -30,6 +30,9 @@ | |||
30 | #include "string.h" | 30 | #include "string.h" |
31 | #include "hwcompat.h" | 31 | #include "hwcompat.h" |
32 | 32 | ||
33 | /* skip whole file for an MMC-based system, FIXME in makefile */ | ||
34 | #ifndef HAVE_MMC | ||
35 | |||
33 | /* Uncomment the matching #define to use plain C code instead if the tweaked | 36 | /* Uncomment the matching #define to use plain C code instead if the tweaked |
34 | * assembler code for disk reading or writing should cause problems. */ | 37 | * assembler code for disk reading or writing should cause problems. */ |
35 | /* #define PREFER_C_READING */ | 38 | /* #define PREFER_C_READING */ |
@@ -1170,3 +1173,5 @@ int ata_init(void) | |||
1170 | 1173 | ||
1171 | return 0; | 1174 | return 0; |
1172 | } | 1175 | } |
1176 | |||
1177 | #endif /* #ifndef HAVE_MMC */ \ No newline at end of file | ||
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c new file mode 100644 index 0000000000..a3669573e0 --- /dev/null +++ b/firmware/drivers/ata_mmc.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include <stdbool.h> | ||
20 | #include "ata.h" | ||
21 | #include "kernel.h" | ||
22 | #include "thread.h" | ||
23 | #include "led.h" | ||
24 | #include "sh7034.h" | ||
25 | #include "system.h" | ||
26 | #include "debug.h" | ||
27 | #include "panic.h" | ||
28 | #include "usb.h" | ||
29 | #include "power.h" | ||
30 | #include "string.h" | ||
31 | #include "hwcompat.h" | ||
32 | |||
33 | /* use file for an MMC-based system, FIXME in makefile */ | ||
34 | #ifdef HAVE_MMC | ||
35 | |||
36 | #define SECTOR_SIZE 512 | ||
37 | #define Q_SLEEP 0 | ||
38 | |||
39 | /* for compatibility */ | ||
40 | bool old_recorder = false; /* FIXME: get rid of this cross-dependency */ | ||
41 | int ata_spinup_time = 0; | ||
42 | static int sleep_timeout = 5*HZ; | ||
43 | char ata_device = 0; /* device 0 (master) or 1 (slave) */ | ||
44 | int ata_io_address = 0; /* 0x300 or 0x200, only valid on recorder */ | ||
45 | static unsigned short identify_info[SECTOR_SIZE]; | ||
46 | |||
47 | static struct mutex ata_mtx; | ||
48 | |||
49 | static bool sleeping = true; | ||
50 | |||
51 | static char ata_stack[DEFAULT_STACK_SIZE]; | ||
52 | static const char ata_thread_name[] = "ata"; | ||
53 | static struct event_queue ata_queue; | ||
54 | static bool initialized = false; | ||
55 | static bool delayed_write = false; | ||
56 | static unsigned char delayed_sector[SECTOR_SIZE]; | ||
57 | static int delayed_sector_num; | ||
58 | |||
59 | static long last_user_activity = -1; | ||
60 | long last_disk_activity = -1; | ||
61 | |||
62 | |||
63 | int ata_read_sectors(unsigned long start, | ||
64 | int incount, | ||
65 | void* inbuf) | ||
66 | { | ||
67 | int ret = 0; | ||
68 | |||
69 | mutex_lock(&ata_mtx); | ||
70 | |||
71 | last_disk_activity = current_tick; | ||
72 | |||
73 | led(true); | ||
74 | sleeping = false; | ||
75 | |||
76 | /* ToDo: action */ | ||
77 | (void)start; | ||
78 | (void)incount; | ||
79 | (void)inbuf; | ||
80 | |||
81 | led(false); | ||
82 | |||
83 | mutex_unlock(&ata_mtx); | ||
84 | |||
85 | /* only flush if reading went ok */ | ||
86 | if ( (ret == 0) && delayed_write ) | ||
87 | ata_flush(); | ||
88 | |||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | |||
93 | |||
94 | int ata_write_sectors(unsigned long start, | ||
95 | int count, | ||
96 | const void* buf) | ||
97 | { | ||
98 | int ret = 0; | ||
99 | |||
100 | if (start == 0) | ||
101 | panicf("Writing on sector 0\n"); | ||
102 | |||
103 | mutex_lock(&ata_mtx); | ||
104 | sleeping = false; | ||
105 | |||
106 | last_disk_activity = current_tick; | ||
107 | |||
108 | led(true); | ||
109 | |||
110 | /* ToDo: action */ | ||
111 | (void)start; | ||
112 | (void)count; | ||
113 | (void)buf; | ||
114 | |||
115 | led(false); | ||
116 | |||
117 | mutex_unlock(&ata_mtx); | ||
118 | |||
119 | /* only flush if writing went ok */ | ||
120 | if ( (ret == 0) && delayed_write ) | ||
121 | ata_flush(); | ||
122 | |||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | extern void ata_delayed_write(unsigned long sector, const void* buf) | ||
127 | { | ||
128 | memcpy(delayed_sector, buf, SECTOR_SIZE); | ||
129 | delayed_sector_num = sector; | ||
130 | delayed_write = true; | ||
131 | } | ||
132 | |||
133 | extern void ata_flush(void) | ||
134 | { | ||
135 | if ( delayed_write ) { | ||
136 | DEBUGF("ata_flush()\n"); | ||
137 | delayed_write = false; | ||
138 | ata_write_sectors(delayed_sector_num, 1, delayed_sector); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | void ata_spindown(int seconds) | ||
143 | { | ||
144 | sleep_timeout = seconds * HZ; | ||
145 | } | ||
146 | |||
147 | bool ata_disk_is_active(void) | ||
148 | { | ||
149 | return !sleeping; | ||
150 | } | ||
151 | |||
152 | static int ata_perform_sleep(void) | ||
153 | { | ||
154 | int ret = 0; | ||
155 | |||
156 | mutex_lock(&ata_mtx); | ||
157 | |||
158 | /* ToDo: is there an equivalent? */ | ||
159 | |||
160 | sleeping = true; | ||
161 | mutex_unlock(&ata_mtx); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | int ata_standby(int time) | ||
166 | { | ||
167 | int ret = 0; | ||
168 | |||
169 | mutex_lock(&ata_mtx); | ||
170 | |||
171 | /* ToDo: is there an equivalent? */ | ||
172 | (void)time; | ||
173 | |||
174 | mutex_unlock(&ata_mtx); | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | int ata_sleep(void) | ||
179 | { | ||
180 | queue_post(&ata_queue, Q_SLEEP, NULL); | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | void ata_spin(void) | ||
185 | { | ||
186 | last_user_activity = current_tick; | ||
187 | } | ||
188 | |||
189 | static void ata_thread(void) | ||
190 | { | ||
191 | static long last_sleep = 0; | ||
192 | struct event ev; | ||
193 | |||
194 | while (1) { | ||
195 | while ( queue_empty( &ata_queue ) ) { | ||
196 | if ( sleep_timeout && !sleeping && | ||
197 | TIME_AFTER( current_tick, | ||
198 | last_user_activity + sleep_timeout ) && | ||
199 | TIME_AFTER( current_tick, | ||
200 | last_disk_activity + sleep_timeout ) ) | ||
201 | { | ||
202 | ata_perform_sleep(); | ||
203 | last_sleep = current_tick; | ||
204 | } | ||
205 | |||
206 | sleep(HZ/4); | ||
207 | } | ||
208 | queue_wait(&ata_queue, &ev); | ||
209 | switch ( ev.id ) { | ||
210 | #ifndef USB_NONE | ||
211 | case SYS_USB_CONNECTED: | ||
212 | /* Tell the USB thread that we are safe */ | ||
213 | DEBUGF("ata_thread got SYS_USB_CONNECTED\n"); | ||
214 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
215 | |||
216 | /* Wait until the USB cable is extracted again */ | ||
217 | usb_wait_for_disconnect(&ata_queue); | ||
218 | break; | ||
219 | #endif | ||
220 | case Q_SLEEP: | ||
221 | last_disk_activity = current_tick - sleep_timeout + (HZ/2); | ||
222 | break; | ||
223 | } | ||
224 | } | ||
225 | } | ||
226 | |||
227 | /* Hardware reset protocol as specified in chapter 9.1, ATA spec draft v5 */ | ||
228 | int ata_hard_reset(void) | ||
229 | { | ||
230 | int ret = 0; | ||
231 | |||
232 | return ret; | ||
233 | } | ||
234 | |||
235 | int ata_soft_reset(void) | ||
236 | { | ||
237 | int ret = 0; | ||
238 | |||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | void ata_enable(bool on) | ||
243 | { | ||
244 | (void)on; | ||
245 | } | ||
246 | |||
247 | unsigned short* ata_get_identify(void) | ||
248 | { | ||
249 | return identify_info; | ||
250 | } | ||
251 | |||
252 | int ata_init(void) | ||
253 | { | ||
254 | int rc = 0; | ||
255 | |||
256 | mutex_init(&ata_mtx); | ||
257 | |||
258 | led(false); | ||
259 | |||
260 | /* ToDo: Port setup */ | ||
261 | // PAIOR |= 0x1680; | ||
262 | |||
263 | |||
264 | sleeping = false; | ||
265 | ata_enable(true); | ||
266 | |||
267 | if ( !initialized ) { | ||
268 | |||
269 | queue_init(&ata_queue); | ||
270 | |||
271 | last_disk_activity = current_tick; | ||
272 | create_thread(ata_thread, ata_stack, | ||
273 | sizeof(ata_stack), ata_thread_name); | ||
274 | initialized = true; | ||
275 | } | ||
276 | |||
277 | return rc; | ||
278 | } | ||
279 | |||
280 | #endif /* #ifdef HAVE_MMC */ | ||