/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2002 by Alan Korr * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include #include "ata.h" #include "kernel.h" #include "led.h" #include "sh7034.h" #include "system.h" #include "debug.h" #define ATA_DATA (*((volatile unsigned short*)0x06104100)) #define ATA_ERROR (*((volatile unsigned char*)0x06100101)) #define ATA_FEATURE ATA_ERROR #define ATA_NSECTOR (*((volatile unsigned char*)0x06100102)) #define ATA_SECTOR (*((volatile unsigned char*)0x06100103)) #define ATA_LCYL (*((volatile unsigned char*)0x06100104)) #define ATA_HCYL (*((volatile unsigned char*)0x06100105)) #define ATA_SELECT (*((volatile unsigned char*)0x06100106)) #define ATA_COMMAND (*((volatile unsigned char*)0x06100107)) #define ATA_STATUS (*((volatile unsigned char*)0x06100107)) #define ATA_CONTROL (*((volatile unsigned char*)0x06200306)) #define ATA_ALT_STATUS ATA_CONTROL #define SELECT_LBA 0x40 #define STATUS_BSY 0x80 #define STATUS_RDY 0x40 #define STATUS_DRQ 0x08 #define STATUS_ERR 0x01 #define CONTROL_nIEN 0x02 #define CONTROL_SRST 0x04 #define CMD_READ_SECTORS 0x20 #define CMD_WRITE_SECTORS 0x30 #define CMD_STANDBY_IMMEDIATE 0xE0 #define CMD_STANDBY 0xE2 #define CMD_SLEEP 0xE6 #define CMD_SECURITY_FREEZE_LOCK 0xF5 static int wait_for_bsy(void) { int timeout = current_tick + HZ*4; while (TIME_BEFORE(current_tick, timeout) && (ATA_ALT_STATUS & STATUS_BSY)) yield(); if (TIME_BEFORE(current_tick, timeout)) { return 1; } else { return 0; /* timeout */ } } static int wait_for_rdy(void) { if (!wait_for_bsy()) return 0; return ATA_ALT_STATUS & STATUS_RDY; } static int wait_for_start_of_transfer(void) { if (!wait_for_bsy()) return 0; return (ATA_ALT_STATUS & (STATUS_BSY|STATUS_DRQ)) == STATUS_DRQ; } static int wait_for_end_of_transfer(void) { if (!wait_for_bsy()) return 0; return (ATA_ALT_STATUS & (STATUS_RDY|STATUS_DRQ)) == STATUS_RDY; } int ata_read_sectors(unsigned long start, unsigned char count, void* buf) { int i; if (!wait_for_rdy()) return -1; led(true); ATA_NSECTOR = count; ATA_SECTOR = start & 0xff; ATA_LCYL = (start >> 8) & 0xff; ATA_HCYL = (start >> 16) & 0xff; ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA; ATA_COMMAND = CMD_READ_SECTORS; for (i=0; i> 8) & 0xff; ATA_HCYL = (start >> 16) & 0xff; ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA; ATA_COMMAND = CMD_WRITE_SECTORS; for (i=0; i 255) return -1; ATA_NSECTOR = time & 0xff; ATA_COMMAND = CMD_STANDBY; } if (!wait_for_rdy()) return -1; return 0; } int ata_hard_reset(void) { PADR &= ~0x0002; sleep(2); PADR |= 0x0002; return wait_for_rdy(); } int ata_soft_reset(void) { ATA_SELECT = SELECT_LBA; ATA_CONTROL = CONTROL_nIEN|CONTROL_SRST; sleep(HZ/20000); /* >= 5us */ ATA_CONTROL = CONTROL_nIEN; sleep(HZ/400); /* >2ms */ return wait_for_rdy(); } int ata_init(void) { led(false); /* activate ATA */ PADR &= ~0x80; if (!ata_hard_reset()) return -1; if (!check_registers()) return -2; if (freeze_lock() < 0) return -4; ATA_SELECT = SELECT_LBA; ATA_CONTROL = CONTROL_nIEN; return 0; }