---------- Forwarded message ----------
From: champ yen <[email protected]>
Date: Wed, Aug 19, 2009 at 11:30 PM
Subject: Re: Re : Re: [Prex-devel] FAT32 support for Prex
To: Richard PANDION <[email protected]>
Hello Richard:
Multi-partitioned Card may be supported. I have tried this in Febuary. I
implemented this by analyzing partition table of a block device first(in
block device driver not fs server). And partition device nodes are built by
block device driver(of course, they are read/write via same driver with
partition's parameters. ex:offset and length). For full multi-partition
support, an official implementation between fs server and primative block
device driver should be implemented.
For further detail, you can refer to the attached file. I'm sorry for
the messy code and the code is ported from S3C2440 demo program. I just
study to understand the major part and make it work under prex.
best regards
champ yen
On Wed, Aug 19, 2009 at 9:26 PM, Richard PANDION <[email protected]>wrote:
> Hi Andrew, hi Champ,
>
>
> I have tested the new FAT32 support on my Beagle Board with my WIP SD/MMC
> device driver and it seems to be OK.
>
>
> I say "seems" since, by default, prex FAT implementation only supports
> non-partitionned devices (i.e., floppy devices or non-floppy devices
> formatted as "big floppies").
>
> As Champ did not remove this limitation in its code, it did not work out of
> the box with my partitionned SD card media.
>
>
> Also, as I hit this problem before (with the original prex code) and
> developped a patch to deal with this issue at that time, I have backported
> my patch against Champ's FAT32 changes and I have been able to access both a
> FAT16 and a FAT32 formatted SD card (single partition).
>
>
> I have attached the 2 files I've changed for reference. The patch is
> against the fat_read_pbp() function. Please note that my patch only allows
> access to a single FAT partition. If the media has more than 1 partition
> on it, the FAT partition MUST be the first one (other partitions are
> ignored).
>
>
> Best regards,
>
>
> RICHARD
>
>
> P.S. : Champ, I have removed the check for validity of FAT Media Descriptor
> in fat_read_bpb() as, per Microsoft documentation: " This dates back to
> the old MS-DOS 1.x media determination and is no longer usually used for
> anything."...
>
>
>
>
> ----- Message d'origine -----
>
> De : Andrew Dennison
>
> Envoyés : 16.08.09 09:02
>
> À : champ yen
>
> Objet : Re: [Prex-devel] FAT32 support for Prex
>
>
> On Tue, Aug 11, 2009 at 9:46 PM, Andrew Dennison wrote:
> > On Sun, Aug 9, 2009 at 12:30 AM, champ yen wrote:
> >> Hello Andrew:
> >> The commented part is removed from original 0.8.1 code base. The fat
> >> infomation is getting by lines before the "Build FAT mount data". I
> >> modified the fatfs implementation just for fun. Therefore, further
> testing
> >> is required. To clean the unnecessary code may be needed. I just
> provides
> >> the code for those who want to add FAT32 support for their
> implementation.
> >> If you want to commit it to SVN, some works must be done first. I'm
> willing
> >> to do it, but it takes some time. Since I do not have much spare time
> now.
> >
> > Hi Champ Yen,
> >
> > I've had a look at this in more detail and most of the changes are
> > safe to commit as they only affect FAT32. I just need to check through
> > the changes in vfsops more carefully.
>
> Hi Champ,
>
> I've just committed fat32 support to git, see:
>
> http://github.com/AndrewD/prex/tree/master
>
> All looks ok but I made some changes to fat_read_bpb() that are only
> compile tested. Is there anyone currently using fat filesystems that
> can test? Note that this filesystem currently doesn't support big
> endian systems.
>
> Andrew
>
>
> ------------------------------------------------------------------------------
> Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
>
> trial. Simplify your report design, integration and deployment - and focus
> on
> what you do best, core application coding. Discover what's new with
> Crystal Reports now. http://p.sf.net/sfu/bobj-july
> _______________________________________________
> Prex-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/prex-devel
>
>
>
>
/*
* card.c - SD Card disk driver
*/
#include <driver.h>
#include <arm/platform/at2440ii.h>
/* #define DEBUG_SDCARD 1 */
//#define DEBUG_SDCARD
#define _USE_DMA0_ 1
#ifdef DEBUG_SDCARD
#define DPRINTF(a) printf a
#else
#define DPRINTF(a)
#endif
//YH 0811#define INICLK 300000
#define INICLK 400000
//#define NORCLK 25000000
#define SDCLK 24000000 //PCLK=49.392MHz
#define MMCCLK 15000000 //PCLK=49.392MHz
#define PCLK 66608640
/* Block size */
#define BSIZE 512
static int card_read(device_t, char *, size_t *, int);
static int card_write(device_t, char *, size_t *, int);
static int card_open(void);
static int card_close(void);
static int card_init(void);
/*
* Driver structure
*/
struct driver card_drv = {
/* name */ "SD card",
/* order */ 6,
/* init */ card_init,
};
/*
* Device I/O table
*/
static struct devio card_io = {
/* open */ NULL,
/* close */ NULL,
/* read */ card_read,
/* write */ card_write,
/* ioctl */ NULL,
/* event */ NULL,
};
static struct timer card_tmr;
static device_t card_dev; /* Device object */
static device_t card_part_dev[4]; /* Device object */
static int part_offset[4];
static struct event card_event;
//static char *img_start;
//static size_t img_size;
static int Wide=0; // 0:1bit, 1:4bit
static int MMC=0; // 0:SD , 1:MMC
static int RCA;
#if !_USE_DMA0_
#define CARD_READ 0
#define CARD_WRITE 1
static unsigned int *read_buf = NULL;
static unsigned int *write_buf = NULL;
static int card_op = 0;
static int op_length = 0;
static int op_count = 0;
#endif
static int chk_cmd_end(int cmd, int be_resp)
{
//0: Timeout
int finish0;
if(!be_resp){
// No response
finish0 = SDICSTA;
while((finish0&0x800)!=0x800) // Check cmd end
finish0 = SDICSTA;
SDICSTA= finish0;// Clear cmd end state
return 1;
}else{
// With response
finish0 = SDICSTA;
// while( !( ((finish0&0x200)==0x200) | ((finish0&0x400)==0x800) )) // Check cmd/rsp end
// while((finish0&0x1800)!=0x1800) //YH 0811 Check cmd end
while( !( ((finish0 & 0x200)==0x200) | ((finish0 & 0x400)==0x400) )) // Check cmd/rsp end
finish0 = SDICSTA;
// Uart_Printf("CMD%d:rSDICSTA=0x%x\n", cmd, rSDICSTA); //YH 0811
// CRC no check, CMD9 is a long Resp. command.
//YH 0624 if(cmd==1 | cmd==9 | cmd==41) // CRC no check
if(cmd==1 | cmd==41){
// Check error
if( (finish0 & 0xf00) != 0xa00 ){
SDICSTA = finish0; // Clear error state
if(((finish0&0x400)==0x400))
return 0; // Timeout error
}
SDICSTA = finish0; // Clear cmd & rsp end state
}else{
// CRC check
// Check error
if( (finish0 & 0x1f00) != 0xa00 ){
DPRINTF(("CMD%d:SDICSTA=0x%x, SDIRSP0=0x%x\n",cmd, SDICSTA, SDIRSP0));
SDICSTA = finish0; // Clear error state
// Timeout error
if(((finish0&0x400)==0x400))
return 0;
}
SDICSTA = finish0;
}
return 1;
}
}
static int chk_dat_end(void)
{
int finish;
finish = SDIDSTA;
// Chek timeout or data end
while( !( ((finish&0x10) == 0x10) | ((finish&0x20) == 0x20) )){
finish = SDIDSTA;
//DPRINTF(("SDIDSTA:0x%x\n", finish));
}
if( (finish&0xfc) != 0x10 ){
DPRINTF(("DATA:finish=0x%x\n", finish));
SDIDSTA = 0xec; // Clear error state
return 0;
}
return 1;
}
static int chk_busy_end(void)
{
int finish;
finish = SDIDSTA;
while( !( ((finish&0x08)==0x08) | ((finish&0x20)==0x20) ))
finish = SDIDSTA;
if( (finish & 0xfc) != 0x08 ){
DPRINTF(("DATA:finish=0x%x\n", finish));
SDIDSTA = 0xf4; //clear error state
return 0;
}
return 1;
}
static void cmd0(void)
{
//-- Make card idle state
SDICARG = 0x0; // CMD0(stuff bit)
SDICCON = (1<<8)|0x40; // No_resp, start, CMD0
//-- Check end of CMD0
chk_cmd_end(0, 0);
SDICSTA = 0x800; // Clear cmd_end(no rsp)
}
static int cmd55(void)
{
//--Make ACMD
SDICARG = (RCA << 16); //CMD7(RCA,stuff bit)
SDICCON = (0x1<<9)|(0x1<<8)|0x77; //sht_resp, wait_resp, start, CMD55
//-- Check end of CMD55
if(!chk_cmd_end(55, 1))
return 0;
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 1;
}
static int cmd13(void)//SEND_STATUS
{
int response0;
SDICARG = (RCA<<16); // CMD13(RCA,stuff bit)
SDICCON = (0x1<<9)|(0x1<<8)|0x4d; // sht_resp, wait_resp, start, CMD13
//-- Check end of CMD13
if(!chk_cmd_end(13, 1))
return 0;
//Uart_Printf("rSDIRSP0=0x%x\n", rSDIRSP0);
if(SDIRSP0 & 0x100)
//Uart_Printf("Ready for Data\n");
// else
//Uart_Printf("Not Ready\n");
response0 = SDIRSP0;
response0 &= 0x3c00;
response0 = response0 >> 9;
//Uart_Printf("Current Status=%d\n", response0);
/*
if(response0==6)
Test_SDI();
*/
SDICSTA=0xa00; // Clear cmd_end(with rsp)
return 1;
}
static int cmd9(void)//SEND_CSD
{
SDICARG = (RCA<<16); // CMD9(RCA,stuff bit)
SDICCON = (0x1<<10)|(0x1<<9)|(0x1<<8)|0x49; // long_resp, wait_resp, start, CMD9
DPRINTF(("\n****CSD register****\n"));
//-- Check end of CMD9
if(!chk_cmd_end(9, 1))
return 0;
DPRINTF((" SDIRSP0=0x%x\n SDIRSP1=0x%x\n SDIRSP2=0x%x\n SDIRSP3=0x%x\n", SDIRSP0, SDIRSP1, SDIRSP2, SDIRSP3));
return 1;
}
static void set_bus(void)
{
SET_BUS:
cmd55(); // Make ACMD
//-- CMD6 implement
SDICARG = Wide<<1; //Wide 0: 1bit, 1: 4bit
SDICCON = (0x1<<9)|(0x1<<8)|0x46; //sht_resp, wait_resp, start, CMD55
if(!chk_cmd_end(6, 1)) // ACMD6
goto SET_BUS;
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
}
static void set_1bit_bus(void)
{
Wide=0;
if(!MMC)
set_bus();
DPRINTF(("\n****1bit bus****\n"));
}
static void set_4bit_bus(void)
{
Wide=1;
set_bus();
DPRINTF(("\n****4bit bus****\n"));
}
static void set_prt(void)
{
//-- Set protection addr.0 ~ 262144(32*16*512)
DPRINTF(("[Set protection(addr.0 ~ 262144) test]\n"));
RECMD28:
//--Make ACMD
SDICARG = 0; // CMD28(addr)
SDICCON=(0x1<<9)|(0x1<<8)|0x5c; //sht_resp, wait_resp, start, CMD28
//-- Check end of CMD28
if(!chk_cmd_end(28, 1))
goto RECMD28;
SDICSTA=0xa00; // Clear cmd_end(with rsp)
}
static void clr_prt(void)
{
//-- Clear protection addr.0 ~ 262144(32*16*512)
//Uart_Printf("[Clear protection(addr.0 ~ 262144) test]\n");
RECMD29:
//--Make ACMD
SDICARG = 0; // CMD29(addr)
SDICCON = (0x1<<9)|(0x1<<8)|0x5d; //sht_resp, wait_resp, start, CMD29
//-- Check end of CMD29
if(!chk_cmd_end(29, 1))
goto RECMD29;
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
}
static int chk_mmc_ocr(void)
{
int i;
//-- Negotiate operating condition for MMC, it makes card ready state
//Negotiation time is dependent on CARD Vendors.
for(i=0;i<100;i++){
SDICARG = 0xffc000; //CMD1(MMC OCR:2.6V~3.6V)
//SDICARG = 0xff8000; //CMD1(SD OCR:2.7V~3.6V)
SDICCON = (0x1<<9)|(0x1<<8)|0x41; //sht_resp, wait_resp, start, CMD1
//-- Check end of CMD1
// if(Chk_CMDend(1, 1) & rSDIRSP0==0x80ffc000) //[31]:Card Power up status bit (busy)
//0xffc000 is Voltage window
// if(Chk_CMDend(1, 1) & rSDIRSP0==0x80ff8000)
//YH 0903 [31]:Card Power up status bit (busy)
if( chk_cmd_end(1, 1) && ((SDIRSP0 >> 16) == 0x80ff) ) {
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 1; // Success
}
}
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 0; // Fail
}
static int chk_sd_ocr(void)
{
int i,j=0;
//-- Negotiate operating condition for SD, it makes card ready state
//If this time is short, init. can be fail.
for(i=0;i<500;i++){
cmd55(); // Make ACMD
SDICARG = 0xff8000; //ACMD41(SD OCR:2.7V~3.6V)
// SDICARG=0xffc000; //ACMD41(MMC OCR:2.6V~3.6V)
SDICCON = (0x1<<9)|(0x1<<8)|0x69;//sht_resp, wait_resp, start, ACMD41
//-- Check end of ACMD41
if( chk_cmd_end(41, 1) & (SDIRSP0 == 0x80ff8000) ) {
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 1; // Success
}
//Delay(200); // Wait Card power up status
for(j = 0; j < 10000; j++);
}
//Uart_Printf("SDIRSP0=0x%x\n",rSDIRSP0);
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 0; // Fail
}
static void card_sel_desel(char sel_desel)
{
//-- Card select or deselect
if(sel_desel){
RECMDS7:
SDICARG = RCA<<16; // CMD7(RCA,stuff bit)
SDICCON = (0x1<<9)|(0x1<<8)|0x47; // sht_resp, wait_resp, start, CMD7
//-- Check end of CMD7
if(!chk_cmd_end(7, 1))
goto RECMDS7;
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
//--State(transfer) check
if( SDIRSP0 & 0x1e00!=0x800 )
goto RECMDS7;
}else{
RECMDD7:
SDICARG = 0<<16; //CMD7(RCA,stuff bit)
SDICCON = (0x1<<8)|0x47; //no_resp, start, CMD7
//-- Check end of CMD7
if(!chk_cmd_end(7, 0))
goto RECMDD7;
SDICSTA=0x800; // Clear cmd_end(no rsp)
}
}
static int
card_isr(int irq)
{
#if _USE_DMA0_
DPRINTF(("dma finish\n"));
sched_wakeup(&card_event);
#else
int status;
int i;
switch(card_op){
case CARD_READ:
status = SDIFSTA;
if( (status&0x200) == 0x200 ){
// Check Last interrupt?
for(i = (status & 0x7f)/4; i> 0; i--){
*(read_buf + op_count) = SDIDAT;
op_count++;
}
// Uart_Printf("status1=0x%x\n", status);
// status=rSDIFSTA&0x200; //If you do like this, rSDIFSTA register will not be updated., YH 040221
SDIFSTA = SDIFSTA&0x200; //Clear Rx FIFO Last data Ready, YH 040221
// Uart_Printf("rSDIFSTA=0x%x\n", rSDIFSTA);
}else if( (status&0x80) == 0x80 ){
// Check Half interrupt?
for(i = 0; i < 8; i++){
*(read_buf + op_count)=SDIDAT;
op_count++;
}
}
//DPRINTF(("card read %d %d\n", op_count, op_length));
if(op_count == op_length)
sched_wakeup(&card_event);
break;
case CARD_WRITE:
SDIDAT=*(write_buf + op_count);
op_count++;
if(op_count == op_length){
sched_wakeup(&card_event);
}
//DPRINTF(("card write %d %d\n", op_count, op_length));
break;
}
#endif
return 0;
}
static int
card_read(device_t dev, char *buf, size_t *nbyte, int blkno)
{
int i;
int block = (*nbyte)/BSIZE;
int offset = 0;
void *kbuf;
size_t nr_read;
if(dev == card_dev){
offset = 0;
}else{
for(i = 0; i < 4; i++){
if(dev == card_part_dev[i]){
offset = part_offset[i];
break;
}
}
}
nr_read = *nbyte;
kbuf = kmem_map(buf, nr_read);
//DPRINTF(("card_read: kbuf=%x block=%d blkno=%x\n", kbuf, block, blkno));
/* Clear command and data status registers */
SDIFSTA = 0xFFFFFFFF;
SDICSTA = 0xFFFFFFFF;
SDIDSTA = 0xFFFFFFFF;
SDIFSTA = SDIFSTA | (1<<16); // FIFO reset
SDICARG = (blkno + offset)*512; // CMD17/18(addr)
RERDCMD:
#if _USE_DMA0_
SDIDCON = SDIDCON | (1<<24); //YH 040227, Burst4 Enable
DISRC(_DMA0_) = (unsigned int)(SDIDAT_ADDR); // SDIDAT
DISRCC(_DMA0_) = (1<<1)+(1<<0); // APB, fix
DIDST(_DMA0_) = (unsigned int)(kbuf + 0x30000000); // Rx_buffer
DIDSTC(_DMA0_) = (0<<1)+(0<<0); // AHB, inc
DCON(_DMA0_) = (1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23)+(1<<22)+(2<<20)+128*block;
//handshake, sync PCLK, TC int, single tx, single service, SDI, H/W request,
//auto-reload off, word, 128blk*num
SDIDCON = (2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<15)|(1<<14)|(2<<12)|block;
DMASKTRIG(_DMA0_) = (0<<2)+(1<<1)+0;
if(block < 2){
// SINGLE_READ
SDICCON = (0x1<<9)|(0x1<<8)|0x51; // sht_resp, wait_resp, dat, start, CMD17
if(!chk_cmd_end(17, 1)) //-- Check end of CMD17
goto RERDCMD;
}else{
// MULTI_READ
SDICCON = (0x1<<9)|(0x1<<8)|0x52; // sht_resp, wait_resp, dat, start, CMD18
if(!chk_cmd_end(18, 1)) //-- Check end of CMD18
goto RERDCMD;
}
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
DPRINTF(("read wait 0x%x\n", SDIDCNT));
sched_sleep(&card_event);
DMASKTRIG(_DMA0_) = (1<<2); //DMA0 stop
DPRINTF(("read finish 0x%x\n", SDIDCNT));
#else
card_op = CARD_READ;
op_length = (*nbyte) / 4; //in word(4 bytes)
op_count = 0;
read_buf = (unsigned int*)kbuf;
SDIDCON = (2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<14)|(2<<12)|(block<<0); //YH 040220
SDIIMSK=5; // Last & Rx FIFO half int.
if(block<2){
// SINGLE_READ
SDICCON = (0x1<<9)|(0x1<<8)|0x51; // sht_resp, wait_resp, dat, start, CMD17
if(!chk_cmd_end(17, 1)) //-- Check end of CMD17
goto RERDCMD;
}else{
// MULTI_READ
SDICCON = (0x1<<9)|(0x1<<8)|0x52; // sht_resp, wait_resp, dat, start, CMD18
if(!chk_cmd_end(18, 1)) //-- Check end of CMD18
goto RERDCMD;
}
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
//DPRINTF(("read wait 0x%x\n", SDIDCNT));
sched_sleep(&card_event);
//DPRINTF(("read finish 0x%x\n", SDIDCNT));
SDIIMSK=0; // All mask
#endif
//-- Check end of DATA
if(!chk_dat_end())
DPRINTF(("dat error\n"));
SDIDCON = SDIDCON&~(7<<12); //YH 040220, Clear Data Transfer mode => no operation, Cleata Data Transfer start
SDIFSTA = SDIFSTA&0x200; //Clear Rx FIFO Last data Ready, YH 040221
SDIDSTA = 0x10; // Clear data Tx/Rx end detect
if(block > 1){
RERCMD12:
//--Stop cmd(CMD12)
SDICARG = 0x0; //CMD12(stuff bit)
SDICCON = (0x1<<9)|(0x1<<8)|0x4c;//sht_resp, wait_resp, start, CMD12
//-- Check end of CMD12
if(!chk_cmd_end(12, 1))
goto RERCMD12;
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
}
/* Cleanup controller */
SDICARG = 0;
SDIDCON = 0;
SDIIMSK = 0;
SDICCON = 0;
return 0;
}
#if 0
static int
card_read(device_t dev, char *buf, size_t *nbyte, int blkno)
{
int i;
size_t size;
int block = (*nbyte)/512;
for(i = 0; i < block; i++){
size = 512;
_card_read(dev, buf+(i*512), &size, blkno+i);
}
return 0;
}
#endif
static int
card_write(device_t dev, char *buf, size_t *nbyte, int blkno)
{
int block = (*nbyte)/BSIZE;
int i;
int offset = 0;
void *kbuf;
size_t nr_read;
if(dev == card_dev){
offset = 0;
}else{
for(i = 0; i < 4; i++){
if(dev == card_part_dev[i]){
offset = part_offset[i];
break;
}
}
}
nr_read = *nbyte;
kbuf = kmem_map(buf, nr_read);
//DPRINTF(("card_write: buf=%x nbyte=%d blkno=%x\n", buf, *nbyte, blkno));
/* Clear command and data status registers */
SDIFSTA = 0xFFFFFFFF;
SDICSTA = 0xFFFFFFFF;
SDIDSTA = 0xFFFFFFFF;
SDIFSTA = SDIFSTA|(1<<16); //YH 040223 FIFO reset
SDICARG = (blkno + offset)*512; // CMD24/25(addr)
REWTCMD:
#if _USE_DMA0_
SDIDCON = SDIDCON|(1<<24); //YH 040227, Burst4 Enable
DISRC(_DMA0_) = (int)(kbuf + 0x30000000); // Tx_buffer
DISRCC(_DMA0_) = (0<<1)+(0<<0); // AHB, inc
DIDST(_DMA0_) = (unsigned int)(SDIDAT_ADDR); // SDIDAT
DIDSTC(_DMA0_) = (1<<1)+(1<<0); // APB, fix
//handshake, sync PCLK, TC int, single tx, single service, SDI, H/W request,
//auto-reload off, word, 128blk*num
DCON(_DMA0_) = (1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23)+(1<<22)+(2<<20)+128*block;
DMASKTRIG(_DMA0_) = (0<<2)+(1<<1)+0; //no-stop, DMA0 channel on, no-sw trigger
SDIDCON = (2<<22)|(1<<20)|(1<<17)|(Wide<<16)|(1<<15)|(1<<14)|(3<<12)|block; //YH 040220
if(block<2){
// SINGLE_WRITE
SDICCON = (0x1<<9)|(0x1<<8)|0x58; //sht_resp, wait_resp, dat, start, CMD24
if(!chk_cmd_end(24, 1)) //-- Check end of CMD24
goto REWTCMD;
}else{
// MULTI_WRITE
SDICCON = (0x1<<9)|(0x1<<8)|0x59; //sht_resp, wait_resp, dat, start, CMD25
if(!chk_cmd_end(25, 1)) //-- Check end of CMD25
goto REWTCMD;
}
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
DPRINTF(("write wait 0x%x\n", SDIDCNT));
sched_sleep(&card_event);
DMASKTRIG(_DMA0_) = (1<<2); //DMA0 stop
DPRINTF(("write finish 0x%x\n", SDIDCNT));
#else
card_op = CARD_WRITE;
op_length = (*nbyte) / 4; //in word(4 bytes)
op_count = 0;
write_buf = (unsigned int*)kbuf;
SDIDCON=(2<<22)|(1<<20)|(1<<17)|(Wide<<16)|(1<<14)|(3<<12)|block; //YH 040220
SDIIMSK=0x10; // Tx FIFO half int.
if(block<2){
// SINGLE_WRITE
SDICCON=(0x1<<9)|(0x1<<8)|0x58; //sht_resp, wait_resp, dat, start, CMD24
if(!chk_cmd_end(24, 1)) //-- Check end of CMD24
goto REWTCMD;
}else{
// MULTI_WRITE
SDICCON=(0x1<<9)|(0x1<<8)|0x59; //sht_resp, wait_resp, dat, start, CMD25
if(!chk_cmd_end(25, 1)) //-- Check end of CMD25
goto REWTCMD;
}
SDICSTA=0xa00; // Clear cmd_end(with rsp)
//DPRINTF(("write wait 0x%x\n", SDIDCNT));
sched_sleep(&card_event);
//DPRINTF(("write finish 0x%x\n", SDIDCNT));
SDIIMSK=0; // All mask
#endif
//-- Check end of DATA
if(!chk_dat_end())
DPRINTF(("dat error\n"));
SDIDCON = SDIDCON&~(7<<12); //YH 040220, Clear Data Transfer mode => no operation, Cleata Data Transfer start
SDIDSTA = 0x10; // Clear data Tx/Rx end
if(block > 1){
//--Stop cmd(CMD12)
REWCMD12:
//rSDIDCON=(1<<18)|(1<<17)|(0<<16)|(1<<12)|(block<<0);
SDIDCON = (1<<18)|(1<<17)|(0<<16)|(1<<14)|(1<<12)|(block<<0); //YH 040220
SDICARG = 0x0; //CMD12(stuff bit)
SDICCON = (0x1<<9)|(0x1<<8)|0x4c; //sht_resp, wait_resp, start, CMD12
//-- Check end of CMD12
if(!chk_cmd_end(12, 1))
goto REWCMD12;
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
//-- Check end of DATA(with busy state)
if(!chk_busy_end())
DPRINTF(("error\n"));
SDIDSTA = 0x08; //! Should be cleared by writing '1'.
}
/* Cleanup controller */
SDICARG = 0;
SDIDCON = 0;
SDIIMSK = 0;
SDICCON = 0;
return 0;
}
static int
card_open(void)
{
return 0;
}
static int
card_close(void)
{
return 0;
}
static void
card_init_partition(void)
{
//create multi-partition
int i;
char dev_name[5] = "card0";
unsigned char *mbr, *ptr;
int part_exist = 0;
size_t mbr_size;
/* TODO: check boot sector to create partition */
#if 1
for(i = 0; i < 4; i++)
part_offset[i] = 0;
mbr = kmem_alloc(BSIZE);
mbr_size = BSIZE;
card_read(card_dev, mbr, &mbr_size, 0);
ptr = mbr + 446;
for(i = 0; i < 4; i++){
part_exist = *(ptr+4) + (*(ptr+5) << 8) + (*(ptr+6) << 16) + (*(ptr+7) << 24);
if(part_exist){
part_offset[i] = *(ptr+8) + (*(ptr+9) << 8) + (*(ptr+10) << 16) + (*(ptr+11) << 24);
dev_name[4] = '0' + i;
card_part_dev[i] = device_create(&card_io, dev_name, DF_BLK);
DPRINTF(("create %s offset=%x\n", dev_name, part_offset[i]));
}
ptr += 16;
}
kmem_free(mbr);
#endif
}
/*
* Initialize
*/
static int
card_init(void)
{
//-- SD controller & card initialize
int i;
char key;
/* Important notice for MMC test condition */
/* Cmd & Data lines must be enabled by pull up resister */
//YH 0816, Org rSDIPRE=PCLK/(2*INICLK)-1; // 400KHz
SDIPRE = PCLK/(INICLK)-1; // 400KHz
DPRINTF( ("Init. SD Freq. is %dHz\n",(PCLK/(SDIPRE+1))) );
// rSDICON=(1<<4)|(1<<1)|1; // Type B, FIFO reset, clk enable
SDICON = (0<<4)|1; // Type A, clk enable
SDIFSTA = SDIFSTA|(1<<16); //YH 040223 FIFO reset
SDIBSIZE = 0x200; // 512byte(128word)
SDIDTIMER = 0x7fffff; // Set timeout count
for(i=0; i<0x1000; i++); // Wait 74SDCLK for MMC card
//Uart_Printf("rSDIRSP0=0x%x\n",rSDIRSP0);
cmd0();
DPRINTF(("\nIn idle\n"));
//-- Check MMC card OCR
if(chk_mmc_ocr()) {
DPRINTF(("\nIn MMC ready\n"));
MMC=1;
goto RECMD2;
}
DPRINTF(("MMC check end!!\n"));
//-- Check SD card OCR
if(chk_sd_ocr()){
DPRINTF(("\nIn SD ready\n"));
}else{
DPRINTF(("\nInitialize fail\nNo Card assertion\n"));
return 0;
}
RECMD2:
//-- Check attaced cards, it makes card identification state
SDICARG = 0x0; // CMD2(stuff bit)
SDICCON = (0x1<<10)|(0x1<<9)|(0x1<<8)|0x42; //lng_resp, wait_resp, start, CMD2
//-- Check end of CMD2
if(!chk_cmd_end(2, 1))
goto RECMD2;
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
DPRINTF(("\nEnd id\n"));
RECMD3:
//--Send RCA
SDICARG = MMC<<16; // CMD3(MMC:Set RCA, SD:Ask RCA-->SBZ)
SDICCON = (0x1<<9)|(0x1<<8)|0x43; // sht_resp, wait_resp, start, CMD3
//-- Check end of CMD3
if(!chk_cmd_end(3, 1))
goto RECMD3;
SDICSTA = 0xa00; // Clear cmd_end(with rsp)
//--Publish RCA
if(MMC) {
RCA=1;
//YH 0812 rSDIPRE=(PCLK/(MMCCLK)+1)-1; // YH 0716, Normal clock=20MHz
SDIPRE=(PCLK/MMCCLK)-1; // YH 0812, Normal clock=20MHz
DPRINTF(("MMC Frequency is %dHz\n",(PCLK/(SDIPRE+1))));
}else{
RCA = ( SDIRSP0 & 0xffff0000 )>>16;
DPRINTF(("RCA=0x%x\n",RCA));
SDIPRE = PCLK/(SDCLK)-1; // Normal clock=25MHz
DPRINTF(("SD Frequency is %dHz\n",(PCLK/(SDIPRE+1))));
} //YH 0716
//--State(stand-by) check
if( SDIRSP0 & 0x1e00!=0x600 ) // CURRENT_STATE check
goto RECMD3;
DPRINTF(("\nIn stand-by\n"));
// rSDIPRE=PCLK/(2*NORCLK)-1; // Normal clock=25MHz
//YH 0716 rSDIPRE=PCLK/(SDCLK)-1; // Normal clock=25MHz
//YH 0716 //Uart_Printf("SD Frequency is %dMHz\n",(PCLK/(rSDIPRE+1)));
card_sel_desel(1); // Select
if(!MMC)
set_4bit_bus();
else
set_1bit_bus();
#ifdef DEBUG
printf("SD disk \n");
#endif
/* Create device object */
card_dev = device_create(&card_io, "card", DF_BLK);
//card_dev = device_create(&card_io, "card0", DF_BLK);
event_init(&card_event, "dma_finish");
{
#if _USE_DMA0_
irq_t dma_irq;
dma_irq = irq_attach(DMA0_IRQ, IPL_BLOCK, 0, &card_isr, NULL);
#else
irq_t card_irq;
card_irq = irq_attach(SDI_IRQ, IPL_BLOCK, 0, &card_isr, NULL);
#endif
}
timer_callout(&card_tmr, 50, &card_init_partition, NULL);
DPRINTF(("Card Initial ok\n"));
ASSERT(card_dev);
return 0;
}
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now. http://p.sf.net/sfu/bobj-july
_______________________________________________
Prex-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/prex-devel