--- I'm working on creating a raw I/O mechanism for writing data out to an IDE disk. Right now, I'm putting my own request list together with the code below. Note that I'm calling ide_do_drive_cmd(), which isn't the way to do it at _all_, and I'd rather use some other mechanism. Eventually I'll have a function to handle this ...I could call start_request() on my own, but there's the issue if you have other requests in the queue. My ide_raw_read() needs to do the appropriate locking, especially if it wants to call do_rw_disk() ...
My questions are:
1) What's the best "supported" mechanism for doing this? I've already setup the file_operations[] table to use ide_raw_read() for a new register_chrdev() link, and we call ide_raw_read(), and then we set up the request by hand, but should I be using another function, or perhaps calling start_request() on my own?
2) The one problem I have right now is I can't specify the disk offset (which is, of course, a _bad_ thing). This requires using a different front-end to the problem. The do_rw_disk() is a great function for that purpose, but it requires that I setup a number of lock conditions before calling it. If that's the next best alternative, what locks are required in the request path for using that function? (I know it's eventually called via the ide_driver_t path).
--Matt
#if defined(CONFIG_RAW)
#define RAW_SECTOR_SIZE 512
/* * Name: ide_raw_rw() * Func: Perform a raw read/write on an IDE disk. One sector at a time * (for now). */ static ssize_t ide_raw_rw(struct file *filp, char *buf, loff_t *ppos, int mode) { struct request rq; ide_drive_t *drive = (ide_drive_t *)0; unsigned int h, major, unit;
/* make sure we're pointed at a disk */ major = MAJOR(filp->f_dentry->d_inode->i_rdev);
for (h = 0; h < MAX_HWIFS; ++h) { ide_hwif_t *hwif = &ide_hwifs[h]; if (hwif->present && major == hwif->major) { unit = DEVICE_NR(filp->f_dentry->d_inode->i_rdev); if (unit < MAX_DRIVES) { drive = &hwif->drives[unit]; if (!drive->present) { printk("ide_raw_rw(): drive " "not present\n"); return (-1); } break; } else { printk("ide_raw_rw(): unit number beyond " "MAX_DRIVES\n"); return (-1); } } }
/* make sure we get a drive here */ if (!drive) { printk("ide_raw_rw(): no drive found for device " "0x%x [%s]\n", filp->f_dentry->d_inode->i_rdev, bdevname(filp->f_dentry->d_inode->i_rdev)); return (-1); } else { printk("ide_raw_rw(): drive found! [%s]\n", bdevname(filp->f_dentry->d_inode->i_rdev)); }
/* configure the request */ printk("ide_raw_rw(): configuring request ...\n"); ide_init_drive_cmd(&rq); rq.cmd = mode; rq.rq_dev = filp->f_dentry->d_inode->i_rdev; rq.sector = (*ppos / RAW_SECTOR_SIZE); /* XXX - change this! */ rq.current_nr_sectors = rq.nr_sectors = 1; rq.bh = rq.bhtail = (struct buffer_head *)NULL; rq.next = (struct request *)NULL; rq.rq_status = RQ_ACTIVE; rq.buffer = buf; printk("ide_raw_rw(): request configured!\n");
/* send the request */ printk("ide_raw_rw(): sending request ...\n"); ide_do_drive_cmd(drive, &rq, ide_wait); /* XXX - cheezy */ printk("ide_raw_rw(): request sent!\n");
*ppos += RAW_SECTOR_SIZE; return (1); }
/* * Name: ide_raw_read() * Func: Perform a raw read on an IDE disk. */ static ssize_t ide_raw_read(struct file *filp, char *buf, size_t count, loff_t *ppos) { int i;
/* verify we are an increment of a raw sector size */ if (count % RAW_SECTOR_SIZE) { printk(KERN_WARNING "ide_raw_read(): byte count not a " "increment of %d bytes!\n", RAW_SECTOR_SIZE); return (-1); }
/* write out one sector at a time */ for (i = 0; i < count; i += RAW_SECTOR_SIZE) { /* perform the write operation */ if (ide_raw_rw(filp, (char *)&buf[i], ppos, READ) < 0) { /* houston, we have a problem */ printk(KERN_WARNING "ide_raw_read(): " "ide_raw_rw() returned an error!\n"); return (-1); } } return (count); } #endif
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/