Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | /* * drivers/scsi/sd_ioctl.c * * ioctl handling for SCSI disks */ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/hdreg.h> #include <linux/errno.h> #include <asm/uaccess.h> #define MAJOR_NR SCSI_DISK0_MAJOR #include <linux/blk.h> #include "scsi.h" #include <scsi/scsi_ioctl.h> #include "hosts.h" #include "sd.h" #include <scsi/scsicam.h> /* must follow "hosts.h" */ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { kdev_t dev = inode->i_rdev; int error; struct Scsi_Host * host; Scsi_Device * SDev; int diskinfo[4]; struct hd_geometry *loc = (struct hd_geometry *) arg; SDev = rscsi_disks[DEVICE_NR(dev)].device; /* * If we are in the middle of error recovery, don't let anyone * else try and use this device. Also, if error recovery fails, it * may try and take the device offline, in which case all further * access to the device is prohibited. */ if( !scsi_block_when_processing_errors(SDev) ) { return -ENODEV; } switch (cmd) { case HDIO_GETGEO: /* Return BIOS disk parameters */ if (!loc) return -EINVAL; error = verify_area(VERIFY_WRITE, loc, sizeof(*loc)); if (error) return error; host = rscsi_disks[DEVICE_NR(dev)].device->host; /* default to most commonly used values */ diskinfo[0] = 0x40; diskinfo[1] = 0x20; diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11; /* override with calculated, extended default, or driver values */ if(host->hostt->bios_param != NULL) host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)], dev, &diskinfo[0]); else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)], dev, &diskinfo[0]); put_user(diskinfo[0], &loc->heads); put_user(diskinfo[1], &loc->sectors); put_user(diskinfo[2], &loc->cylinders); put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &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_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects, (long *) arg); return 0; case BLKRASET: if (!capable(CAP_SYS_ADMIN)) return -EACCES; if(!(inode->i_rdev)) return -EINVAL; if(arg > 0xff) return -EINVAL; read_ahead[MAJOR(inode->i_rdev)] = arg; return 0; case BLKRAGET: if (!arg) return -EINVAL; error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); if (error) return error; put_user(read_ahead[MAJOR(inode->i_rdev)], (long *) arg); return 0; case BLKFLSBUF: if(!capable(CAP_SYS_ADMIN)) 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 */ if (!capable(CAP_SYS_ADMIN)) return -EACCES; return revalidate_scsidisk(dev, 1); RO_IOCTLS(dev, arg); default: return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg); } } /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * indent-tabs-mode: nil * tab-width: 8 * End: */ |