IDE Driver (Raw Interface) Questions

Matt Robinson (yakker@cthulhu.engr.sgi.com)
Mon, 20 Dec 1999 01:26:47 -0800 (PST)


I have questions regarding character devices for IDE drives. I've
tried asking Andre Hedrick, but he hasn't responded, and is probably
busy with other things -- no big deal. So I'll send out my questions
to the community. I'll immediately claim I have no extended
knowledge of the IDE drivers, and I've just been reading through the
code and evaluating how it works. :)

---
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/