📄 mcc4.txt
字号:
code = 0;
break;
}
else
{
mmc_address += hd_hardsectsizes[0];
buffer_address += hd_hardsectsizes[0];
}
}
spin_lock_irq(&io_request_lock);
}
else
{
code = 0;
}
end_request(code);
}
}
static int mmc_open(struct inode *inode, struct file *filp)
{
int device;
(void)filp;
if (mmc_media_detect == 0) return -ENODEV;
#if defined(MODULE)
MOD_INC_USE_COUNT;
#endif
return 0;
}
static int mmc_release(struct inode *inode, struct file *filp)
{
(void)filp;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
#if defined(MODULE)
MOD_DEC_USE_COUNT;
#endif
return 0;
}
extern struct gendisk hd_gendisk;
static int mmc_revalidate(kdev_t dev)
{
int target, max_p, start, i;
if (mmc_media_detect == 0) return -ENODEV;
target = DEVICE_NR(dev);
max_p = hd_gendisk.max_p;
start = target << 6;
for (i = max_p - 1; i >= 0; i--) {
int minor = start + i;
invalidate_device(MKDEV(MAJOR_NR, minor), 1);
hd_gendisk.part[minor].start_sect = 0;
hd_gendisk.part[minor].nr_sects = 0;
}
grok_partitions(&hd_gendisk, target, 1 << 6,
hd_sizes[0] * 2);
return 0;
}
static int mmc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
if (!inode || !inode->i_rdev)
return -EINVAL;
switch(cmd) {
case BLKGETSIZE:
return put_user(hd[MINOR(inode->i_rdev)].nr_sects, (unsigned long *)arg);
case BLKGETSIZE64:
return put_user((u64)hd[MINOR(inode->i_rdev)].
nr_sects, (u64 *) arg);
case BLKRRPART:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return mmc_revalidate(inode->i_rdev);
case HDIO_GETGEO:
{
struct hd_geometry *loc, g;
loc = (struct hd_geometry *) arg;
if (!loc)
return -EINVAL;
g.heads = 4;
g.sectors = 16;
g.cylinders = hd[0].nr_sects / (4 * 16);
g.start = hd[MINOR(inode->i_rdev)].start_sect;
return copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0;
}
default:
return blk_ioctl(inode->i_rdev, cmd, arg);
}
}
static int mmc_card_init(void)
{
unsigned char r = 0;
short i, j;
unsigned long flags;
save_flags(flags);
cli();
printk("mmc Card init\n");
mmc_spi_cs_high();
for (i = 0; i < 20; i++) mmc_spi_io(0xff);
mmc_spi_cs_low();
mmc_spi_io(0x40);
for (i = 0; i < 4; i++) mmc_spi_io(0x00);
mmc_spi_io(0x95);
for (i = 0; i < 8; i++)
{
r = mmc_spi_io(0xff);
if (r == 0x01)
{
// printk("mmc Card init WAS break\n");
break;
}
}
mmc_spi_cs_high();
mmc_spi_io(0xff);
//printk("mmc Card init WAS r=%d\n", r);
if (r != 0x01)
{
restore_flags(flags);
return 1;
}
printk("mmc Card init *1*\n");
for (j = 0; j < 10000; j++)
{
mmc_spi_cs_low();
mmc_spi_io(0x41);
for (i = 0; i < 4; i++) mmc_spi_io(0x00);
mmc_spi_io(0xff);
for (i = 0; i < 8; i++)
{
r = mmc_spi_io(0xff);
if (r == 0x00) break;
}
mmc_spi_cs_high();
mmc_spi_io(0xff);
if (r == 0x00)
{
restore_flags(flags);
printk("mmc Card init *2*\n");
return 0;
}
}
restore_flags(flags);
return 2;
} /* end function mmc_card_init */
static int mmc_card_config(void)
{
unsigned char r = 0;
short i;
unsigned char csd[32];
unsigned int c_size;
unsigned int c_size_mult;
unsigned int mult;
unsigned int read_bl_len;
unsigned int blocknr = 0;
unsigned int block_len = 0;
unsigned int size = 0;
mmc_spi_cs_low();
for (i = 0; i < 4; i++) mmc_spi_io(0xff);
mmc_spi_io(0x49);
for (i = 0; i < 4; i++) mmc_spi_io(0x00);
mmc_spi_io(0xff);
for (i = 0; i < 8; i++)
{
r = mmc_spi_io(0xff);
if (r == 0x00) break;
}
if (r != 0x00)
{
mmc_spi_cs_high();
mmc_spi_io(0xff);
return(1);
}
for (i = 0; i < 8; i++)
{
r = mmc_spi_io(0xff);
if (r == 0xfe) break;
}
if (r != 0xfe)
{
mmc_spi_cs_high();
mmc_spi_io(0xff);
return(2);
}
for (i = 0; i < 16; i++)
{
r = mmc_spi_io(0xff);
csd[i] = r;
}
for (i = 0; i < 2; i++)
{
r = mmc_spi_io(0xff);
}
mmc_spi_cs_high();
mmc_spi_io(0xff);
if (r == 0x00) return(3);
c_size = csd[8] + csd[7] * 256 + (csd[6] & 0x03) * 256 * 256;
c_size >>= 6;
c_size_mult = csd[10] + (csd[9] & 0x03) * 256;
c_size_mult >>= 7;
read_bl_len = csd[5] & 0x0f;
mult = 1;
mult <<= c_size_mult + 2;
blocknr = (c_size + 1) * mult;
block_len = 1;
block_len <<= read_bl_len;
size = block_len * blocknr;
size >>= 10;
for(i=0; i<(1<<6); i++) {
hd_blocksizes[i] = 1024;
hd_hardsectsizes[i] = block_len;
hd_maxsect[i] = 256;
}
hd_sizes[0] = size;
hd[0].nr_sects = blocknr;
printk("Size = %d, hardsectsize = %d, sectors = %d\n",
size, block_len, blocknr);
return 0;
}
static int mmc_hardware_init(void)
{
unsigned int gpio_outen;
// Set inputs/outputs here
printk("mmc Hardware init\n");
gpio_outen = *gpioaddr_enable;
gpio_outen = (gpio_outen | SD_DI | SD_CLK | SD_CS) & ~SD_DO;
*gpioaddr_enable = gpio_outen;
port_state = *gpioaddr_input;
// Clock low
// all low
port_state &= ~(SD_CLK | SD_DI | SD_CS);
*gpioaddr_output = port_state;
return 0;
}
static int mmc_check_media_change(kdev_t dev)
{
(void)dev;
if (mmc_media_changed == 1)
{
mmc_media_changed = 0;
return 1;
}
else return 0;
}
static struct block_device_operations mmc_bdops =
{
open: mmc_open,
release: mmc_release,
ioctl: mmc_ioctl,
#if 0
check_media_change: mmc_check_media_change,
revalidate: mmc_revalidate,
#endif
};
static struct gendisk hd_gendisk = {
major: MAJOR_NR,
major_name: DEVICE_NAME,
minor_shift: 6,
max_p: 1 << 6,
part: hd,
sizes: hd_sizes,
fops: &mmc_bdops,
};
static int mmc_init(void)
{
int rc;
rc = mmc_hardware_init();
if ( rc != 0)
{
printk("mmc: error in mmc_hardware_init (%d)\n", rc);
return -1;
}
rc = mmc_card_init();
if ( rc != 0)
{
// Give it an extra shot
rc = mmc_card_init();
if ( rc != 0)
{
printk("mmc: error in mmc_card_init (%d)\n", rc);
return -1;
}
}
memset(hd_sizes, 0, sizeof(hd_sizes));
rc = mmc_card_config();
if ( rc != 0)
{
printk("mmc: error in mmc_card_config (%d)\n", rc);
return -1;
}
blk_size[MAJOR_NR] = hd_sizes;
memset(hd, 0, sizeof(hd));
hd[0].nr_sects = hd_sizes[0]*2;
blksize_size[MAJOR_NR] = hd_blocksizes;
hardsect_size[MAJOR_NR] = hd_hardsectsizes;
max_sectors[MAJOR_NR] = hd_maxsect;
hd_gendisk.nr_real = 1;
register_disk(&hd_gendisk, MKDEV(MAJOR_NR,0), 1<<6,
&mmc_bdops, hd_sizes[0]*2);
return 0;
}
static void mmc_exit(void)
{
blk_size[MAJOR_NR] = NULL;
blksize_size[MAJOR_NR] = NULL;
hardsect_size[MAJOR_NR] = NULL;
max_sectors[MAJOR_NR] = NULL;
hd[0].nr_sects = 0;
}
static void mmc_check_media(void)
{
int old_state;
int rc;
old_state = mmc_media_detect;
// TODO: Add card detection here
mmc_media_detect = 1;
if (old_state != mmc_media_detect)
{
mmc_media_changed = 1;
if (mmc_media_detect == 1)
{
rc = mmc_init();
if (rc != 0) printk("mmc: error in mmc_init (%d)\n", rc);
}
else
{
mmc_exit();
}
}
/* del_timer(&mmc_timer);
mmc_timer.expires = jiffies + 10*HZ;
add_timer(&mmc_timer); */
}
static int __init mmc_driver_init(void)
{
int rc;
rc = devfs_register_blkdev(MAJOR_NR, DEVICE_NAME, &mmc_bdops);
if (rc < 0)
{
printk(KERN_WARNING "mmc: can't get major %d\n", MAJOR_NR);
return rc;
}
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), mmc_request);
read_ahead[MAJOR_NR] = 8;
add_gendisk(&hd_gendisk);
mmc_check_media();
/*init_timer(&mmc_timer);
mmc_timer.expires = jiffies + HZ;
mmc_timer.function = (void *)mmc_check_media;
add_timer(&mmc_timer);*/
return 0;
}
static void __exit mmc_driver_exit(void)
{
int i;
del_timer(&mmc_timer);
for (i = 0; i < (1 << 6); i++)
fsync_dev(MKDEV(MAJOR_NR, i));
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
del_gendisk(&hd_gendisk);
devfs_unregister_blkdev(MAJOR_NR, DEVICE_NAME);
mmc_exit();
}
module_init(mmc_driver_init);
module_exit(mmc_driver_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -