Line 39... |
Line 39... |
#include <linux/bio.h>
|
#include <linux/bio.h>
|
|
|
|
|
#include "sd_card.h"
|
#include "sd_card.h"
|
|
|
#define SDC_DEBUG 1
|
//#define SDC_DEBUG 1
|
|
|
#ifdef SDC_DEBUG
|
#ifdef SDC_DEBUG
|
# define SDC_PRINTK(fmt, args...) printk( KERN_WARNING "sd_card:" fmt, ## args)
|
# define SDC_PRINTK(fmt, args...) printk( KERN_WARNING "sd_card:" fmt, ## args)
|
#else
|
#else
|
# define SDC_PRINTK(fmt, args...)
|
# define SDC_PRINTK(fmt, args...)
|
#endif
|
#endif
|
|
|
#define DRIVER_NAME "sd_card"
|
#define DRIVER_NAME "sd_card"
|
#define SD_CARD_MINORS 8
|
#define SD_CARD_MINORS 8
|
#define SD_CARD_SIZE 1995440128
|
#define SD_CARD_SIZE 1995440128
|
|
//(512*1024*1024)
|
|
//1995440128
|
|
|
static int major = 8;
|
static int major = 8;
|
|
|
|
|
/**
|
/**
|
Line 103... |
Line 105... |
unsigned char data;
|
unsigned char data;
|
unsigned char transError;
|
unsigned char transError;
|
int i;
|
int i;
|
unsigned int buffer_offset = 0;
|
unsigned int buffer_offset = 0;
|
unsigned int blockCnt;
|
unsigned int blockCnt;
|
|
unsigned int start = sector << 9; /* x512*/
|
|
|
SDC_PRINTK("read_sd_block begin: sector=%d, nsect=%d\n", sector, nsect);
|
SDC_PRINTK("read_sd_block begin: sector=%ld, nsect=%ld\n", sector, nsect);
|
|
|
for (blockCnt = 0; blockCnt < nsect; blockCnt++) {
|
for (blockCnt = 0; blockCnt < nsect; blockCnt++) {
|
REG8(sd_vbase + SD_ADDR_7_0_REG) = 0;
|
REG8(sd_vbase + SD_ADDR_7_0_REG) = 0;
|
REG8(sd_vbase + SD_ADDR_15_8_REG) = (unsigned char) ((sector >> 8) & 0xff);
|
REG8(sd_vbase + SD_ADDR_15_8_REG) = (unsigned char) ((start >> 8) & 0xff);
|
REG8(sd_vbase + SD_ADDR_23_16_REG) = (unsigned char) ((sector >> 16) & 0xff);
|
REG8(sd_vbase + SD_ADDR_23_16_REG) = (unsigned char) ((start >> 16) & 0xff);
|
REG8(sd_vbase + SD_ADDR_31_24_REG) = (unsigned char) ((sector >> 24) & 0xff);
|
REG8(sd_vbase + SD_ADDR_31_24_REG) = (unsigned char) ((start >> 24) & 0xff);
|
|
|
REG8(sd_vbase + SD_TRANS_TYPE_REG) = SD_RW_READ_SD_BLOCK;
|
REG8(sd_vbase + SD_TRANS_TYPE_REG) = SD_RW_READ_SD_BLOCK;
|
REG8(sd_vbase + SD_RX_FIFO_CONTROL_REG) = 0x1; /* Clean the RX FIFO */
|
REG8(sd_vbase + SD_RX_FIFO_CONTROL_REG) = 0x1; /* Clean the RX FIFO */
|
REG8(sd_vbase + SD_TRANS_CTRL_REG) = 0x1; /* TRANS_START */
|
REG8(sd_vbase + SD_TRANS_CTRL_REG) = 0x1; /* TRANS_START */
|
|
|
|
|
while (REG8(sd_vbase + SD_TRANS_STS_REG) & 0x1) { /* exit while !TRABS_BUSY */
|
while (REG8(sd_vbase + SD_TRANS_STS_REG) & 0x1) { /* exit while !TRABS_BUSY */
|
;
|
;
|
}
|
}
|
|
|
transError = REG8(sd_vbase + SD_TRANS_ERROR_REG) & 0xc;
|
transError = REG8(sd_vbase + SD_TRANS_ERROR_REG) & 0xc;
|
if ( transError == SD_READ_NO_ERROR) {
|
if ( transError == SD_READ_NO_ERROR) {
|
for (i = 0; i < 512; i++) {
|
for (i = 0; i < 512; i++) {
|
data = REG8(sd_vbase + SD_RX_FIFO_DATA_REG) ;
|
data = REG8(sd_vbase + SD_RX_FIFO_DATA_REG) ;
|
REG8(buffer + buffer_offset + i) = data ;
|
//REG8(buffer + buffer_offset + i) = data ;
|
|
buffer[buffer_offset + i] = data ;
|
|
// printk("%x\t",data);
|
|
// if (i%16 == 0) {
|
|
// printk("\n");
|
|
// }
|
}
|
}
|
|
// printk("\n");
|
buffer_offset += 512;
|
buffer_offset += 512;
|
sector += 512;
|
start += 512;
|
} else {
|
} else {
|
SDC_PRINTK("read_sd_block failed. Re-try\n");
|
SDC_PRINTK("read_sd_block failed. Re-try\n");
|
spiMaster_init(sd_vbase); /* Init again and retry */
|
spiMaster_init(sd_vbase); /* Init again and retry */
|
blockCnt--; /* read the same block again */
|
blockCnt--; /* read the same block again */
|
}
|
}
|
Line 146... |
Line 157... |
{
|
{
|
int i;
|
int i;
|
unsigned char data;
|
unsigned char data;
|
unsigned int blockCnt;
|
unsigned int blockCnt;
|
char *p = buffer;
|
char *p = buffer;
|
|
unsigned int start = sector << 9; /* x512*/
|
|
|
SDC_PRINTK("write_sd_block begin: sector=%d, nsect=%d\n", sector, nsect);
|
|
|
SDC_PRINTK("write_sd_block begin: sector=%ld, nsect=%ld\n", sector, nsect);
|
|
|
for (blockCnt = 0; blockCnt < nsect; blockCnt++) {
|
for (blockCnt = 0; blockCnt < nsect; blockCnt++) {
|
|
|
/* Clean the TX FIFO */
|
/* Clean the TX FIFO */
|
REG8(sd_vbase + SD_TX_FIFO_CONTROL_REG) = 0x1;
|
REG8(sd_vbase + SD_TX_FIFO_CONTROL_REG) = 0x1;
|
|
|
REG8(sd_vbase + SD_ADDR_7_0_REG) = 0;
|
REG8(sd_vbase + SD_ADDR_7_0_REG) = 0;
|
REG8(sd_vbase + SD_ADDR_15_8_REG) = (unsigned char) ((sector >> 8) & 0xff);
|
REG8(sd_vbase + SD_ADDR_15_8_REG) = (unsigned char) ((start >> 8) & 0xff);
|
REG8(sd_vbase + SD_ADDR_23_16_REG) = (unsigned char) ((sector >> 16) & 0xff);
|
REG8(sd_vbase + SD_ADDR_23_16_REG) = (unsigned char) ((start >> 16) & 0xff);
|
REG8(sd_vbase + SD_ADDR_31_24_REG) = (unsigned char) ((sector >> 24) & 0xff);
|
REG8(sd_vbase + SD_ADDR_31_24_REG) = (unsigned char) ((start >> 24) & 0xff);
|
|
|
|
|
// Write data to TX_FIFO_DATA_REG
|
// Write data to TX_FIFO_DATA_REG
|
for (i = 0; i < 512; i++) {
|
for (i = 0; i < 512; i++) {
|
REG8(sd_vbase + SD_TX_FIFO_DATA_REG) = p[i];
|
REG8(sd_vbase + SD_TX_FIFO_DATA_REG) = p[i];
|
}
|
}
|
|
|
|
|
REG8(sd_vbase + SD_TRANS_TYPE_REG) = SD_RW_WRITE_SD_BLOCK;
|
REG8(sd_vbase + SD_TRANS_TYPE_REG) = SD_RW_WRITE_SD_BLOCK;
|
REG8(sd_vbase + SD_TRANS_CTRL_REG) = 1; /* TRANS_START */
|
REG8(sd_vbase + SD_TRANS_CTRL_REG) = 1; /* TRANS_START */
|
|
|
|
udelay(10);
|
while (REG8(sd_vbase + SD_TRANS_STS_REG) & 0x1) { /* exit while !TRABS_BUSY */
|
while (REG8(sd_vbase + SD_TRANS_STS_REG) & 0x1) { /* exit while !TRABS_BUSY */
|
;
|
;
|
}
|
}
|
|
|
data = REG8(sd_vbase + SD_TRANS_ERROR_REG) & 0x30;
|
data = REG8(sd_vbase + SD_TRANS_ERROR_REG) & 0x30;
|
if (data == 1) {
|
if (data == 1) {
|
SDC_PRINTK("WRITE_CMD_ERROR\n\r");
|
printk("sd_card:WRITE_CMD_ERROR\n\r");
|
} else if (data == 2) {
|
} else if (data == 2) {
|
SDC_PRINTK("WRITE_DATA_ERROR\n\r");
|
printk("sd_card:WRITE_DATA_ERROR\n\r");
|
} else if (data == 3) {
|
} else if (data == 3) {
|
SDC_PRINTK("WRITE_BUSY_ERROR\n\r");
|
printk("sd_card:WRITE_BUSY_ERROR\n\r");
|
}
|
}
|
|
|
sector += 512;
|
start += 512;
|
p += 512;
|
p += 512;
|
}
|
}
|
|
|
SDC_PRINTK("write_sd_block done\n");
|
SDC_PRINTK("write_sd_block done\n");
|
return 0;
|
return 0;
|
Line 308... |
Line 320... |
|
|
/*
|
/*
|
* The ioctl() implementation
|
* The ioctl() implementation
|
*/
|
*/
|
|
|
|
static int sd_card_getgeo(struct block_device *bdev,
|
|
struct hd_geometry *geo)
|
|
{
|
|
/*
|
|
* capacity heads sectors cylinders
|
|
* 0~16M 1 1 0~32768
|
|
* 16M~512M 1 32 1024~32768
|
|
* 512M~16G 32 32 1024~32768
|
|
* 16G~... 255 63 2088~...
|
|
*/
|
|
if (SD_CARD_SIZE < 16 * 1024 * 1024) {
|
|
geo->heads = 1;
|
|
geo->sectors = 1;
|
|
|
|
} else if (SD_CARD_SIZE < 512 * 1024 * 1024) {
|
|
geo->heads = 1;
|
|
geo->sectors = 32;
|
|
} else if (SD_CARD_SIZE < 16ULL * 1024 * 1024 * 1024) {
|
|
geo->heads = 32;
|
|
geo->sectors = 32;
|
|
} else {
|
|
geo->heads = 255;
|
|
geo->sectors = 63;
|
|
}
|
|
|
|
geo->cylinders = SD_CARD_SIZE>>9/geo->heads/geo->sectors;
|
|
|
|
return 0;
|
|
}
|
|
|
int sd_card_ioctl (struct inode *inode, struct file *filp,
|
int sd_card_ioctl (struct inode *inode, struct file *filp,
|
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
{
|
{
|
long size;
|
long size;
|
struct hd_geometry geo;
|
struct hd_geometry geo;
|
Line 346... |
Line 388... |
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
.open = sd_card_open,
|
.open = sd_card_open,
|
.release = sd_card_release,
|
.release = sd_card_release,
|
.media_changed = sd_card_media_changed,
|
.media_changed = sd_card_media_changed,
|
.revalidate_disk = sd_card_revalidate,
|
.revalidate_disk = sd_card_revalidate,
|
.ioctl = sd_card_ioctl
|
// .ioctl = sd_card_ioctl,
|
|
.getgeo = sd_card_getgeo
|
};
|
};
|
|
|
/**
|
/**
|
* ============================================================
|
* ============================================================
|
* Driver Entry and clean up
|
* Driver Entry and clean up
|