Linux Lower block device driver

Source: Internet
Author: User

A block device cannot be accessed as a character device, but instead is placed in a queue and then executed after tuning the order, which is called an "elevator scheduling algorithm".

This article explains how to write block device drivers through RAMDisk, NAND flash, nor flash.

First, RAMDisk

1. Because the block device driver is executed after the request is placed in the queue and then adjusted sequentially, we need to define the request queue first:

StaticUnsignedChar*Ramblock_buf;ramblock_buf=Kzalloc (ramblock_size, gfp_kernel);StaticDefine_spinlock (ramblock_lock);structrequest_queue_t *ramblock_queue = Blk_init_queue (Do_ramblock_request,&ramblock_lock);//provides read and write functions and spin locksStatic voidDo_ramblock_request (request_queue_t *q) {     structRequest *req;  while(req = = elv_next_request (q)! =NULL)) {unsignedLongoffset = Req->sector * +; unsignedLongLen = req->current_nr_sectors * +; if(Rq_data_dir (req) = =READ) {memcpy (req->buffer,ramblock_buf+offset, Len); } Else{memcpy (ramblock_buf+offset, req->buffer, Len); } end_request (req,1); }}

The main members of the request structure are:
sector_t sector; The first sector that has not yet been transferred
unsigned long nr_sectors; number of sectors yet to be completed
unsigned int current_nr_sectors; Number of sectors to be completed in the current I/O operation
These 3 members are often dealt with in the drive, and the 3 members play a significant role in the kernel and driver interactions. They are a sector with a size of 512 bytes, and if the sector size of the hardware is not 512 bytes, it needs to be adjusted accordingly. For example, if the sector size of the hardware is 2048 bytes, you need to use 4来 in addition to the starting sector code before the hardware operation.

2. Register the block device and let the system automatically assign the main device number to us:

Static int  = Register_blkdev (0,"ramblock");

3. Construct the Block_device_operations structure:

#defineRamblock_size (1024*1024)structBlcok_device_operations = Rameblcok_fops ={. Owner=this_module,. Getgeo=Ramblock_getgeo,};Static intRamblock_getgeo (structBlock_device *bdev,structHd_geometry *Geo) {    /*capacity =heads*cylinders*sectors*512*/Geo->heads =2; Geo->cylinders = +; Geo->sectors = ramblock_size/2/ +/ +; return 0;}

4. Assign Settings Gendisk structure:

struct gendisk *ramblock_disk = Alloc_disk (+); /*  */ramblock_disk->major = majorramblock_disk0; sprintf ( Ramblcok_disk"ramblock"); Ramblcok_disk->fops = &  Ramblcok_fops;set_capacity (Ramblock_disk, ramblock_size); Add_disk (ramblock_disk);

5. Test:

(1) Insmod Ramblock.ko
(2) ls/dev/ramblock* information is as follows: BRW-RW----1 0 0 254, 0 Jan 1 02:26/dev/ramblock (3) partition: Fdisk/dev/rambloc K
Input: M to view help information
Input: n is used to create a new partition
Input: P is used to establish the primary partition
Then follow the prompts to create the partition two, NAND flash1. Defines the s3c2440 NAND Flash control Register structure:
structS3c_nand_regs {unsignedLongnfconf; unsignedLongNfcont; unsignedLongNfcmd; unsignedLongnfaddr; unsignedLongNfdata; unsignedLongnfeccd0; unsignedLongNFECCD1; unsignedLongNFECCD; unsignedLongNfstat; unsignedLongNfestat0; unsignedLongNFESTAT1; unsignedLongnfmecc0; unsignedLongnfmecc1; unsignedLongNFSECC; unsignedLongnfsblk; unsignedLongnfeblk;};Static structS3c_nand_regs *S3c_nand_regs;s3c_nand_regs= Ioremap (0x4e000000,sizeof(structS3c_nand_regs));

2. Manually define the partition:

Static structMtd_partition s3c_nand_parts[] = {    [0] ={. Name="bootloader",. Size=0x00040000,. Offset=0,    },    [1] ={. Name="params",. Offset=mtdpart_ofs_append,. Size=0x00020000,    },    [2] ={. Name="Kernel",. Offset=mtdpart_ofs_append,. Size=0x00200000,    },    [3] ={. Name="Root",. Offset=mtdpart_ofs_append,. Size=Mtdpart_siz_full,}};

3. Enable the clock of the NAND flash controller to be s3c2440:

