| /* |
| * sd.c Copyright (C) 1992 Drew Eckhardt |
| * Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale |
| * |
| * Linux scsi disk driver |
| * Initial versions: Drew Eckhardt |
| * Subsequent revisions: Eric Youngdale |
| * Modification history: |
| * - Drew Eckhardt <drew@colorado.edu> original |
| * - Eric Youngdale <eric@andante.org> add scatter-gather, multiple |
| * outstanding request, and other enhancements. |
| * Support loadable low-level scsi drivers. |
| * - Jirka Hanika <geo@ff.cuni.cz> support more scsi disks using |
| * eight major numbers. |
| * - Richard Gooch <rgooch@atnf.csiro.au> support devfs. |
| * - Torben Mathiasen <tmm@image.dk> Resource allocation fixes in |
| * sd_init and cleanups. |
| * - Alex Davis <letmein@erols.com> Fix problem where partition info |
| * not being read in sd_open. Fix problem where removable media |
| * could be ejected after sd_open. |
| * - Douglas Gilbert <dgilbert@interlog.com> cleanup for lk 2.5 series |
| * |
| * Logging policy (needs CONFIG_SCSI_LOGGING defined): |
| * - setting up transfer: SCSI_LOG_HLQUEUE levels 1 and 2 |
| * - end of transfer (bh + scsi_lib): SCSI_LOG_HLCOMPLETE level 1 |
| * - entering sd_ioctl: SCSI_LOG_IOCTL level 1 |
| * - entering other commands: SCSI_LOG_HLQUEUE level 3 |
| * Note: when the logging level is set by the user, it must be greater |
| * than the level indicated above to trigger output. |
| */ |
| |
| #include <linux/config.h> |
| #include <linux/module.h> |
| |
| #include <linux/fs.h> |
| #include <linux/kernel.h> |
| #include <linux/sched.h> |
| #include <linux/mm.h> |
| #include <linux/string.h> |
| #include <linux/hdreg.h> |
| #include <linux/errno.h> |
| #include <linux/interrupt.h> |
| #include <linux/init.h> |
| #include <linux/vmalloc.h> |
| #include <linux/smp.h> |
| |
| #include <asm/uaccess.h> |
| #include <asm/system.h> |
| #include <asm/io.h> |
| |
| #define MAJOR_NR SCSI_DISK0_MAJOR |
| #define LOCAL_END_REQUEST |
| #include <linux/blk.h> |
| #include <linux/blkpg.h> |
| #include "scsi.h" |
| #include "hosts.h" |
| #include "sd.h" |
| #include <scsi/scsi_ioctl.h> |
| #include "constants.h" |
| #include <scsi/scsicam.h> /* must follow "hosts.h" */ |
| |
| #include <linux/genhd.h> |
| |
| /* static char sd_version_str[] = "Version: 2.0.3 (20020417)"; */ |
| |
| #define SD_MAJOR(i) (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i)) |
| |
| #define SCSI_DISKS_PER_MAJOR 16 |
| #define SD_MAJOR_NUMBER(i) SD_MAJOR((i) >> 8) |
| #define SD_MINOR_NUMBER(i) ((i) & 255) |
| #define MKDEV_SD_PARTITION(i) mk_kdev(SD_MAJOR_NUMBER(i), (i) & 255) |
| #define MKDEV_SD(index) MKDEV_SD_PARTITION((index) << 4) |
| #define N_USED_SD_MAJORS (1 + ((sd_template.dev_max - 1) >> 4)) |
| |
| #define MAX_RETRIES 5 |
| |
| /* |
| * Time out in seconds for disks and Magneto-opticals (which are slower). |
| */ |
| |
| #define SD_TIMEOUT (30 * HZ) |
| #define SD_MOD_TIMEOUT (75 * HZ) |
| |
| #define SD_DSK_ARR_LUMP 6 /* amount to over allocate sd_dsk_arr by */ |
| |
| |
| struct hd_struct *sd; |
| |
| static Scsi_Disk ** sd_dsk_arr; |
| static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED; |
| |
| static int *sd_sizes; |
| static int *sd_max_sectors; |
| |
| static int check_scsidisk_media_change(kdev_t); |
| static int fop_revalidate_scsidisk(kdev_t); |
| |
| static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr); |
| |
| static int sd_init(void); |
| static void sd_finish(void); |
| static int sd_attach(Scsi_Device *); |
| static int sd_detect(Scsi_Device *); |
| static void sd_detach(Scsi_Device *); |
| static int sd_init_command(Scsi_Cmnd *); |
| |
| static struct Scsi_Device_Template sd_template = { |
| module:THIS_MODULE, |
| name:"disk", |
| tag:"sd", |
| scsi_type:TYPE_DISK, |
| major:SCSI_DISK0_MAJOR, |
| /* |
| * Secondary range of majors that this driver handles. |
| */ |
| min_major:SCSI_DISK1_MAJOR, |
| max_major:SCSI_DISK7_MAJOR, |
| blk:1, |
| detect:sd_detect, |
| init:sd_init, |
| finish:sd_finish, |
| attach:sd_attach, |
| detach:sd_detach, |
| init_command:sd_init_command, |
| }; |
| |
| static void sd_rw_intr(Scsi_Cmnd * SCpnt); |
| |
| static Scsi_Disk * sd_get_sdisk(int index); |
| |
| |
| #if defined(CONFIG_PPC32) |
| /** |
| * sd_find_target - find kdev_t of first scsi disk that matches |
| * given host and scsi_id. |
| * @host: Scsi_Host object pointer that owns scsi device of interest |
| * @scsi_id: scsi (target) id number of device of interest |
| * |
| * Returns kdev_t of first scsi device that matches arguments or |
| * NODEV of no match. |
| * |
| * Notes: Looks like a hack, should scan for <host,channel,id,lin> |
| * tuple. |
| * [Architectural dependency: ppc only.] Moved here from |
| * arch/ppc/pmac_setup.c. |
| **/ |
| kdev_t __init |
| sd_find_target(void *hp, int scsi_id) |
| { |
| Scsi_Disk *sdkp; |
| Scsi_Device *sdp; |
| struct Scsi_Host *shp = hp; |
| int dsk_nr; |
| unsigned long iflags; |
| |
| SCSI_LOG_HLQUEUE(3, printk("sd_find_target: host_nr=%d, " |
| "scsi_id=%d\n", shp->host_no, scsi_id)); |
| read_lock_irqsave(&sd_dsk_arr_lock, iflags); |
| for (dsk_nr = 0; dsk_nr < sd_template.dev_max; ++dsk_nr) { |
| if (NULL == (sdkp = sd_dsk_arr[dsk_nr])) |
| continue; |
| sdp = sdkp->device; |
| if (sdp && (sdp->host == shp) && (sdp->id == scsi_id)) { |
| read_unlock_irqrestore(&sd_dsk_arr_lock, iflags); |
| return MKDEV_SD(dsk_nr); |
| } |
| } |
| read_unlock_irqrestore(&sd_dsk_arr_lock, iflags); |
| return NODEV; |
| } |
| #endif |
| |
| /** |
| * sd_ioctl - process an ioctl |
| * @inode: only i_rdev member may be used |
| * @filp: only f_mode and f_flags may be used |
| * @cmd: ioctl command number |
| * @arg: this is third argument given to ioctl(2) system call. |
| * Often contains a pointer. |
| * |
| * Returns 0 if successful (some ioctls return postive numbers on |
| * success as well). Returns a negated errno value in case of error. |
| * |
| * Note: most ioctls are forward onto the block subsystem or further |
| * down in the scsi subsytem. |
| **/ |
| static int sd_ioctl(struct inode * inode, struct file * filp, |
| unsigned int cmd, unsigned long arg) |
| { |
| kdev_t dev = inode->i_rdev; |
| Scsi_Disk * sdkp; |
| struct Scsi_Host * host; |
| Scsi_Device * sdp; |
| int diskinfo[4]; |
| int dsk_nr = DEVICE_NR(dev); |
| |
| SCSI_LOG_IOCTL(1, printk("sd_ioctl: dsk_nr=%d, cmd=0x%x\n", |
| dsk_nr, cmd)); |
| sdkp = sd_get_sdisk(dsk_nr); |
| if ((NULL == sdkp) || (NULL == (sdp = sdkp->device))) |
| return -ENODEV; |
| /* |
| * 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(sdp) ) |
| return -ENODEV; |
| |
| switch (cmd) |
| { |
| case HDIO_GETGEO: /* Return BIOS disk parameters */ |
| { |
| struct hd_geometry *loc = (struct hd_geometry *) arg; |
| if(!loc) |
| return -EINVAL; |
| |
| host = sdp->host; |
| |
| /* default to most commonly used values */ |
| |
| diskinfo[0] = 0x40; |
| diskinfo[1] = 0x20; |
| diskinfo[2] = sdkp->capacity >> 11; |
| |
| /* override with calculated, extended default, |
| or driver values */ |
| |
| if(host->hostt->bios_param != NULL) |
| host->hostt->bios_param(sdkp, dev, |
| &diskinfo[0]); |
| else |
| scsicam_bios_param(sdkp, dev, &diskinfo[0]); |
| if (put_user(diskinfo[0], &loc->heads) || |
| put_user(diskinfo[1], &loc->sectors) || |
| put_user(diskinfo[2], &loc->cylinders) || |
| put_user((unsigned) |
| get_start_sect(inode->i_rdev), |
| (unsigned long *) &loc->start)) |
| return -EFAULT; |
| return 0; |
| } |
| |
| case BLKGETSIZE: |
| case BLKGETSIZE64: |
| case BLKROSET: |
| case BLKROGET: |
| case BLKFLSBUF: |
| case BLKSSZGET: |
| case BLKPG: |
| case BLKELVGET: |
| case BLKELVSET: |
| case BLKBSZGET: |
| case BLKBSZSET: |
| return blk_ioctl(inode->i_bdev, cmd, arg); |
| |
| case BLKRRPART: /* Re-read partition tables */ |
| if (!capable(CAP_SYS_ADMIN)) |
| return -EACCES; |
| return revalidate_scsidisk(dev, 1); |
| |
| default: |
| return scsi_ioctl(sdp, cmd, (void *) arg); |
| } |
| } |
| |
| static void sd_dskname(unsigned int dsk_nr, char *buffer) |
| { |
| if (dsk_nr < 26) |
| sprintf(buffer, "sd%c", 'a' + dsk_nr); |
| else { |
| unsigned int min1; |
| unsigned int min2; |
| /* |
| * For larger numbers of disks, we need to go to a new |
| * naming scheme. |
| */ |
| min1 = dsk_nr / 26; |
| min2 = dsk_nr % 26; |
| sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2); |
| } |
| } |
| |
| /** |
| * sd_find_queue - yields queue associated with device |
| * @dev: kernel device descriptor (kdev_t) |
| * |
| * Returns NULL if no match, otherwise returns pointer to associated |
| * request queue. |
| * |
| * Note: this function is invoked (often) from the block subsystem |
| * and should not wait on anything (sd_get_sdisk() does have a read |
| * spinlock). |
| **/ |
| static request_queue_t *sd_find_queue(kdev_t dev) |
| { |
| Scsi_Disk *sdkp; |
| int dsk_nr = DEVICE_NR(dev); |
| |
| sdkp = sd_get_sdisk(dsk_nr); |
| if (sdkp && sdkp->device) |
| return &sdkp->device->request_queue; |
| else |
| return NULL; /* No such device */ |
| } |
| |
| /** |
| * sd_init_command - build a scsi (read or write) command from |
| * information in the request structure. |
| * @SCpnt: pointer to mid-level's per scsi command structure that |
| * contains request and into which the scsi command is written |
| * |
| * Returns 1 if successful and 0 if error (or cannot be done now). |
| **/ |
| static int sd_init_command(Scsi_Cmnd * SCpnt) |
| { |
| int dsk_nr, part_nr, block, this_count; |
| Scsi_Device *sdp; |
| #if CONFIG_SCSI_LOGGING |
| char nbuff[6]; |
| #endif |
| /* |
| * don't support specials for nwo |
| */ |
| if (!(SCpnt->request.flags & REQ_CMD)) |
| return 0; |
| |
| part_nr = SD_PARTITION(SCpnt->request.rq_dev); |
| dsk_nr = DEVICE_NR(SCpnt->request.rq_dev); |
| |
| block = SCpnt->request.sector; |
| this_count = SCpnt->request_bufflen >> 9; |
| |
| SCSI_LOG_HLQUEUE(1, printk("sd_command_init: dsk_nr=%d, block=%d, " |
| "count=%d\n", dsk_nr, block, this_count)); |
| |
| sdp = SCpnt->device; |
| /* >>>>> the "(part_nr & 0xf)" excludes 15th partition, why?? */ |
| /* >>>>> this change is not in the lk 2.5 series */ |
| if (part_nr >= (sd_template.dev_max << 4) || (part_nr & 0xf) || |
| !sdp || !sdp->online || |
| block + SCpnt->request.nr_sectors > sd[part_nr].nr_sects) { |
| SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", |
| SCpnt->request.nr_sectors)); |
| SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); |
| return 0; |
| } |
| |
| if (sdp->changed) { |
| /* |
| * quietly refuse to do anything to a changed disc until |
| * the changed bit has been reset |
| */ |
| /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ |
| return 0; |
| } |
| SCSI_LOG_HLQUEUE(2, sd_dskname(dsk_nr, nbuff)); |
| SCSI_LOG_HLQUEUE(2, printk("%s : [part_nr=%d], block=%d\n", |
| nbuff, part_nr, block)); |
| |
| /* |
| * If we have a 1K hardware sectorsize, prevent access to single |
| * 512 byte sectors. In theory we could handle this - in fact |
| * the scsi cdrom driver must be able to handle this because |
| * we typically use 1K blocksizes, and cdroms typically have |
| * 2K hardware sectorsizes. Of course, things are simpler |
| * with the cdrom, since it is read-only. For performance |
| * reasons, the filesystems should be able to handle this |
| * and not force the scsi disk driver to use bounce buffers |
| * for this. |
| */ |
| if (sdp->sector_size == 1024) { |
| if ((block & 1) || (SCpnt->request.nr_sectors & 1)) { |
| printk(KERN_ERR "sd: Bad block number requested"); |
| return 0; |
| } else { |
| block = block >> 1; |
| this_count = this_count >> 1; |
| } |
| } |
| if (sdp->sector_size == 2048) { |
| if ((block & 3) || (SCpnt->request.nr_sectors & 3)) { |
| printk(KERN_ERR "sd: Bad block number requested"); |
| return 0; |
| } else { |
| block = block >> 2; |
| this_count = this_count >> 2; |
| } |
| } |
| if (sdp->sector_size == 4096) { |
| if ((block & 7) || (SCpnt->request.nr_sectors & 7)) { |
| printk(KERN_ERR "sd: Bad block number requested"); |
| return 0; |
| } else { |
| block = block >> 3; |
| this_count = this_count >> 3; |
| } |
| } |
| if (rq_data_dir(&SCpnt->request) == WRITE) { |
| if (!sdp->writeable) { |
| return 0; |
| } |
| SCpnt->cmnd[0] = WRITE_6; |
| SCpnt->sc_data_direction = SCSI_DATA_WRITE; |
| } else if (rq_data_dir(&SCpnt->request) == READ) { |
| SCpnt->cmnd[0] = READ_6; |
| SCpnt->sc_data_direction = SCSI_DATA_READ; |
| } else { |
| printk(KERN_ERR "sd: Unknown command %lx\n", |
| SCpnt->request.flags); |
| /* overkill panic("Unknown sd command %lx\n", SCpnt->request.flags); */ |
| return 0; |
| } |
| |
| SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", |
| nbuff, (rq_data_dir(&SCpnt->request) == WRITE) ? |
| "writing" : "reading", this_count, SCpnt->request.nr_sectors)); |
| |
| SCpnt->cmnd[1] = (SCpnt->device->scsi_level <= SCSI_2) ? |
| ((SCpnt->lun << 5) & 0xe0) : 0; |
| |
| if (((this_count > 0xff) || (block > 0x1fffff)) || SCpnt->device->ten) { |
| if (this_count > 0xffff) |
| this_count = 0xffff; |
| |
| SCpnt->cmnd[0] += READ_10 - READ_6; |
| SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; |
| SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; |
| SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; |
| SCpnt->cmnd[5] = (unsigned char) block & 0xff; |
| SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0; |
| SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; |
| SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; |
| } else { |
| if (this_count > 0xff) |
| this_count = 0xff; |
| |
| SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); |
| SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff); |
| SCpnt->cmnd[3] = (unsigned char) block & 0xff; |
| SCpnt->cmnd[4] = (unsigned char) this_count; |
| SCpnt->cmnd[5] = 0; |
| } |
| |
| /* |
| * We shouldn't disconnect in the middle of a sector, so with a dumb |
| * host adapter, it's safe to assume that we can at least transfer |
| * this many bytes between each connect / disconnect. |
| */ |
| SCpnt->transfersize = sdp->sector_size; |
| SCpnt->underflow = this_count << 9; |
| |
| SCpnt->allowed = MAX_RETRIES; |
| SCpnt->timeout_per_command = (SCpnt->device->type == TYPE_DISK ? |
| SD_TIMEOUT : SD_MOD_TIMEOUT); |
| |
| /* |
| * This is the completion routine we use. This is matched in terms |
| * of capability to this function. |
| */ |
| SCpnt->done = sd_rw_intr; |
| |
| /* |
| * This indicates that the command is ready from our end to be |
| * queued. |
| */ |
| return 1; |
| } |
| |
| /** |
| * sd_open - open a scsi disk device |
| * @inode: only i_rdev member may be used |
| * @filp: only f_mode and f_flags may be used |
| * |
| * Returns 0 if successful. Returns a negated errno value in case |
| * of error. |
| * |
| * Note: This can be called from a user context (e.g. fsck(1) ) |
| * or from within the kernel (e.g. as a result of a mount(1) ). |
| * In the latter case @inode and @filp carry an abridged amount |
| * of information as noted above. |
| **/ |
| static int sd_open(struct inode *inode, struct file *filp) |
| { |
| int retval = -ENXIO; |
| Scsi_Device * sdp; |
| Scsi_Disk * sdkp; |
| int dsk_nr = DEVICE_NR(inode->i_rdev); |
| |
| SCSI_LOG_HLQUEUE(3, printk("sd_open: dsk_nr=%d, part_nr=%d\n", |
| dsk_nr, SD_PARTITION(inode->i_rdev))); |
| |
| sdkp = sd_get_sdisk(dsk_nr); |
| if ((NULL == sdkp) || (NULL == (sdp = sdkp->device))) |
| return -ENXIO; /* No such device */ |
| |
| /* |
| * If the device is in error recovery, wait until it is done. |
| * If the device is offline, then disallow any access to it. |
| */ |
| if (!scsi_block_when_processing_errors(sdp)) |
| return -ENXIO; |
| /* |
| * Make sure that only one process can do a check_change_disk at |
| * one time. This is also used to lock out further access when |
| * the partition table is being re-read. |
| */ |
| |
| while (sdp->busy) { |
| barrier(); |
| cpu_relax(); |
| } |
| /* |
| * The following code can sleep. |
| * Module unloading must be prevented |
| */ |
| if (sdp->host->hostt->module) |
| __MOD_INC_USE_COUNT(sdp->host->hostt->module); |
| if (sd_template.module) |
| __MOD_INC_USE_COUNT(sd_template.module); |
| sdp->access_count++; |
| |
| if (sdp->removable) { |
| sdp->allow_revalidate = 1; |
| check_disk_change(inode->i_rdev); |
| sdp->allow_revalidate = 0; |
| |
| /* |
| * If the drive is empty, just let the open fail. |
| */ |
| if ((!sdkp->ready) && !(filp->f_flags & O_NDELAY)) { |
| retval = -ENOMEDIUM; |
| goto error_out; |
| } |
| |
| /* |
| * Similarly, if the device has the write protect tab set, |
| * have the open fail if the user expects to be able to write |
| * to the thing. |
| */ |
| if ((sdkp->write_prot) && (filp->f_mode & FMODE_WRITE)) { |
| retval = -EROFS; |
| goto error_out; |
| } |
| } |
| /* |
| * It is possible that the disk changing stuff resulted in the device |
| * being taken offline. If this is the case, report this to the user, |
| * and don't pretend that |
| * the open actually succeeded. |
| */ |
| if (!sdp->online) { |
| goto error_out; |
| } |
| /* |
| * See if we are requesting a non-existent partition. Do this |
| * after checking for disk change. |
| */ |
| if (sd_sizes[SD_PARTITION(inode->i_rdev)] == 0) { |
| goto error_out; |
| } |
| |
| if (sdp->removable) |
| if (sdp->access_count==1) |
| if (scsi_block_when_processing_errors(sdp)) |
| scsi_ioctl(sdp, SCSI_IOCTL_DOORLOCK, NULL); |
| |
| return 0; |
| |
| error_out: |
| sdp->access_count--; |
| if (sdp->host->hostt->module) |
| __MOD_DEC_USE_COUNT(sdp->host->hostt->module); |
| if (sd_template.module) |
| __MOD_DEC_USE_COUNT(sd_template.module); |
| return retval; |
| } |
| |
| /** |
| * sd_release - invoked when the (last) close(2) is called on this |
| * scsi disk. |
| * @inode: only i_rdev member may be used |
| * @filp: only f_mode and f_flags may be used |
| * |
| * Returns 0. |
| * |
| * Note: may block (uninterruptible) if error recovery is underway |
| * on this disk. |
| **/ |
| static int sd_release(struct inode *inode, struct file *filp) |
| { |
| Scsi_Disk * sdkp; |
| int dsk_nr = DEVICE_NR(inode->i_rdev); |
| Scsi_Device * sdp; |
| |
| SCSI_LOG_HLQUEUE(3, printk("sd_release: dsk_nr=%d, part_nr=%d\n", |
| dsk_nr, SD_PARTITION(inode->i_rdev))); |
| sdkp = sd_get_sdisk(dsk_nr); |
| if ((NULL == sdkp) || (NULL == (sdp = sdkp->device))) |
| return -ENODEV; /* open uses ENXIO ?? */ |
| |
| /* ... and what if there are packets in flight and this close() |
| * is followed by a "rmmod sd_mod" */ |
| |
| sdp->access_count--; |
| |
| if (sdp->removable) { |
| if (!sdp->access_count) |
| if (scsi_block_when_processing_errors(sdp)) |
| scsi_ioctl(sdp, SCSI_IOCTL_DOORUNLOCK, NULL); |
| } |
| if (sdp->host->hostt->module) |
| __MOD_DEC_USE_COUNT(sdp->host->hostt->module); |
| if (sd_template.module) |
| __MOD_DEC_USE_COUNT(sd_template.module); |
| return 0; |
| } |
| |
| static struct block_device_operations sd_fops = |
| { |
| owner: THIS_MODULE, |
| open: sd_open, |
| release: sd_release, |
| ioctl: sd_ioctl, |
| check_media_change: check_scsidisk_media_change, |
| revalidate: fop_revalidate_scsidisk |
| }; |
| |
| /* |
| * If we need more than one SCSI disk major (i.e. more than |
| * 16 SCSI disks), we'll have to vmalloc() more gendisks later. |
| */ |
| |
| static struct gendisk sd_gendisk = |
| { |
| major: SCSI_DISK0_MAJOR, |
| major_name: "sd", |
| minor_shift: 4, |
| fops: &sd_fops, |
| }; |
| |
| static struct gendisk *sd_gendisks = &sd_gendisk; |
| |
| #define SD_GENDISK(i) sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR] |
| |
| /** |
| * sd_rw_intr - bottom half handler: called when the lower level |
| * driver has completed (successfully or otherwise) a scsi command. |
| * @SCpnt: mid-level's per command structure. |
| * |
| * Note: potentially run from within an ISR. Must not block. |
| **/ |
| static void sd_rw_intr(Scsi_Cmnd * SCpnt) |
| { |
| int result = SCpnt->result; |
| int this_count = SCpnt->bufflen >> 9; |
| int good_sectors = (result == 0 ? this_count : 0); |
| int block_sectors = 1; |
| long error_sector; |
| #if CONFIG_SCSI_LOGGING |
| char nbuff[6]; |
| |
| SCSI_LOG_HLCOMPLETE(1, sd_dskname(DEVICE_NR(SCpnt->request.rq_dev), |
| nbuff)); |
| SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n", |
| nbuff, result)); |
| if (0 != result) { |
| SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: sb[0,2,asc,ascq]" |
| "=%x,%x,%x,%x\n", SCpnt->sense_buffer[0], |
| SCpnt->sense_buffer[2], SCpnt->sense_buffer[12], |
| SCpnt->sense_buffer[13])); |
| } |
| #endif |
| /* |
| Handle MEDIUM ERRORs that indicate partial success. Since this is a |
| relatively rare error condition, no care is taken to avoid |
| unnecessary additional work such as memcpy's that could be avoided. |
| */ |
| |
| /* An error occurred */ |
| if (driver_byte(result) != 0 && /* An error occured */ |
| SCpnt->sense_buffer[0] != 0xF0) { /* Sense data is valid */ |
| switch (SCpnt->sense_buffer[2]) { |
| case MEDIUM_ERROR: |
| error_sector = (SCpnt->sense_buffer[3] << 24) | |
| (SCpnt->sense_buffer[4] << 16) | |
| (SCpnt->sense_buffer[5] << 8) | |
| SCpnt->sense_buffer[6]; |
| if (SCpnt->request.bio != NULL) |
| block_sectors = bio_sectors(SCpnt->request.bio); |
| switch (SCpnt->device->sector_size) { |
| case 1024: |
| error_sector <<= 1; |
| if (block_sectors < 2) |
| block_sectors = 2; |
| break; |
| case 2048: |
| error_sector <<= 2; |
| if (block_sectors < 4) |
| block_sectors = 4; |
| break; |
| case 4096: |
| error_sector <<=3; |
| if (block_sectors < 8) |
| block_sectors = 8; |
| break; |
| case 256: |
| error_sector >>= 1; |
| break; |
| default: |
| break; |
| } |
| |
| error_sector &= ~(block_sectors - 1); |
| good_sectors = error_sector - SCpnt->request.sector; |
| if (good_sectors < 0 || good_sectors >= this_count) |
| good_sectors = 0; |
| break; |
| |
| case RECOVERED_ERROR: |
| /* |
| * An error occured, but it recovered. Inform the |
| * user, but make sure that it's not treated as a |
| * hard error. |
| */ |
| print_sense("sd", SCpnt); |
| result = 0; |
| SCpnt->sense_buffer[0] = 0x0; |
| good_sectors = this_count; |
| break; |
| |
| case ILLEGAL_REQUEST: |
| if (SCpnt->device->ten == 1) { |
| if (SCpnt->cmnd[0] == READ_10 || |
| SCpnt->cmnd[0] == WRITE_10) |
| SCpnt->device->ten = 0; |
| } |
| break; |
| |
| default: |
| break; |
| } |
| } |
| /* |
| * This calls the generic completion function, now that we know |
| * how many actual sectors finished, and how many sectors we need |
| * to say have failed. |
| */ |
| scsi_io_completion(SCpnt, good_sectors, block_sectors); |
| } |
| |
| /** |
| * check_scsidisk_media_change - self descriptive |
| * @full_dev: kernel device descriptor (kdev_t) |
| * |
| * Returns 0 if not applicable or no change; 1 if change |
| * |
| * Note: this function is invoked from the block subsystem. |
| **/ |
| static int check_scsidisk_media_change(kdev_t full_dev) |
| { |
| int retval; |
| int flag = 0; /* <<<< what is this for?? */ |
| Scsi_Disk * sdkp; |
| Scsi_Device * sdp; |
| int dsk_nr = DEVICE_NR(full_dev); |
| |
| sdkp = sd_get_sdisk(dsk_nr); |
| |
| SCSI_LOG_HLQUEUE(3, printk("check_scsidisk_media_change: " |
| "dsk_nr=%d\n", dsk_nr)); |
| if ((NULL == sdkp) || (NULL == (sdp = sdkp->device))) { |
| printk(KERN_ERR "check_scsidisk_media_change: dsk_nr=%d, " |
| "invalid device\n", dsk_nr); |
| return 0; |
| } |
| if (!sdp->removable) |
| return 0; |
| |
| /* |
| * If the device is offline, don't send any commands - just pretend as |
| * if the command failed. If the device ever comes back online, we |
| * can deal with it then. It is only because of unrecoverable errors |
| * that we would ever take a device offline in the first place. |
| */ |
| if (sdp->online == FALSE) { |
| sdkp->ready = 0; |
| sdp->changed = 1; |
| return 1; /* This will force a flush, if called from |
| * check_disk_change */ |
| } |
| |
| /* Using Start/Stop enables differentiation between drive with |
| * no cartridge loaded - NOT READY, drive with changed cartridge - |
| * UNIT ATTENTION, or with same cartridge - GOOD STATUS. |
| * This also handles drives that auto spin down. eg iomega jaz 1GB |
| * as this will spin up the drive. |
| */ |
| retval = -ENODEV; |
| if (scsi_block_when_processing_errors(sdp)) |
| retval = scsi_ioctl(sdp, SCSI_IOCTL_START_UNIT, NULL); |
| |
| if (retval) { /* Unable to test, unit probably not ready. |
| * This usually means there is no disc in the |
| * drive. Mark as changed, and we will figure |
| * it out later once the drive is available |
| * again. */ |
| |
| sdkp->ready = 0; |
| sdp->changed = 1; |
| return 1; /* This will force a flush, if called from |
| * check_disk_change */ |
| } |
| /* |
| * for removable scsi disk ( FLOPTICAL ) we have to recognise the |
| * presence of disk in the drive. This is kept in the Scsi_Disk |
| * struct and tested at open ! Daniel Roche ( dan@lectra.fr ) |
| */ |
| |
| sdkp->ready = 1; /* FLOPTICAL */ |
| |
| retval = sdp->changed; |
| if (!flag) |
| sdp->changed = 0; |
| return retval; |
| } |
| |
| /** |
| * sd_init_onedisk - called the first time a new disk is seen, |
| * performs read_capacity, disk spin up (as required), etc. |
| * @sdkp: pointer to associated Scsi_Disk object |
| * @dsk_nr: disk number within this driver (e.g. 0->/dev/sda, |
| * 1->/dev/sdb, etc) |
| * |
| * Returns dsk_nr (pointless) |
| * |
| * Note: this function is local to this driver. |
| **/ |
| static int sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr) |
| { |
| unsigned char cmd[10]; |
| char nbuff[6]; |
| unsigned char *buffer; |
| unsigned long spintime_value = 0; |
| int the_result, retries, spintime; |
| int sector_size; |
| Scsi_Device *sdp; |
| Scsi_Request *SRpnt; |
| |
| SCSI_LOG_HLQUEUE(3, printk("sd_init_onedisk: dsk_nr=%d\n", |
| dsk_nr)); |
| /* |
| * Get the name of the disk, in case we need to log it somewhere. |
| */ |
| sd_dskname(dsk_nr, nbuff); |
| |
| /* |
| * If the device is offline, don't try and read capacity or any |
| * of the other niceties. |
| */ |
| sdp = sdkp->device; |
| if (sdp->online == FALSE) |
| return dsk_nr; |
| |
| /* |
| * We need to retry the READ_CAPACITY because a UNIT_ATTENTION is |
| * considered a fatal error, and many devices report such an error |
| * just after a scsi bus reset. |
| */ |
| |
| SRpnt = scsi_allocate_request(sdp); |
| if (!SRpnt) { |
| printk(KERN_WARNING "(sd_init_onedisk:) Request allocation " |
| "failure.\n"); |
| return dsk_nr; |
| } |
| |
| buffer = kmalloc(512, GFP_DMA); |
| if (!buffer) { |
| printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation " |
| "failure.\n"); |
| scsi_release_request(SRpnt); |
| return dsk_nr; |
| } |
| |
| spintime = 0; |
| |
| /* Spin up drives, as required. Only do this at boot time */ |
| /* Spinup needs to be done for module loads too. */ |
| do { |
| retries = 0; |
| |
| while (retries < 3) { |
| cmd[0] = TEST_UNIT_READY; |
| cmd[1] = (sdp->scsi_level <= SCSI_2) ? |
| ((sdp->lun << 5) & 0xe0) : 0; |
| memset((void *) &cmd[2], 0, 8); |
| SRpnt->sr_cmd_len = 0; |
| SRpnt->sr_sense_buffer[0] = 0; |
| SRpnt->sr_sense_buffer[2] = 0; |
| SRpnt->sr_data_direction = SCSI_DATA_NONE; |
| |
| scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer, |
| 0/*512*/, SD_TIMEOUT, MAX_RETRIES); |
| |
| the_result = SRpnt->sr_result; |
| retries++; |
| if (the_result == 0 |
| || SRpnt->sr_sense_buffer[2] != UNIT_ATTENTION) |
| break; |
| } |
| |
| /* |
| * If the drive has indicated to us that it doesn't have |
| * any media in it, don't bother with any of the rest of |
| * this crap. |
| */ |
| if( the_result != 0 |
| && ((driver_byte(the_result) & DRIVER_SENSE) != 0) |
| && SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION |
| && SRpnt->sr_sense_buffer[12] == 0x3A ) { |
| sdkp->capacity = 0x1fffff; |
| sector_size = 512; |
| sdp->changed = 1; |
| sdkp->ready = 0; |
| break; |
| } |
| |
| /* Look for non-removable devices that return NOT_READY. |
| * Issue command to spin up drive for these cases. */ |
| if (the_result && !sdp->removable && |
| SRpnt->sr_sense_buffer[2] == NOT_READY) { |
| unsigned long time1; |
| if (!spintime) { |
| printk(KERN_NOTICE "%s: Spinning up disk...", |
| nbuff); |
| cmd[0] = START_STOP; |
| cmd[1] = (sdp->scsi_level <= SCSI_2) ? |
| ((sdp->lun << 5) & 0xe0) : 0; |
| cmd[1] |= 1; /* Return immediately */ |
| memset((void *) &cmd[2], 0, 8); |
| cmd[4] = 1; /* Start spin cycle */ |
| SRpnt->sr_cmd_len = 0; |
| SRpnt->sr_sense_buffer[0] = 0; |
| SRpnt->sr_sense_buffer[2] = 0; |
| |
| SRpnt->sr_data_direction = SCSI_DATA_READ; |
| scsi_wait_req(SRpnt, (void *)cmd, |
| (void *) buffer, 0/*512*/, |
| SD_TIMEOUT, MAX_RETRIES); |
| spintime_value = jiffies; |
| } |
| spintime = 1; |
| time1 = HZ; |
| /* Wait 1 second for next try */ |
| do { |
| current->state = TASK_UNINTERRUPTIBLE; |
| time1 = schedule_timeout(time1); |
| } while(time1); |
| printk("."); |
| } |
| } while (the_result && spintime && |
| time_after(spintime_value + 100 * HZ, jiffies)); |
| if (spintime) { |
| if (the_result) |
| printk("not responding...\n"); |
| else |
| printk("ready\n"); |
| } |
| retries = 3; |
| do { |
| cmd[0] = READ_CAPACITY; |
| cmd[1] = (sdp->scsi_level <= SCSI_2) ? |
| ((sdp->lun << 5) & 0xe0) : 0; |
| memset((void *) &cmd[2], 0, 8); |
| memset((void *) buffer, 0, 8); |
| SRpnt->sr_cmd_len = 0; |
| SRpnt->sr_sense_buffer[0] = 0; |
| SRpnt->sr_sense_buffer[2] = 0; |
| |
| SRpnt->sr_data_direction = SCSI_DATA_READ; |
| scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, |
| 8, SD_TIMEOUT, MAX_RETRIES); |
| |
| the_result = SRpnt->sr_result; |
| retries--; |
| |
| } while (the_result && retries); |
| |
| /* |
| * The SCSI standard says: |
| * "READ CAPACITY is necessary for self configuring software" |
| * While not mandatory, support of READ CAPACITY is strongly |
| * encouraged. |
| * We used to die if we couldn't successfully do a READ CAPACITY. |
| * But, now we go on about our way. The side effects of this are |
| * |
| * 1. We can't know block size with certainty. I have said |
| * "512 bytes is it" as this is most common. |
| * |
| * 2. Recovery from when someone attempts to read past the |
| * end of the raw device will be slower. |
| */ |
| |
| if (the_result) { |
| printk(KERN_NOTICE "%s : READ CAPACITY failed.\n" |
| "%s : status=%x, message=%02x, host=%d, driver=%02x \n", |
| nbuff, nbuff, |
| status_byte(the_result), |
| msg_byte(the_result), |
| host_byte(the_result), |
| driver_byte(the_result) |
| ); |
| if (driver_byte(the_result) & DRIVER_SENSE) |
| print_req_sense("sd", SRpnt); |
| else |
| printk("%s : sense not available. \n", nbuff); |
| |
| printk(KERN_NOTICE "%s : block size assumed to be 512 " |
| "bytes, disk size 1GB. \n", nbuff); |
| sdkp->capacity = 0x1fffff; |
| sector_size = 512; |
| |
| /* Set dirty bit for removable devices if not ready - |
| * sometimes drives will not report this properly. */ |
| if (sdp->removable && |
| SRpnt->sr_sense_buffer[2] == NOT_READY) |
| sdp->changed = 1; |
| |
| } else { |
| /* |
| * FLOPTICAL, if read_capa is ok, drive is assumed to be ready |
| */ |
| sdkp->ready = 1; |
| |
| sdkp->capacity = 1 + ((buffer[0] << 24) | |
| (buffer[1] << 16) | |
| (buffer[2] << 8) | |
| buffer[3]); |
| |
| sector_size = (buffer[4] << 24) | |
| (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; |
| |
| if (sector_size == 0) { |
| sector_size = 512; |
| printk(KERN_NOTICE "%s : sector size 0 reported, " |
| "assuming 512.\n", nbuff); |
| } |
| if (sector_size != 512 && |
| sector_size != 1024 && |
| sector_size != 2048 && |
| sector_size != 4096 && |
| sector_size != 256) { |
| printk(KERN_NOTICE "%s : unsupported sector size " |
| "%d.\n", nbuff, sector_size); |
| /* |
| * The user might want to re-format the drive with |
| * a supported sectorsize. Once this happens, it |
| * would be relatively trivial to set the thing up. |
| * For this reason, we leave the thing in the table. |
| */ |
| sdkp->capacity = 0; |
| } |
| { |
| /* |
| * The msdos fs needs to know the hardware sector size |
| * So I have created this table. See ll_rw_blk.c |
| * Jacques Gelinas (Jacques@solucorp.qc.ca) |
| */ |
| int hard_sector = sector_size; |
| int sz = sdkp->capacity * (hard_sector/256); |
| request_queue_t *queue = &sdp->request_queue; |
| |
| blk_queue_hardsect_size(queue, hard_sector); |
| printk(KERN_NOTICE "SCSI device %s: " |
| "%d %d-byte hdwr sectors (%d MB)\n", |
| nbuff, sdkp->capacity, |
| hard_sector, (sz/2 - sz/1250 + 974)/1950); |
| } |
| |
| /* Rescale capacity to 512-byte units */ |
| if (sector_size == 4096) |
| sdkp->capacity <<= 3; |
| if (sector_size == 2048) |
| sdkp->capacity <<= 2; |
| if (sector_size == 1024) |
| sdkp->capacity <<= 1; |
| if (sector_size == 256) |
| sdkp->capacity >>= 1; |
| } |
| |
| |
| /* |
| * Unless otherwise specified, this is not write protected. |
| */ |
| sdkp->write_prot = 0; |
| if (sdp->removable && sdkp->ready) { |
| /* FLOPTICAL */ |
| |
| /* |
| * For removable scsi disk ( FLOPTICAL ) we have to recognise |
| * the Write Protect Flag. This flag is kept in the Scsi_Disk |
| * struct and tested at open ! |
| * Daniel Roche ( dan@lectra.fr ) |
| * |
| * Changed to get all pages (0x3f) rather than page 1 to |
| * get around devices which do not have a page 1. Since |
| * we're only interested in the header anyway, this should |
| * be fine. |
| * -- Matthew Dharm (mdharm-scsi@one-eyed-alien.net) |
| * |
| * As it turns out, some devices return an error for |
| * every MODE_SENSE request except one for page 0. |
| * So, we should also try that. --aeb |
| */ |
| |
| memset((void *) &cmd[0], 0, 8); |
| cmd[0] = MODE_SENSE; |
| cmd[1] = (sdp->scsi_level <= SCSI_2) ? |
| ((sdp->lun << 5) & 0xe0) : 0; |
| cmd[2] = 0x3f; /* Get all pages */ |
| cmd[4] = 255; /* Ask for 255 bytes, even tho we want just the first 8 */ |
| SRpnt->sr_cmd_len = 0; |
| SRpnt->sr_sense_buffer[0] = 0; |
| SRpnt->sr_sense_buffer[2] = 0; |
| |
| /* same code as READCAPA !! */ |
| SRpnt->sr_data_direction = SCSI_DATA_READ; |
| scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, |
| 512, SD_TIMEOUT, MAX_RETRIES); |
| |
| the_result = SRpnt->sr_result; |
| |
| if (the_result) { |
| printk("%s: test WP failed, assume Write Enabled\n", |
| nbuff); |
| /* alternatively, try page 0 */ |
| } else { |
| sdkp->write_prot = ((buffer[2] & 0x80) != 0); |
| printk(KERN_NOTICE "%s: Write Protect is %s\n", nbuff, |
| sdkp->write_prot ? "on" : "off"); |
| } |
| |
| } /* check for write protect */ |
| SRpnt->sr_device->ten = 1; |
| SRpnt->sr_device->remap = 1; |
| SRpnt->sr_device->sector_size = sector_size; |
| /* Wake up a process waiting for device */ |
| scsi_release_request(SRpnt); |
| SRpnt = NULL; |
| |
| kfree(buffer); |
| return dsk_nr; |
| } |
| |
| /* |
| * The sd_init() function looks at all SCSI drives present, determines |
| * their size, and reads partition table entries for them. |
| */ |
| |
| static int sd_registered; |
| |
| /** |
| * sd_init- called during driver initialization (after |
| * sd_detect() is called for each scsi device present). |
| * |
| * Returns 0 is successful (or already called); 1 if error |
| * |
| * Note: this function is invoked from the scsi mid-level. |
| **/ |
| static int sd_init() |
| { |
| int k, maxparts; |
| Scsi_Disk * sdkp; |
| |
| SCSI_LOG_HLQUEUE(3, printk("sd_init: dev_noticed=%d\n", |
| sd_template.dev_noticed)); |
| if (sd_template.dev_noticed == 0) |
| return 0; |
| |
| if (NULL == sd_dsk_arr) |
| sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS; |
| |
| if (sd_template.dev_max > N_SD_MAJORS * SCSI_DISKS_PER_MAJOR) |
| sd_template.dev_max = N_SD_MAJORS * SCSI_DISKS_PER_MAJOR; |
| |
| /* At most 16 partitions on each scsi disk. */ |
| maxparts = (sd_template.dev_max << 4); |
| if (maxparts == 0) |
| return 0; |
| |
| if (!sd_registered) { |
| for (k = 0; k < N_USED_SD_MAJORS; k++) { |
| if (devfs_register_blkdev(SD_MAJOR(k), "sd", |
| &sd_fops)) { |
| printk(KERN_NOTICE "Unable to get major %d " |
| "for SCSI disk\n", SD_MAJOR(k)); |
| return 1; |
| } |
| } |
| sd_registered++; |
| } |
| /* We do not support attaching loadable devices yet. */ |
| if (sd_dsk_arr) |
| return 0; |
| |
| /* allocate memory */ |
| #define init_mem_lth(x,n) x = vmalloc((n) * sizeof(*x)) |
| #define zero_mem_lth(x,n) memset(x, 0, (n) * sizeof(*x)) |
| |
| init_mem_lth(sd_dsk_arr, sd_template.dev_max); |
| if (sd_dsk_arr) { |
| zero_mem_lth(sd_dsk_arr, sd_template.dev_max); |
| for (k = 0; k < sd_template.dev_max; ++k) { |
| sdkp = vmalloc(sizeof(Scsi_Disk)); |
| if (NULL == sdkp) |
| goto cleanup_mem; |
| memset(sdkp, 0, sizeof(Scsi_Disk)); |
| sd_dsk_arr[k] = sdkp; |
| } |
| } |
| init_mem_lth(sd_sizes, maxparts); |
| init_mem_lth(sd, maxparts); |
| init_mem_lth(sd_gendisks, N_USED_SD_MAJORS); |
| init_mem_lth(sd_max_sectors, sd_template.dev_max << 4); |
| |
| if (!sd_dsk_arr || !sd_sizes || !sd || !sd_gendisks) |
| goto cleanup_mem; |
| |
| zero_mem_lth(sd_sizes, maxparts); |
| zero_mem_lth(sd, maxparts); |
| |
| for (k = 0; k < maxparts; k++) { |
| /* |
| * Allow lowlevel device drivers to generate 512k large scsi |
| * commands if they know what they're doing and they ask for it |
| * explicitly via the SHpnt->max_sectors API. |
| */ |
| sd_max_sectors[k] = MAX_PHYS_SEGMENTS*8; |
| } |
| |
| for (k = 0; k < N_USED_SD_MAJORS; k++) { |
| int N = SCSI_DISKS_PER_MAJOR; |
| |
| sd_gendisks[k] = sd_gendisk; |
| |
| init_mem_lth(sd_gendisks[k].de_arr, N); |
| init_mem_lth(sd_gendisks[k].flags, N); |
| |
| if (!sd_gendisks[k].de_arr || !sd_gendisks[k].flags) |
| goto cleanup_gendisks; |
| |
| zero_mem_lth(sd_gendisks[k].de_arr, N); |
| zero_mem_lth(sd_gendisks[k].flags, N); |
| |
| sd_gendisks[k].major = SD_MAJOR(k); |
| sd_gendisks[k].major_name = "sd"; |
| sd_gendisks[k].minor_shift = 4; |
| sd_gendisks[k].part = sd + k * (N << 4); |
| sd_gendisks[k].sizes = sd_sizes + k * (N << 4); |
| sd_gendisks[k].nr_real = 0; |
| } |
| |
| return 0; |
| |
| #undef init_mem_lth |
| #undef zero_mem_lth |
| |
| cleanup_gendisks: |
| /* vfree can handle NULL, so no test is required here */ |
| for (k = 0; k < N_USED_SD_MAJORS; k++) { |
| vfree(sd_gendisks[k].de_arr); |
| vfree(sd_gendisks[k].flags); |
| } |
| cleanup_mem: |
| if (sd_gendisks) vfree(sd_gendisks); |
| sd_gendisks = NULL; |
| if (sd) vfree(sd); |
| sd = NULL; |
| if (sd_sizes) vfree(sd_sizes); |
| sd_sizes = NULL; |
| if (sd_dsk_arr) { |
| for (k = 0; k < sd_template.dev_max; ++k) { |
| sdkp = sd_dsk_arr[k]; |
| if (sdkp) |
| vfree(sdkp); |
| } |
| vfree(sd_dsk_arr); |
| sd_dsk_arr = NULL; |
| } |
| for (k = 0; k < N_USED_SD_MAJORS; k++) { |
| devfs_unregister_blkdev(SD_MAJOR(k), "sd"); |
| } |
| sd_registered--; |
| return 1; |
| } |
| |
| /** |
| * sd_finish- called during driver initialization, after all |
| * the sd_attach() calls are finished. |
| * |
| * Note: this function is invoked from the scsi mid-level. |
| * This function is not called after driver initialization has completed. |
| * Specifically later device attachments invoke sd_attach() but not |
| * this function. |
| **/ |
| static void sd_finish() |
| { |
| int k; |
| Scsi_Disk * sdkp; |
| |
| SCSI_LOG_HLQUEUE(3, printk("sd_finish: \n")); |
| for (k = 0; k < N_USED_SD_MAJORS; k++) { |
| blk_dev[SD_MAJOR(k)].queue = sd_find_queue; |
| add_gendisk(&(sd_gendisks[k])); |
| } |
| |
| for (k = 0; k < sd_template.dev_max; ++k) { |
| sdkp = sd_get_sdisk(k); |
| if (sdkp && (0 == sdkp->capacity) && sdkp->device) { |
| sd_init_onedisk(sdkp, k); |
| if (!sdkp->has_part_table) { |
| sd_sizes[k << 4] = sdkp->capacity; |
| register_disk(&SD_GENDISK(k), MKDEV_SD(k), |
| 1<<4, &sd_fops, |
| sdkp->capacity); |
| sdkp->has_part_table = 1; |
| } |
| } |
| } |
| return; |
| } |
| |
| /** |
| * sd_detect- called at the start of driver initialization, once |
| * for each scsi device (not just disks) present. |
| * |
| * Returns 0 if not interested in this scsi device (e.g. scanner); |
| * 1 if this device is of interest (e.g. a disk). |
| * |
| * Note: this function is invoked from the scsi mid-level. |
| * This function is called before sd_init() so very little is available. |
| **/ |
| static int sd_detect(Scsi_Device * sdp) |
| { |
| SCSI_LOG_HLQUEUE(3, printk("sd_detect: type=%d\n", sdp->type)); |
| if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD) |
| return 0; |
| sd_template.dev_noticed++; |
| return 1; |
| } |
| |
| /** |
| * sd_attach- called during driver initialization and whenever a |
| * new scsi device is attached to the system. It is called once |
| * for each scsi device (not just disks) present. |
| * @sdp: pointer to mid level scsi device object |
| * |
| * Returns 0 if successful (or not interested in this scsi device |
| * (e.g. scanner)); 1 when there is an error. |
| * |
| * Note: this function is invoked from the scsi mid-level. |
| * This function sets up the mapping between a given |
| * <host,channel,id,lun> (found in sdp) and new device name |
| * (e.g. /dev/sda). More precisely it is the block device major |
| * and minor number that is chosen here. |
| **/ |
| static int sd_attach(Scsi_Device * sdp) |
| { |
| unsigned int devnum; |
| Scsi_Disk *sdkp; |
| int dsk_nr; |
| char nbuff[6]; |
| unsigned long iflags; |
| |
| if ((NULL == sdp) || |
| ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD))) |
| return 0; |
| |
| SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", |
| sdp->host->host_no, sdp->channel, sdp->id, sdp->lun)); |
| if (sd_template.nr_dev >= sd_template.dev_max) { |
| sdp->attached--; |
| printk(KERN_ERR "sd_init: no more room for device\n"); |
| return 1; |
| } |
| |
| /* Assume sd_attach is not re-entrant (for time being) */ |
| /* Also think about sd_attach() and sd_detach() running coincidentally. */ |
| write_lock_irqsave(&sd_dsk_arr_lock, iflags); |
| for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) { |
| sdkp = sd_dsk_arr[dsk_nr]; |
| if (!sdkp->device) { |
| sdkp->device = sdp; |
| sdkp->has_part_table = 0; |
| break; |
| } |
| } |
| write_unlock_irqrestore(&sd_dsk_arr_lock, iflags); |
| |
| if (dsk_nr >= sd_template.dev_max) { |
| /* panic("scsi_devices corrupt (sd)"); overkill */ |
| printk(KERN_ERR "sd_init: sd_dsk_arr corrupted\n"); |
| return 1; |
| } |
| |
| sd_template.nr_dev++; |
| SD_GENDISK(dsk_nr).nr_real++; |
| devnum = dsk_nr % SCSI_DISKS_PER_MAJOR; |
| SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de; |
| if (sdp->removable) |
| SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE; |
| sd_dskname(dsk_nr, nbuff); |
| printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, " |
| "id %d, lun %d\n", sdp->removable ? "removable " : "", |
| nbuff, sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); |
| return 0; |
| } |
| |
| /** |
| * revalidate_scsidisk- called to flush all partitions and partition |
| * tables for a changed scsi disk. sd_init_onedisk() is then called |
| * followed by re-reading the new partition table. |
| * @dev: kernel device descriptor (kdev_t) |
| * @maxusage: 0 when called from block level, 1 when called from |
| * sd_ioctl(). |
| * |
| * Returns 0 if successful; negated errno value otherwise. |
| */ |
| int revalidate_scsidisk(kdev_t dev, int maxusage) |
| { |
| int dsk_nr = DEVICE_NR(dev); |
| int res; |
| Scsi_Disk * sdkp; |
| Scsi_Device * sdp; |
| |
| SCSI_LOG_HLQUEUE(3, printk("revalidate_scsidisk: dsk_nr=%d\n", |
| DEVICE_NR(dev))); |
| sdkp = sd_get_sdisk(dsk_nr); |
| if ((NULL == sdkp) || (NULL == (sdp = sdkp->device))) |
| return -ENODEV; |
| |
| if (sdp->busy || ((sdp->allow_revalidate == 0) && |
| (sdp->access_count > maxusage))) { |
| printk(KERN_WARNING "Device busy for revalidation " |
| "(access_count=%d)\n", sdp->access_count); |
| return -EBUSY; |
| } |
| sdp->busy = 1; |
| |
| res = wipe_partitions(dev); |
| if (res) |
| goto leave; |
| |
| sd_init_onedisk(sdkp, dsk_nr); |
| |
| grok_partitions(dev, sdkp->capacity); |
| leave: |
| sdp->busy = 0; |
| return res; |
| } |
| |
| static int fop_revalidate_scsidisk(kdev_t dev) |
| { |
| return revalidate_scsidisk(dev, 0); |
| } |
| |
| /** |
| * sd_detach- called whenever a scsi disk (previously recognized by |
| * sd_attach) is detached from the system. It is called (potentially |
| * multiple times) during sd module unload. |
| * @sdp: pointer to mid level scsi device object |
| * |
| * Note: this function is invoked from the scsi mid-level. |
| * This function potentially frees up a device name (e.g. /dev/sdc) |
| * that could be re-used by a subsequent sd_attach(). |
| * This function is not called when the built-in sd driver is "exit-ed". |
| **/ |
| static void sd_detach(Scsi_Device * sdp) |
| { |
| Scsi_Disk *sdkp = NULL; |
| kdev_t dev; |
| int dsk_nr, j; |
| int max_p; |
| int start; |
| unsigned long iflags; |
| |
| SCSI_LOG_HLQUEUE(3, printk("sd_detach: <%d,%d,%d,%d>\n", |
| sdp->host->host_no, sdp->channel, sdp->id, |
| sdp->lun)); |
| write_lock_irqsave(&sd_dsk_arr_lock, iflags); |
| for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) { |
| sdkp = sd_dsk_arr[dsk_nr]; |
| if (sdkp->device == sdp) { |
| sdkp->has_part_table = 0; |
| sdkp->device = NULL; |
| sdkp->capacity = 0; |
| /* sdkp->detaching = 1; */ |
| break; |
| } |
| } |
| write_unlock_irqrestore(&sd_dsk_arr_lock, iflags); |
| if (dsk_nr >= sd_template.dev_max) |
| return; |
| |
| max_p = 1 << sd_gendisk.minor_shift; |
| start = dsk_nr << sd_gendisk.minor_shift; |
| dev = MKDEV_SD_PARTITION(start); |
| wipe_partitions(dev); |
| for (j = max_p - 1; j >= 0; j--) |
| sd_sizes[start + j] = 0; |
| |
| devfs_register_partitions (&SD_GENDISK (dsk_nr), |
| SD_MINOR_NUMBER (start), 1); |
| /* unregister_disk() */ |
| sdp->attached--; |
| sd_template.dev_noticed--; |
| sd_template.nr_dev--; |
| SD_GENDISK(dsk_nr).nr_real--; |
| } |
| |
| /** |
| * init_sd- entry point for this driver (both when built in or when |
| * a module). |
| * |
| * Note: this function registers this driver with the scsi mid-level. |
| **/ |
| static int __init init_sd(void) |
| { |
| SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n")); |
| sd_template.module = THIS_MODULE; |
| return scsi_register_device(&sd_template); |
| } |
| |
| /** |
| * exit_sd- exit point for this driver (when it is a module). |
| * |
| * Note: this function unregisters this driver from the scsi mid-level. |
| **/ |
| static void __exit exit_sd(void) |
| { |
| int k; |
| Scsi_Disk * sdkp; |
| |
| SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n")); |
| scsi_unregister_device(&sd_template); |
| for (k = 0; k < N_USED_SD_MAJORS; k++) |
| devfs_unregister_blkdev(SD_MAJOR(k), "sd"); |
| |
| sd_registered--; |
| if (sd_dsk_arr != NULL) { |
| for (k = 0; k < sd_template.dev_max; ++k) { |
| sdkp = sd_dsk_arr[k]; |
| if (sdkp) |
| vfree(sdkp); |
| } |
| vfree(sd_dsk_arr); |
| } |
| if (sd_sizes) vfree(sd_sizes); |
| if (sd) vfree((char *) sd); |
| for (k = 0; k < N_USED_SD_MAJORS; k++) { |
| blk_dev[SD_MAJOR(k)].queue = NULL; |
| del_gendisk(&(sd_gendisks[k])); |
| blk_clear(SD_MAJOR(k)); |
| } |
| sd_template.dev_max = 0; |
| if (sd_gendisks != &sd_gendisk) |
| vfree(sd_gendisks); |
| } |
| |
| static Scsi_Disk * sd_get_sdisk(int index) |
| { |
| Scsi_Disk * sdkp = NULL; |
| unsigned long iflags; |
| |
| read_lock_irqsave(&sd_dsk_arr_lock, iflags); |
| if (sd_dsk_arr && (index >= 0) && (index < sd_template.dev_max)) |
| sdkp = sd_dsk_arr[index]; |
| read_unlock_irqrestore(&sd_dsk_arr_lock, iflags); |
| return sdkp; |
| } |
| |
| MODULE_LICENSE("GPL"); |
| MODULE_AUTHOR("Eric Youngdale"); |
| MODULE_DESCRIPTION("SCSI disk (sd) driver"); |
| |
| module_init(init_sd); |
| module_exit(exit_sd); |