| #include <linux/kernel.h> |
| #include <linux/sched.h> |
| #include <linux/fs.h> |
| #include <linux/hdreg.h> |
| #include <linux/errno.h> |
| |
| #include <asm/segment.h> |
| |
| #include "../blk.h" |
| #include "scsi.h" |
| #include "scsi_ioctl.h" |
| #include "hosts.h" |
| #include "sd.h" |
| |
| extern int revalidate_scsidisk(int, int); |
| |
| int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) |
| { |
| int dev = inode->i_rdev; |
| int host, error; |
| int diskinfo[4]; |
| struct hd_geometry *loc = (struct hd_geometry *) arg; |
| |
| switch (cmd) { |
| case HDIO_REQ: /* Return BIOS disk parameters */ |
| if (!loc) return -EINVAL; |
| error = verify_area(VERIFY_WRITE, loc, sizeof(*loc)); |
| if (error) |
| return error; |
| host = rscsi_disks[MINOR(dev) >> 4].device->host_no; |
| diskinfo[0] = 0; |
| diskinfo[1] = 0; |
| diskinfo[2] = 0; |
| if(scsi_hosts[host].bios_param != NULL) |
| scsi_hosts[host].bios_param(rscsi_disks[MINOR(dev) >> 4].capacity, |
| dev, |
| &diskinfo[0]); |
| put_fs_byte(diskinfo[0], |
| (char *) &loc->heads); |
| put_fs_byte(diskinfo[1], |
| (char *) &loc->sectors); |
| put_fs_word(diskinfo[2], |
| (short *) &loc->cylinders); |
| put_fs_long(sd[MINOR(inode->i_rdev)].start_sect, |
| (long *) &loc->start); |
| return 0; |
| case BLKGETSIZE: /* Return device size */ |
| if (!arg) return -EINVAL; |
| error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); |
| if (error) |
| return error; |
| put_fs_long(sd[MINOR(inode->i_rdev)].nr_sects, |
| (long *) arg); |
| return 0; |
| case BLKFLSBUF: |
| if(!suser()) return -EACCES; |
| if(!inode->i_rdev) return -EINVAL; |
| fsync_dev(inode->i_rdev); |
| invalidate_buffers(inode->i_rdev); |
| return 0; |
| |
| case BLKRRPART: /* Re-read partition tables */ |
| return revalidate_scsidisk(dev, 1); |
| default: |
| return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device , cmd, (void *) arg); |
| } |
| } |