summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/ata.c95
-rw-r--r--firmware/drivers/ata.h2
2 files changed, 63 insertions, 34 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 963929deb7..3fdc93669e 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -19,11 +19,13 @@
19#include <stdbool.h> 19#include <stdbool.h>
20#include "ata.h" 20#include "ata.h"
21#include "kernel.h" 21#include "kernel.h"
22#include "thread.h"
22#include "led.h" 23#include "led.h"
23#include "sh7034.h" 24#include "sh7034.h"
24#include "system.h" 25#include "system.h"
25#include "debug.h" 26#include "debug.h"
26#include "panic.h" 27#include "panic.h"
28#include "usb.h"
27 29
28#define SECTOR_SIZE 512 30#define SECTOR_SIZE 512
29#define ATA_DATA (*((volatile unsigned short*)0x06104100)) 31#define ATA_DATA (*((volatile unsigned short*)0x06104100))
@@ -61,6 +63,8 @@
61#define CMD_SLEEP 0xE6 63#define CMD_SLEEP 0xE6
62#define CMD_SECURITY_FREEZE_LOCK 0xF5 64#define CMD_SECURITY_FREEZE_LOCK 0xF5
63 65
66#define Q_SLEEP 0
67
64static struct mutex ata_mtx; 68static struct mutex ata_mtx;
65char ata_device; /* device 0 (master) or 1 (slave) */ 69char ata_device; /* device 0 (master) or 1 (slave) */
66int ata_io_address; /* 0x300 or 0x200, only valid on recorder */ 70int ata_io_address; /* 0x300 or 0x200, only valid on recorder */
@@ -68,6 +72,12 @@ static volatile unsigned char* ata_control;
68 72
69bool old_recorder = false; 73bool old_recorder = false;
70static bool sleeping = false; 74static bool sleeping = false;
75static int sleep_timer = 0;
76static int sleep_timeout = 5*HZ;
77static char ata_stack[DEFAULT_STACK_SIZE];
78static char ata_thread_name[] = "ata";
79static struct event_queue ata_queue;
80static bool initialized = false;
71 81
72static int wait_for_bsy(void) 82static int wait_for_bsy(void)
73{ 83{
@@ -121,7 +131,8 @@ int ata_read_sectors(unsigned long start,
121 } 131 }
122 132
123 mutex_lock(&ata_mtx); 133 mutex_lock(&ata_mtx);
124 134 sleep_timer = sleep_timeout;
135
125 if (!wait_for_rdy()) 136 if (!wait_for_rdy())
126 { 137 {
127 mutex_unlock(&ata_mtx); 138 mutex_unlock(&ata_mtx);
@@ -179,6 +190,7 @@ int ata_write_sectors(unsigned long start,
179 } 190 }
180 191
181 mutex_lock(&ata_mtx); 192 mutex_lock(&ata_mtx);
193 sleep_timer = sleep_timeout;
182 194
183 if (!wait_for_rdy()) 195 if (!wait_for_rdy())
184 { 196 {
@@ -254,58 +266,70 @@ static int freeze_lock(void)
254 return 0; 266 return 0;
255} 267}
256 268
257int ata_spindown(int time) 269void ata_spindown(int seconds)
270{
271 sleep_timeout = seconds * HZ;
272}
273
274static int ata_perform_sleep(void)
258{ 275{
259 int ret = 0; 276 int ret = 0;
260 277
261 mutex_lock(&ata_mtx); 278 mutex_lock(&ata_mtx);
262 279
263 if(!wait_for_rdy()) 280 if(!wait_for_rdy()) {
264 {
265 mutex_unlock(&ata_mtx); 281 mutex_unlock(&ata_mtx);
266 return -1; 282 return -1;
267 } 283 }
268 284
269 if ( time == -1 ) { 285 ATA_SELECT = ata_device;
270 ATA_COMMAND = CMD_STANDBY_IMMEDIATE; 286 ATA_COMMAND = CMD_SLEEP;
271 }
272 else {
273 if (time > 255)
274 {
275 mutex_unlock(&ata_mtx);
276 return -1;
277 }
278 ATA_NSECTOR = time & 0xff;
279 ATA_COMMAND = CMD_STANDBY;
280 }
281 287
282 if (!wait_for_rdy()) 288 if (!wait_for_rdy())
283 ret = -1; 289 ret = -1;
284 290
291 sleeping = true;
292 sleep_timer = 0;
285 mutex_unlock(&ata_mtx); 293 mutex_unlock(&ata_mtx);
286 return ret; 294 return ret;
287} 295}
288 296
289int ata_sleep(void) 297int ata_sleep(void)
290{ 298{
291 int ret = 0; 299 queue_post(&ata_queue, Q_SLEEP, NULL);
300 return 0;
301}
292 302
293 mutex_lock(&ata_mtx); 303static void ata_thread(void)
304{
305 struct event ev;
294 306
295 if(!wait_for_rdy()) { 307 while (1) {
296 mutex_unlock(&ata_mtx); 308 queue_wait(&ata_queue, &ev);
297 return -1; 309 switch ( ev.id ) {
310 case SYS_USB_CONNECTED:
311 /* Tell the USB thread that we are safe */
312 DEBUGF("backlight_thread got SYS_USB_CONNECTED\n");
313 usb_acknowledge(SYS_USB_CONNECTED_ACK);
314
315 /* Wait until the USB cable is extracted again */
316 usb_wait_for_disconnect(&ata_queue);
317 break;
318
319 case Q_SLEEP:
320 ata_perform_sleep();
321 break;
322 }
298 } 323 }
324}
299 325
300 ATA_SELECT = ata_device; 326static void ata_tick(void)
301 ATA_COMMAND = CMD_SLEEP; 327{
302 328 if (sleep_timer) {
303 if (!wait_for_rdy()) 329 sleep_timer--;
304 ret = -1; 330 if (!sleep_timer)
305 331 queue_post(&ata_queue, 0, NULL);
306 sleeping = true; 332 }
307 mutex_unlock(&ata_mtx);
308 return ret;
309} 333}
310 334
311int ata_hard_reset(void) 335int ata_hard_reset(void)
@@ -433,7 +457,7 @@ void ata_enable(bool on)
433int ata_init(void) 457int ata_init(void)
434{ 458{
435 mutex_init(&ata_mtx); 459 mutex_init(&ata_mtx);
436 460
437 led(false); 461 led(false);
438 462
439 ata_enable(true); 463 ata_enable(true);
@@ -450,8 +474,13 @@ int ata_init(void)
450 if (freeze_lock()) 474 if (freeze_lock())
451 return -4; 475 return -4;
452 476
453 if (ata_spindown(1)) 477 if ( !initialized ) {
454 return -5; 478 queue_init(&ata_queue);
479 create_thread(ata_thread, ata_stack,
480 sizeof(ata_stack), ata_thread_name);
481 tick_add_task(ata_tick);
482 initialized = true;
483 }
455 484
456 ATA_SELECT = SELECT_LBA; 485 ATA_SELECT = SELECT_LBA;
457 ATA_CONTROL = CONTROL_nIEN; 486 ATA_CONTROL = CONTROL_nIEN;
diff --git a/firmware/drivers/ata.h b/firmware/drivers/ata.h
index 23dd1fac58..77c4c2b7bf 100644
--- a/firmware/drivers/ata.h
+++ b/firmware/drivers/ata.h
@@ -33,7 +33,7 @@
33 255 21 min 15 s 33 255 21 min 15 s
34*/ 34*/
35extern void ata_enable(bool on); 35extern void ata_enable(bool on);
36extern int ata_spindown(int time); 36extern void ata_spindown(int seconds);
37extern int ata_sleep(void); 37extern int ata_sleep(void);
38extern int ata_hard_reset(void); 38extern int ata_hard_reset(void);
39extern int ata_soft_reset(void); 39extern int ata_soft_reset(void);