structCLK *CLK = Clk_get (NULL,"NAND"); clk_enable (CLK);/*Hclk=100mhz * Tacls: How long after issuing the Cle/ale nwe signal, from the NAND manual that Cle/ale and NWE can be issued simultaneously, so tacls=0 * twrph0:nwe pulse width, hclk X (TWRPH0 + 1), from the NAND manual to know it to >=12ns, so twrph0>=1 * twrph1:nwe to high-level after the Cle/ale to become low, from the NAND manual know it to >=5ns, so t Wrph1>=0*/#defineTacls 0#defineTWRPH0 1#defineTWRPH1 0S3c_nand_regs->nfconf = (tacls<< A) | (twrph0<<8) | (twrph1<<4); /*Nfcont: * bit1-set to 1, cancel chip select * bit0-set to 1, enable NAND Flash controller*/S3c_nand_regs->nfcont = (1<<1) | (1<<0);

4. Assign the nand_chip and Mtd_info structures and initialize them:

structNand_chip *s3c_nand = Kzmalloc (sizeof(structnand_chip), gfp_kernel);structMtd_info *S3C_MTD = Kzmalloc (sizeof(structmtd_info), gfp_kernel); S3c_nand->select_chip =S3c2440_select_chip;s3c_nand->cmd_ctrl =S3c2440_cmd_ctrl;s3c_nand->io_addr_r = &s3c_nand_regs->Nfdata;s3c_nand->io_addr_w = &s3c_nand_regs->Nfdata;s3c_nand->dev_ready =S3c2440_dev_ready;s3c_nand->ecc.mode =NAND_ECC_SOFT;S3C_MTD->owner =THIS_MODULE;S3C_MTD->priv =S3c_nand;nand_scan (S3C_MTD,1);//identify NAND flashAdd_mtd_partitions (S3C_MTD, S3c_nand_parts,4);Static voidS3c2440_select_chip (structMtd_info *MTD,intCHIPNR) {     if(CHIPNR = =-1)     {          /*uncheck: nfcont[1] set to 1*/S3c_nand_regs->nfcont |= (1<<1); }     Else     {          /*check: nfcont[1] set to 0*/S3c_nand_regs->nfcont &= ~ (1<<1); }}/** When the ale for high-level transmission is the address, * when the CLE for high power transmission is the command * when Ale and CLE are low-power transmission is the data */Static voidS3c2440_cmd_ctrl (structMtd_info *MTD,intDAT, unsignedintctrl) {     if(Ctrl &nand_cle) {          /*outgoing command: Nfcmmd=dat*/S3c_nand_regs->nfcmd =dat; }     Else     {          /*send address: Nfaddr=dat*/S3c_nand_regs-&GT;NFADDR =dat; }}Static intS3c2440_dev_ready (structMtd_info *MTD) {     return(S3c_nand_regs->nfstat & (1<<0));}

5. Test:

Using mtd-utils-05.07.23.tar.bz2

Third, Nor Flash

1. Assign Map_info and mtd_info structures and initialize them:

Static struct map_info *s3c_nor_map; Static struct mtd_info *= kzalloc (sizeof(struct map_info), Gfp_kernel);
/* Settings: bit width, physical base address, virtual base addresses, size */

S3c_nor_map->name = "S3c_nor";
S3c_nor_map->phys = 0;
S3c_nor_map->size = 0x1000000; /* >= nor true size */
S3c_nor_map->bankwidth = 2;
S3c_nor_map->virt = Ioremap (S3c_nor_map->phys, s3c_nor_map->size);

Simple_map_init (S3C_NOR_MAP);//The function of reading and erasing is set.

2. Manual partitioning:

Static structMtd_partition s3c_nor_parts[] = {    [0] ={. Name="Bootloader_nor",. Size=0x00040000,. Offset=0,    },    [1] ={. Name="Root_nor",. Offset=mtdpart_ofs_append,. Size=Mtdpart_siz_full,}};

3. Probing NOR Flash:

/*probing nor Flash with the CFI protocol*/S3C_NOR_MTD= Do_map_probe ("Cfi_probe", s3c_nor_map);if(!S3C_NOR_MTD) {    /*probing nor Flash using the JEDEC protocol*/S3C_NOR_MTD= Do_map_probe ("Jedec_probe", S3c_nor_map);}if(!S3C_NOR_MTD) {Iounmap (S3c_nor_map-virt);    Kfree (S3C_NOR_MAP); return-EIO;} Add_mtd_partitions (S3C_NOR_MTD, S3c_nor_parts,2);

4. Test:

Using mtd-utils-05.07.23.tar.bz2

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.