diff options
author | Björn Stenberg <bjorn@haxx.se> | 2002-04-21 22:06:12 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2002-04-21 22:06:12 +0000 |
commit | 1acfd6b39d30a52c670263db50468590b8661f58 (patch) | |
tree | f5fd00e8bc5edc5b2934d8cfbfc48233d55ead85 | |
parent | 78e6bb8ee25ed3215b010f402a0af849b7f7d25c (diff) |
Alan's ATA code, or what's left of it after I have laid my grubby little hands
on it. :-) It compiles, but it probably doesn't work...
Also, a stub for future kernel code. A sleep() and a dummy yield(), just so we
can start to use them in other code.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@163 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/Makefile | 2 | ||||
-rw-r--r-- | firmware/ata.c | 242 | ||||
-rw-r--r-- | firmware/ata.h | 32 | ||||
-rw-r--r-- | firmware/fat.c | 2 | ||||
-rw-r--r-- | firmware/kernel.c | 35 | ||||
-rw-r--r-- | firmware/kernel.h | 36 |
6 files changed, 348 insertions, 1 deletions
diff --git a/firmware/Makefile b/firmware/Makefile index 636f48094a..22f342a259 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -27,6 +27,8 @@ AFLAGS += -small -relax SRC := $(wildcard *.c) OBJS := $(SRC:%.c=%.o) +OBJS := button.o chartables.o lcd.o led.o serial.o system.o ata.o kernel.o + %.o: %.s $(CC) -o $@ $(CFLAGS) $(INCLUDES) $(DEFS) -c $< diff --git a/firmware/ata.c b/firmware/ata.c new file mode 100644 index 0000000000..460808a217 --- /dev/null +++ b/firmware/ata.c @@ -0,0 +1,242 @@ +/*************************************************************************** + * __________ __ ___. + * 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 "ata.h" +#include "kernel.h" +#include "led.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 ATA_COMMAND +#define ATA_CONTROL (*((volatile unsigned char*)0x06100306)) + +#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) +{ + char timeout = current_tick + HZ; + while (TIME_BEFORE(current_tick, timeout) && (ATA_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_STATUS & STATUS_RDY; +} + +static int wait_for_start_of_transfer(void) +{ + if (!wait_for_bsy()) + return 0; + return (ATA_STATUS & (STATUS_RDY|STATUS_DRQ)) == (STATUS_RDY|STATUS_DRQ); +} + +static int wait_for_end_of_transfer(void) +{ + if (!wait_for_bsy()) + return 0; + return (ATA_STATUS & (STATUS_RDY|STATUS_DRQ)) == STATUS_RDY; +} + +int ata_read_sectors(unsigned long start, + unsigned char count, + unsigned short* buf) +{ + int i; + + if (!wait_for_rdy()) + return 0; + + led_turn_on(); + + 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<count; i++) { + int j; + if (!wait_for_start_of_transfer()) + return 0; + + for (j=0; j<256; j++) + buf[j] = SWAB16(ATA_DATA); + } + + led_turn_off(); + + return wait_for_end_of_transfer(); +} + +int ata_write_sectors(unsigned long start, + unsigned char count, + unsigned short* buf) +{ + int i; + + if (!wait_for_rdy()) + return 0; + + led_turn_on (); + + 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_WRITE_SECTORS; + + for (i=0; i<count; i++) { + int j; + if (!wait_for_start_of_transfer()) + return 0; + + for (j=0; j<256; j++) + ATA_DATA = SWAB16(buf[j]); + } + + led_turn_off (); + + return wait_for_end_of_transfer(); +} + +static int check_registers(void) +{ + if ( ATA_STATUS & STATUS_BSY ) + return 0; + + ATA_NSECTOR = 0xa5; + ATA_SECTOR = 0x5a; + ATA_LCYL = 0xaa; + ATA_HCYL = 0x55; + + if ((ATA_NSECTOR == 0xa5) && + (ATA_SECTOR == 0x5a) && + (ATA_LCYL == 0xaa) && + (ATA_HCYL == 0x55)) + return 1; + else + return 0; +} + +static int check_harddisk(void) +{ + if (!wait_for_rdy()) + return 0; + + if ((ATA_NSECTOR == 1) && + (ATA_SECTOR == 1) && + (ATA_LCYL == 0) && + (ATA_HCYL == 0) && + (ATA_SELECT == 0)) + return 1; + else + return 0; +} + +static int freeze_lock(void) +{ + if (!wait_for_rdy()) + return -1; + + ATA_COMMAND = CMD_SECURITY_FREEZE_LOCK; + + if (!wait_for_rdy()) + return -1; + + return 0; +} + +int ata_hard_reset(void) +{ + clear_bit(1,PADR); + sleep(HZ/500); + + set_bit(1,PADR); + sleep(HZ/500); + + 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_turn_off(); + + /* activate ATA */ + PADR |= 0x80; + + if (!ata_hard_reset()) + return -1; + + if (!check_registers()) + return -2; + + if (!check_harddisk()) + return -3; + + if (!freeze_lock()) + return -4; + + ATA_SELECT = SELECT_LBA; + ATA_CONTROL = CONTROL_nIEN; + + return 0; +} diff --git a/firmware/ata.h b/firmware/ata.h new file mode 100644 index 0000000000..de94803b3b --- /dev/null +++ b/firmware/ata.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * __________ __ ___. + * 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. + * + ****************************************************************************/ +#ifndef __ATA_H__ +#define __ATA_H__ + +extern int ata_hard_reset(void); +extern int ata_soft_reset(void); +extern int ata_init(void); +extern int ata_read_sectors(unsigned long start, + unsigned char count, + unsigned short* buf); +extern int ata_write_sectors(unsigned long start, + unsigned char count, + unsigned short* buf); + +#endif diff --git a/firmware/fat.c b/firmware/fat.c index bd6ec78426..58f4f36bac 100644 --- a/firmware/fat.c +++ b/firmware/fat.c @@ -96,12 +96,12 @@ struct disk_info di; extern int yyparse(void); +#ifdef TEST_FAT void prompt(void) { printf("C:%s>", current_directory); } -#ifdef TEST_FAT int main(int argc, char *argv[]) { struct bpb bpb; diff --git a/firmware/kernel.c b/firmware/kernel.c new file mode 100644 index 0000000000..012ff94c73 --- /dev/null +++ b/firmware/kernel.c @@ -0,0 +1,35 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Björn Stenberg + * + * 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 "kernel.h" + +long current_tick = 0; + +void sleep(int ticks) +{ + int timeout = current_tick + ticks; + + /* always yield at least once */ + do { + yield(); + } while (TIME_BEFORE( current_tick, timeout )); +} + +void yield(void) +{ +} diff --git a/firmware/kernel.h b/firmware/kernel.h new file mode 100644 index 0000000000..60e8ad6db1 --- /dev/null +++ b/firmware/kernel.h @@ -0,0 +1,36 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Björn Stenberg + * + * 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. + * + ****************************************************************************/ +#ifndef _KERNEL_H_ +#define _KERNEL_H_ + +/* wrap-safe macros for tick comparison */ +#define TIME_AFTER(a,b) ((long)(b) - (long)(a) < 0) +#define TIME_BEFORE(a,b) TIME_AFTER(b,a) + +#define HZ 100 /* number of ticks per second */ + +/* global tick variable */ +extern long current_tick; + +/* kernel functions */ +extern void yield(void); +extern void sleep(int ticks); + + +#endif |