📄 sd.c
字号:
} SDev = rscsi_disks[target].device; /* * 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 (!SDev->online) { return -ENXIO; } /* * 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) return -ENXIO; if (SDev->removable) if (!SDev->access_count) if (scsi_block_when_processing_errors(SDev)) scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, NULL); SDev->access_count++; if (SDev->host->hostt->module) __MOD_INC_USE_COUNT(SDev->host->hostt->module); if (sd_template.module) __MOD_INC_USE_COUNT(sd_template.module); return 0;}static int sd_release(struct inode *inode, struct file *file){ int target; Scsi_Device * SDev; target = DEVICE_NR(inode->i_rdev); SDev = rscsi_disks[target].device; SDev->access_count--; if (SDev->removable) { if (!SDev->access_count) if (scsi_block_when_processing_errors(SDev)) scsi_ioctl(SDev, SCSI_IOCTL_DOORUNLOCK, NULL); } if (SDev->host->hostt->module) __MOD_DEC_USE_COUNT(SDev->host->hostt->module); if (sd_template.module) __MOD_DEC_USE_COUNT(sd_template.module); return 0;}static struct block_device_operations sd_fops ={ 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 kmalloc() more gendisks later. */static struct gendisk sd_gendisk ={ SCSI_DISK0_MAJOR, /* Major number */ "sd", /* Major name */ 4, /* Bits to shift to get real from partition */ 1 << 4, /* Number of partitions per real */ NULL, /* hd struct */ NULL, /* block sizes */ 0, /* number */ NULL, /* internal */ NULL, /* next */ &sd_fops, /* file operations */};static struct gendisk *sd_gendisks = &sd_gendisk;#define SD_GENDISK(i) sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR]#define LAST_SD_GENDISK sd_gendisks[N_USED_SD_MAJORS - 1]/* * rw_intr is the interrupt routine for the device driver. * It will be notified on the end of a SCSI read / write, and * will take one of several actions based on success or failure. */static void rw_intr(Scsi_Cmnd * SCpnt){ int result = SCpnt->result;#if CONFIG_SCSI_LOGGING char nbuff[6];#endif int this_count = SCpnt->bufflen >> 9; int good_sectors = (result == 0 ? this_count : 0); int block_sectors = 1; SCSI_LOG_HLCOMPLETE(1, sd_devname(DEVICE_NR(SCpnt->request.rq_dev), nbuff)); SCSI_LOG_HLCOMPLETE(1, printk("%s : rw_intr(%d, %x [%x %x])\n", nbuff, SCpnt->host->host_no, result, SCpnt->sense_buffer[0], SCpnt->sense_buffer[2])); /* 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) { /* Sense data is valid */ if (SCpnt->sense_buffer[0] == 0xF0 && SCpnt->sense_buffer[2] == MEDIUM_ERROR) { long error_sector = (SCpnt->sense_buffer[3] << 24) | (SCpnt->sense_buffer[4] << 16) | (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6]; if (SCpnt->request.bh != NULL) block_sectors = SCpnt->request.bh->b_size >> 9; 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 -= sd[SD_PARTITION(SCpnt->request.rq_dev)].start_sect; error_sector &= ~(block_sectors - 1); good_sectors = error_sector - SCpnt->request.sector; if (good_sectors < 0 || good_sectors >= this_count) good_sectors = 0; } if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) { if (SCpnt->device->ten == 1) { if (SCpnt->cmnd[0] == READ_10 || SCpnt->cmnd[0] == WRITE_10) SCpnt->device->ten = 0; } } } /* * 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);}/* * requeue_sd_request() is the request handler function for the sd driver. * Its function in life is to take block device requests, and translate * them to SCSI commands. */static int check_scsidisk_media_change(kdev_t full_dev){ int retval; int target; int flag = 0; Scsi_Device * SDev; target = DEVICE_NR(full_dev); SDev = rscsi_disks[target].device; if (target >= sd_template.dev_max || !SDev) { printk("SCSI disk request error: invalid device.\n"); return 0; } if (!SDev->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 (SDev->online == FALSE) { rscsi_disks[target].ready = 0; SDev->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(SDev)) retval = scsi_ioctl(SDev, 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. */ rscsi_disks[target].ready = 0; SDev->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 ) */ rscsi_disks[target].ready = 1; /* FLOPTICAL */ retval = SDev->changed; if (!flag) SDev->changed = 0; return retval;}static int sd_init_onedisk(int i){ unsigned char cmd[10]; char nbuff[6]; unsigned char *buffer; unsigned long spintime_value = 0; int the_result, retries, spintime; int sector_size; Scsi_Request *SRpnt; /* * Get the name of the disk, in case we need to log it somewhere. */ sd_devname(i, nbuff); /* * If the device is offline, don't try and read capacity or any * of the other niceties. */ if (rscsi_disks[i].device->online == FALSE) return i; /* * 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(rscsi_disks[i].device); buffer = (unsigned char *) scsi_malloc(512); 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] = (rscsi_disks[i].device->lun << 5) & 0xe0; 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_READ; 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 ) { rscsi_disks[i].capacity = 0x1fffff; sector_size = 512; rscsi_disks[i].device->changed = 1; rscsi_disks[i].ready = 0; break; } /* Look for non-removable devices that return NOT_READY. * Issue command to spin up drive for these cases. */ if (the_result && !rscsi_disks[i].device->removable && SRpnt->sr_sense_buffer[2] == NOT_READY) { unsigned long time1; if (!spintime) { printk("%s: Spinning up disk...", nbuff); cmd[0] = START_STOP; cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0; 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 = 1; spintime_value = jiffies; 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] = (rscsi_disks[i].device->lun << 5) & 0xe0; 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("%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) printk("%s : extended sense code = %1x \n", nbuff, SRpnt->sr_sense_buffer[2] & 0xf); else printk("%s : sense not available. \n", nbuff); printk("%s : block size assumed to be 512 bytes, disk size 1GB. \n", nbuff); rscsi_disks[i].capacity = 0x1fffff; sector_size = 512; /* Set dirty bit for removable devices if not ready - * sometimes drives will not report this properly. */ if (rscsi_disks[i].device->removable && SRpnt->sr_sense_buffer[2] == NOT_READY) rscsi_disks[i].device->changed = 1; } else { /* * FLOPTICAL, if read_capa is ok, drive is assumed to be ready */ rscsi_disks[i].ready = 1; rscsi_disks[i].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("%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("%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. */ rscsi_disks[i].capacity = 0; } if (sector_size > 1024) { int m; /* * We must fix the sd_blocksizes and sd_hardsizes * to allow us to read the partition tables. * The disk reading code does not allow for reading * of partial sectors. */ for (m = i << 4; m < ((i + 1) << 4); m++) { sd_blocksizes[m] = sector_size; } } { /* * 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 m;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -