summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Ankers <dan@weirdo.org.uk>2006-11-21 22:55:39 +0000
committerDaniel Ankers <dan@weirdo.org.uk>2006-11-21 22:55:39 +0000
commite7b025ba10b25bc50ad5a307bb2ec2480242a975 (patch)
treeab50f9619f9a3ce9d7a1cd8237a4169cec9b57b8
parent2502e681135290550a60a95729c50bb39e8243db (diff)
downloadrockbox-e7b025ba10b25bc50ad5a307bb2ec2480242a975.zip
rockbox-e7b025ba10b25bc50ad5a307bb2ec2480242a975.tar.gz
rockbox-e7b025ba10b25bc50ad5a307bb2ec2480242a975.tar.bz2
rockbox-e7b025ba10b25bc50ad5a307bb2ec2480242a975.tar.xz
Initial NAND driver for Sansa. This has had limited testing, and no testing on 6 or 8Gb models
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11567 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/ata-e200.c624
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/ata-target.h44
2 files changed, 600 insertions, 68 deletions
diff --git a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
index 0c37753..98d71c2 100644
--- a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
@@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id$
*
- * Copyright (C) 2006 Daniel Stenberg
+ * Copyright (C) 2006 Daniel Ankers
*
* 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.
@@ -16,106 +16,461 @@
* KIND, either express or implied.
*
****************************************************************************/
-
+/* TODO: Add ATA Callback support */
+#include "lcd.h"
#include "ata.h"
+#include "ata-target.h"
+#include "cpu.h"
+#include "system.h"
+#include <stdio.h>
#include <stdbool.h>
#include <string.h>
+#include "kernel.h"
+#include "thread.h"
+
+#define NOINLINE_ATTR __attribute__((noinline)) /* don't inline the loops */
+#define BLOCK_SIZE (512)
#define SECTOR_SIZE (512)
+#define STATUS_REG (*(volatile unsigned int *)(0x70008204))
+#define REG_1 (*(volatile unsigned int *)(0x70008208))
+#define UNKNOWN (*(volatile unsigned int *)(0x70008210))
+#define BLOCK_SIZE_REG (*(volatile unsigned int *)(0x7000821c))
+#define BLOCK_COUNT_REG (*(volatile unsigned int *)(0x70008220))
+#define REG_5 (*(volatile unsigned int *)(0x70008224))
+#define CMD_REG0 (*(volatile unsigned int *)(0x70008228))
+#define CMD_REG1 (*(volatile unsigned int *)(0x7000822c))
+#define CMD_REG2 (*(volatile unsigned int *)(0x70008230))
+#define RESPONSE_REG (*(volatile unsigned int *)(0x70008234))
+#define SD_STATE_REG (*(volatile unsigned int *)(0x70008238))
+#define REG_11 (*(volatile unsigned int *)(0x70008240))
+#define REG_12 (*(volatile unsigned int *)(0x70008244))
+#define DATA_REG (*(volatile unsigned int *)(0x70008280))
+
+#define DATA_DONE (1 << 12)
+#define CMD_DONE (1 << 13)
+#define ERROR_BITS (0x3f)
+#define FIFO_FULL (1 << 7)
+#define FIFO_EMPTY (1 << 6)
+
+/* SD States */
+#define IDLE 0
+#define READY 1
+#define IDENT 2
+#define STBY 3
+#define TRAN 4
+#define DATA 5
+#define RCV 6
+#define PRG 7
+#define DIS 8
+
+#define FIFO_SIZE 16 /* FIFO is 16 words deep */
+
+/* SD Commands */
+#define GO_IDLE_STATE 0
+#define ALL_SEND_CID 2
+#define SEND_RELATIVE_ADDR 3
+#define SET_DSR 4
+#define SWITCH_FUNC 6
+#define SELECT_CARD 7
+#define DESELECT_CARD 7
+#define SEND_CSD 9
+#define SEND_CID 10
+#define STOP_TRANSMISSION 12
+#define SEND_STATUS 13
+#define GO_INACTIVE_STATE 15
+#define SET_BLOCKLEN 16
+#define READ_SINGLE_BLOCK 17
+#define READ_MULTIPLE_BLOCK 18
+#define WRITE_BLOCK 24
+#define WRITE_MULTIPLE_BLOCK 25
+#define ERASE_WR_BLK_START 32
+#define ERASE_WR_BLK_END 33
+#define ERASE 38
+
+/* Application Specific commands */
+#define SET_BUS_WIDTH 6
+#define SD_APP_OP_COND 41
+
+#define READ_TIMEOUT 5*HZ
+#define WRITE_TIMEOUT 0.5*HZ
+
static unsigned short identify_info[SECTOR_SIZE];
int ata_spinup_time = 0;
long last_disk_activity = -1;
+static bool delayed_write = false;
-void flash_select_chip(int no, int sel)
-{
-
-}
+static unsigned char current_bank = 0; /* The bank that we are working with */
-unsigned char flash_read_data(void)
-{
+static tSDCardInfo card_info[2];
-}
+/* For multi volume support */
+static int current_card = 0;
-void flash_write_data(unsigned char data)
-{
+static struct mutex ata_mtx;
-}
+/* Private Functions */
-void flash_write_cmd(unsigned char cmd)
+bool sd_send_command(unsigned int cmd, unsigned long arg1, unsigned int arg2)
{
-
+ bool result = false;
+ unsigned char cbuf[32];
+ do
+ {
+ CMD_REG0 = cmd;
+ CMD_REG1 = (unsigned int)((arg1 & 0xffff0000) >> 16);
+ CMD_REG2 = (unsigned int)((arg1 & 0xffff));
+ UNKNOWN = arg2;
+ while ((STATUS_REG & CMD_DONE) == 0)
+ {
+ /* Busy wait */
+ }
+ if ((STATUS_REG & ERROR_BITS) == 0)
+ {
+ result = true;
+ } else {
+ snprintf(cbuf, sizeof(cbuf), "%x", (STATUS_REG & ERROR_BITS));
+ lcd_puts(0,10,cbuf);
+ lcd_update();
+ }
+ } while ((STATUS_REG & ERROR_BITS) != 0);
+ return result;
}
-void flash_write_addr(unsigned char addr)
+void sd_read_response(unsigned int *response, int type)
{
-
+ int i;
+ int words; /* Number of 16 bit words to read from RESPONSE_REG */
+ unsigned int response_from_card[9];
+ if(type == 2)
+ {
+ words = 9; /* R2 types are 8.5 16-bit words long */
+ } else {
+ words = 3;
+ }
+
+ for (i = 0; i < words; i++) /* RESPONSE_REG is read MSB first */
+ {
+ response_from_card[i] = RESPONSE_REG; /* Read most significant 16-bit word */
+ }
+
+ switch (type)
+ {
+ case 1:
+ /* Response type 1 has the following structure:
+ Start bit
+ Transmission bit
+ Command index (6 bits)
+ Card Status (32 bits)
+ CRC7 (7 bits)
+ Stop bit
+ */
+ /* TODO: Sanity checks */
+ response[0] = ((response_from_card[0] & 0xff) << 24)
+ + (response_from_card[1] << 8)
+ + ((response_from_card[2] & 0xff00) >> 8);
+ break;
+ case 2:
+ /* Response type 2 has the following structure:
+ Start bit
+ Transmission bit
+ Reserved (6 bits)
+ CSD/CID register (127 bits)
+ Stop bit
+ */
+ response[3] = ((response_from_card[0]&0xff)<<24) +
+ (response_from_card[1]<<8) +
+ ((response_from_card[2]&0xff00)>>8);
+ response[2] = ((response_from_card[2]&0xff)<<24) +
+ (response_from_card[3]<<8) +
+ ((response_from_card[4]&0xff00)>>8);
+ response[1] = ((response_from_card[4]&0xff)<<24) +
+ (response_from_card[5]<<8) +
+ ((response_from_card[6]&0xff00)>>8);
+ response[0] = ((response_from_card[6]&0xff)<<24) +
+ (response_from_card[7]<<8) +
+ ((response_from_card[8]&0xff00)>>8);
+ break;
+ case 3:
+ /* Response type 3 has the following structure:
+ Start bit
+ Transmission bit
+ Reserved (6 bits)
+ OCR register (32 bits)
+ Reserved (7 bits)
+ Stop bit
+ */
+ response[0] = ((response_from_card[0] & 0xff) << 24)
+ + (response_from_card[1] << 8)
+ + ((response_from_card[2] & 0xff00) >> 8);
+ /* Types 4-6 not supported yet */
+ }
}
-void flash_wait_ready(void)
+bool sd_send_acommand(unsigned int cmd, unsigned long arg1, unsigned int arg2)
{
-
+ unsigned int returncode;
+ if (sd_send_command(55, (card_info[current_card].rca)<<16, 1) == false)
+ return false;
+ sd_read_response(&returncode, 1);
+ if (sd_send_command(cmd, arg1, arg2) == false)
+ return false;
+ return true;
}
-int flash_map_sector(int sector, int* chip, int* chip_sector)
+void sd_wait_for_state(tSDCardInfo* card, unsigned int state)
{
-
+ unsigned int response = 0;
+ while(((response >> 9) & 0xf) != state)
+ {
+ sd_send_command(SEND_STATUS, (card->rca) << 16, 1);
+ sd_read_response(&response, 1);
+ /* TODO: Add a timeout and error handling */
+ }
+ SD_STATE_REG = state;
}
-int flash_read_id(int no)
-{
-}
+static void copy_read_sectors(unsigned char* buf, int wordcount)
+ NOINLINE_ATTR ICODE_ATTR;
-int flash_read_sector(int sector, unsigned char* buf,
- unsigned char* oob)
+static void copy_read_sectors(unsigned char* buf, int wordcount)
{
-
+ unsigned int tmp = 0;
+
+ if ( (unsigned long)buf & 1)
+ { /* not 16-bit aligned, copy byte by byte */
+ unsigned char* bufend = buf + wordcount*2;
+ do
+ {
+ tmp = DATA_REG;
+ *buf++ = tmp & 0xff;
+ *buf++ = tmp >> 8;
+ } while (buf < bufend); /* tail loop is faster */
+ }
+ else
+ { /* 16-bit aligned, can do faster copy */
+ unsigned short* wbuf = (unsigned short*)buf;
+ unsigned short* wbufend = wbuf + wordcount;
+ do
+ {
+ *wbuf = DATA_REG;
+ } while (++wbuf < wbufend); /* tail loop is faster */
+ }
}
-int flash_read_sector_oob(int sector, unsigned char* oob)
-{
-
-}
-
-static int flash_get_n_segments(void)
-{
-
-}
+static void copy_write_sectors(const unsigned char* buf, int wordcount)
+ NOINLINE_ATTR ICODE_ATTR;
-static int flash_get_n_phblocks(void)
+static void copy_write_sectors(const unsigned char* buf, int wordcount)
{
-
+ if ( (unsigned long)buf & 1)
+ { /* not 16-bit aligned, copy byte by byte */
+ unsigned short tmp = 0;
+ const unsigned char* bufend = buf + wordcount*2;
+ do
+ {
+ tmp = (unsigned short) *buf++;
+ tmp |= (unsigned short) *buf++ << 8;
+ DATA_REG = tmp;
+ } while (buf < bufend); /* tail loop is faster */
+ }
+ else
+ { /* 16-bit aligned, can do faster copy */
+ unsigned short* wbuf = (unsigned short*)buf;
+ unsigned short* wbufend = wbuf + wordcount;
+ do
+ {
+ lcd_update();
+ DATA_REG = *wbuf;
+ } while (++wbuf < wbufend); /* tail loop is faster */
+ }
}
-static int flash_get_n_sectors_in_block(void)
-{
-
-}
-static int flash_phblock_to_sector(int segment, int block)
+void sd_select_bank(unsigned char bank)
{
-
+ unsigned int response;
+ unsigned char card_data[512];
+ unsigned char* write_buf;
+ int i;
+ tSDCardInfo *card = &card_info[0]; /* Bank selection will only be done on
+ the onboard flash */
+ if (current_bank != bank)
+ {
+ memset(card_data, 0, 512);
+ sd_wait_for_state(card, TRAN);
+ BLOCK_SIZE_REG = 512;
+ BLOCK_COUNT_REG = 1;
+ sd_send_command(35, 0, 0x1c0d); /* CMD35 is vendor specific */
+ sd_read_response(&response, 1);
+ SD_STATE_REG = PRG;
+
+ card_data[0] = bank;
+
+ /* Write the card data */
+ write_buf = card_data;
+ for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE)
+ {
+ /* Wait for the FIFO to be empty */
+ while((STATUS_REG & FIFO_EMPTY) == 0) {} /* Erm... is this right? */
+
+ copy_write_sectors(write_buf, FIFO_SIZE);
+
+ write_buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */
+ }
+
+ while((STATUS_REG & DATA_DONE) == 0) {}
+ current_bank = bank;
+ }
}
-static int flash_is_bad_block(unsigned char* oob)
+void sd_init_device(void)
{
-
+/* SD Protocol registers */
+ unsigned int dummy;
+ int i;
+
+ static unsigned int read_bl_len = 0;
+ static unsigned int c_size = 0;
+ static unsigned int c_size_mult = 0;
+ static unsigned long mult = 0;
+
+ unsigned char carddata[512];
+ unsigned char *dataptr;
+ tSDCardInfo *card = &card_info[0]; /* Init onboard flash only */
+
+/* Initialise card data as blank */
+ card->initialized = false;
+ card->ocr = 0;
+ card->csd[0] = 0;
+ card->csd[1] = 0;
+ card->csd[2] = 0;
+ card->cid[0] = 0;
+ card->cid[1] = 0;
+ card->cid[2] = 0;
+ card->rca = 0;
+
+ card->capacity = 0;
+ card->numblocks = 0;
+ card->block_size = 0;
+ card->block_exp = 0;
+
+/* Enable and initialise controller */
+ GPIOG_ENABLE |= (0x3 << 5);
+ GPIOG_OUTPUT_EN |= (0x3 << 5);
+ GPIOG_OUTPUT_VAL |= (0x3 << 5);
+ outl(inl(0x70000088) & ~(0x4), 0x70000088);
+ outl(inl(0x7000008c) & ~(0x4), 0x7000008c);
+ outl(inl(0x70000080) | 0x4, 0x70000080);
+ outl(inl(0x70000084) | 0x4, 0x70000084);
+ REG_1 = 6;
+ outl(inl(0x70000014) & ~(0x3ffff), 0x70000014);
+ outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014);
+ outl(0x1010, 0x70000034);
+
+ GPIOA_ENABLE |= (1 << 7);
+ GPIOA_OUTPUT_EN &= ~(1 << 7);
+ GPIOD_ENABLE |= (0x1f);
+ GPIOD_OUTPUT_EN |= (0x1f);
+ GPIOD_OUTPUT_VAL |= (0x1f);
+ outl(inl(0x6000600c) | (1 << 14), 0x6000600c);
+ outl(inl(0x60006004) | (1 << 14), 0x60006004);
+ outl(inl(0x60006004) & ~(1 << 14), 0x60006004); /* Reset Controller? */
+ outl(0, 0x6000b000);
+ outl(0, 0x6000a000); /* Init DMA controller? */
+
+/* Init NAND */
+ REG_11 |= (1 << 15);
+ REG_12 |= (1 << 15);
+ REG_12 &= ~(3 << 12);
+ REG_12 |= (1 << 13);
+ REG_11 &= ~(3 << 12);
+ REG_11 |= (1 << 13);
+
+ SD_STATE_REG = TRAN;
+ REG_5 = 0xf;
+
+ sd_send_command(GO_IDLE_STATE, 0, 256);
+ while ((card->ocr & (1 << 31)) == 0) /* Loop until the card is powered up */
+ {
+ sd_send_acommand(SD_APP_OP_COND, 0x100000, 3);
+ sd_read_response(&(card->ocr), 3);
+
+ if (card->ocr == 0)
+ {
+ /* TODO: Handle failure */
+ while (1) {};
+ }
+ }
+
+ sd_send_command(ALL_SEND_CID, 0, 2);
+ sd_read_response(card->cid, 2);
+ sd_send_command(SEND_RELATIVE_ADDR, 0, 1);
+ sd_read_response(&card->rca, 1);
+ card->rca >>= 16; /* The Relative Card Address is the top 16 bits of the
+ 32 bits returned. Whenever it is used, it gets
+ shifted left by 16 bits, so this step could possibly
+ be skipped. */
+
+ sd_send_command(SEND_CSD, card->rca << 16, 2);
+ sd_read_response(card->csd, 2);
+
+ /* Parse disk geometry */
+ /* These calculations come from the Sandisk SD card product manual */
+ read_bl_len = ((card->csd[2] >> 16) & 0xf);
+ c_size = ((card->csd[2] & (0x3ff)) << 2) +
+ ((card->csd[1] & (0xc0000000)) >> 30);
+ c_size_mult = ((card->csd[1] >> 15) & 0x7);
+ mult = (1<<(c_size_mult + 2));
+ card->max_read_bl_len = (1<<read_bl_len);
+ card->block_size = BLOCK_SIZE; /* Always use 512 byte blocks */
+ card->numblocks = (c_size + 1) * mult * (card->max_read_bl_len / 512);
+ card->capacity = card->numblocks * card->block_size;
+
+ REG_1 = 0;
+ sd_send_command(SELECT_CARD, card->rca << 16, 129);
+ sd_read_response(&dummy, 1); /* I don't think we use the result from this */
+ sd_send_acommand(SET_BUS_WIDTH, (card->rca << 16) | 2, 1);
+ sd_read_response(&dummy, 1); /* 4 bit wide bus */
+ sd_send_command(SET_BLOCKLEN, card->block_size, 1);
+ sd_read_response(&dummy, 1);
+ BLOCK_SIZE_REG = card->block_size;
+
+ /* If this card is > 4Gb, then we need to enable bank switching */
+ if(card->numblocks > 0x7a77ff)
+ {
+ SD_STATE_REG = TRAN;
+ BLOCK_COUNT_REG = 1;
+ sd_send_command(SWITCH_FUNC, 0x80ffffef, 0x1c05);
+ sd_read_response(&dummy, 1);
+ /* Read 512 bytes from the card.
+ The first 512 bits contain the status information
+ TODO: Do something useful with this! */
+ dataptr = carddata;
+ for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE)
+ {
+ /* Wait for the FIFO to be full */
+ while((STATUS_REG & FIFO_FULL) == 0) {}
+
+ copy_read_sectors(dataptr, FIFO_SIZE);
+
+ dataptr += (FIFO_SIZE*2); /* Advance one chunk of 16 words */
+ }
+ }
+ mutex_init(&ata_mtx);
}
-int flash_disk_scan(void)
-{
-
-}
+/* API Functions */
-int flash_disk_find_block(int block)
+void ata_led(bool onoff)
{
-
+ (void)onoff;
}
-int flash_disk_read_sectors(unsigned long start,
- int count,
- void* buf)
+/* write the delayed sector to volume 0 */
+extern void ata_flush(void)
{
}
@@ -125,21 +480,161 @@ int ata_read_sectors(IF_MV2(int drive,)
int incount,
void* inbuf)
{
-
+ int ret = 0;
+ long timeout;
+ int count;
+ void* buf;
+ long spinup_start;
+ unsigned int dummy;
+ unsigned int response;
+ unsigned int i;
+ tSDCardInfo *card = &card_info[current_card];
+
+ /* TODO: Add DMA support. */
+
+#ifdef HAVE_MULTIVOLUME
+ (void)drive; /* unused for now */
+#endif
+ mutex_lock(&ata_mtx);
+
+ last_disk_activity = current_tick;
+ spinup_start = current_tick;
+
+ ata_led(true);
+
+ timeout = current_tick + READ_TIMEOUT;
+
+ /* TODO: Select device */
+ if(current_card == 0)
+ {
+ if(start > 0x7a77ff)
+ {
+ sd_select_bank(1);
+ start-=0x7a77ff;
+ } else {
+ sd_select_bank(0);
+ }
+ }
+
+ buf = inbuf;
+ count = incount;
+ while (TIME_BEFORE(current_tick, timeout)) {
+ ret = 0;
+ last_disk_activity = current_tick;
+
+ SD_STATE_REG = TRAN;
+ BLOCK_COUNT_REG = count;
+ sd_send_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, 0x1c25);
+ sd_read_response(&dummy, 1);
+ /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */
+
+ for (i = 0; i < count * card->block_size / 2; i += FIFO_SIZE)
+ {
+ /* Wait for the FIFO to be full */
+ while((STATUS_REG & FIFO_FULL) == 0) {}
+
+ copy_read_sectors(buf, FIFO_SIZE);
+
+ buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */
+
+ /* TODO: Switch bank if necessary */
+
+ last_disk_activity = current_tick;
+ }
+ udelay(75);
+ sd_send_command(STOP_TRANSMISSION, 0, 1);
+ sd_read_response(&dummy, 1);
+
+ response = 0;
+ sd_wait_for_state(card, TRAN);
+ break;
+ }
+ ata_led(false);
+
+ mutex_unlock(&ata_mtx);
+
+ /* only flush if reading went ok */
+ if ( (ret == 0) && delayed_write )
+ ata_flush();
+
+ return ret;
}
+
int ata_write_sectors(IF_MV2(int drive,)
unsigned long start,
int count,
const void* buf)
{
- (void)start;
- (void)count;
- (void)buf;
- return -1;
+/* Write support is not finished yet */
+/* TODO: The standard suggests using ACMD23 prior to writing multiple blocks
+ to improve performance */
+ unsigned int response;
+ void const* write_buf;
+ int ret = 0;
+ unsigned int i;
+ long timeout;
+ tSDCardInfo *card = &card_info[current_card];
+
+ mutex_lock(&ata_mtx);
+ ata_led(true);
+ if(current_card == 0)
+ {
+ if(start <= 0x7a77ff)
+ {
+ sd_select_bank(0);
+ } else {
+ sd_select_bank(1);
+ start -= 0x7a77ff;
+ }
+ }
+
+retry:
+ sd_wait_for_state(card, TRAN);
+ BLOCK_COUNT_REG = count;
+ sd_send_command(WRITE_MULTIPLE_BLOCK, start * SECTOR_SIZE, 0x1c2d);
+ sd_read_response(&response, 1);
+ write_buf = buf;
+ for (i = 0; i < count * card->block_size / 2; i += FIFO_SIZE)
+ {
+ if(i >= (count * card->block_size / 2)-FIFO_SIZE)
+ {
+ /* Set SD_STATE_REG to PRG for the last buffer fill */
+ SD_STATE_REG = PRG;
+ }
+
+ /* Wait for the FIFO to be empty */
+ while((STATUS_REG & FIFO_EMPTY) == 0) {}
+ /* Perhaps we could use bit 8 of card status (READY_FOR_DATA)? */
+
+ copy_write_sectors(write_buf, FIFO_SIZE);
+
+ write_buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */
+ /* TODO: Switch bank if necessary */
+
+ last_disk_activity = current_tick;
+ }
+
+ timeout = current_tick + WRITE_TIMEOUT;
+
+ while((STATUS_REG & DATA_DONE) == 0) {
+ if(current_tick >= timeout)
+ {
+ sd_send_command(STOP_TRANSMISSION, 0, 1);
+ sd_read_response(&response, 1);
+ goto retry;
+ }
+ }
+ sd_send_command(STOP_TRANSMISSION, 0, 1);
+ sd_read_response(&response, 1);
+
+ sd_wait_for_state(card, TRAN);
+ mutex_unlock(&ata_mtx);
+ ata_led(false);
+ return ret;
}
-/* schedule a single sector write, executed with the the next spinup
+/* schedule a single sector write, executed with the the next spinup
(volume 0 only, used for config sector) */
extern void ata_delayed_write(unsigned long sector, const void* buf)
{
@@ -147,12 +642,6 @@ extern void ata_delayed_write(unsigned long sector, const void* buf)
(void)buf;
}
-/* write the delayed sector to volume 0 */
-extern void ata_flush(void)
-{
-
-}
-
void ata_spindown(int seconds)
{
(void)seconds;
@@ -189,10 +678,11 @@ void ata_enable(bool on)
unsigned short* ata_get_identify(void)
{
-
+ return identify_info;
}
int ata_init(void)
{
+ sd_init_device();
return 0;
}
diff --git a/firmware/target/arm/sandisk/sansa-e200/ata-target.h b/firmware/target/arm/sandisk/sansa-e200/ata-target.h
index 67a01ed..dfdd3fe 100644
--- a/firmware/target/arm/sandisk/sansa-e200/ata-target.h
+++ b/firmware/target/arm/sandisk/sansa-e200/ata-target.h
@@ -1 +1,43 @@
-/* nothing here yet */
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 by Daniel Ankers
+ *
+ * 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_TARGET_H
+#define ATA_TARGET_H
+
+#include "inttypes.h"
+
+typedef struct
+{
+ bool initialized;
+
+ unsigned int ocr; /* OCR register */
+ unsigned int csd[4]; /* CSD register */
+ unsigned int cid[4]; /* CID register */
+ unsigned int rca;
+
+ uint64_t capacity; /* size in bytes */
+ unsigned long numblocks; /* size in flash blocks */
+ unsigned int block_size; /* block size in bytes */
+ unsigned int max_read_bl_len;/* max read data block length */
+ unsigned int block_exp; /* block size exponent */
+} tSDCardInfo;
+
+tSDCardInfo *sd_card_info(int card_no);
+bool sd_touched(void);
+
+#endif