📄 sd.c
字号:
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; int hard_sector = sector_size; int sz = rscsi_disks[i].capacity * (hard_sector/256); /* There are 16 minors allocated for each major device */ for (m = i << 4; m < ((i + 1) << 4); m++) { sd_hardsizes[m] = hard_sector; } printk("SCSI device %s: " "%d %d-byte hdwr sectors (%d MB)\n", nbuff, rscsi_disks[i].capacity, hard_sector, (sz/2 - sz/1250 + 974)/1950); } /* Rescale capacity to 512-byte units */ if (sector_size == 4096) rscsi_disks[i].capacity <<= 3; if (sector_size == 2048) rscsi_disks[i].capacity <<= 2; if (sector_size == 1024) rscsi_disks[i].capacity <<= 1; if (sector_size == 256) rscsi_disks[i].capacity >>= 1; } /* * Unless otherwise specified, this is not write protected. */ rscsi_disks[i].write_prot = 0; if (rscsi_disks[i].device->removable && rscsi_disks[i].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) */ memset((void *) &cmd[0], 0, 8); cmd[0] = MODE_SENSE; cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ? ((rscsi_disks[i].device->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); } else { rscsi_disks[i].write_prot = ((buffer[2] & 0x80) != 0); printk("%s: Write Protect is %s\n", nbuff, rscsi_disks[i].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; scsi_free(buffer, 512); return i;}/* * The sd_init() function looks at all SCSI drives present, determines * their size, and reads partition table entries for them. */static int sd_registered;static int sd_init(){ int i; if (sd_template.dev_noticed == 0) return 0; if (!rscsi_disks) 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; if (!sd_registered) { for (i = 0; i < N_USED_SD_MAJORS; i++) { if (devfs_register_blkdev(SD_MAJOR(i), "sd", &sd_fops)) { printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(i)); sd_template.dev_noticed = 0; return 1; } } sd_registered++; } /* We do not support attaching loadable devices yet. */ if (rscsi_disks) return 0; rscsi_disks = kmalloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC); if (!rscsi_disks) goto cleanup_devfs; memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk)); /* for every (necessary) major: */ sd_sizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); if (!sd_sizes) goto cleanup_disks; memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int)); sd_blocksizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); if (!sd_blocksizes) goto cleanup_sizes; sd_hardsizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); if (!sd_hardsizes) goto cleanup_blocksizes; sd_max_sectors = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); if (!sd_max_sectors) goto cleanup_max_sectors; for (i = 0; i < sd_template.dev_max << 4; i++) { sd_blocksizes[i] = 1024; sd_hardsizes[i] = 512; /* * 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[i] = MAX_SEGMENTS*8; } for (i = 0; i < N_USED_SD_MAJORS; i++) { blksize_size[SD_MAJOR(i)] = sd_blocksizes + i * (SCSI_DISKS_PER_MAJOR << 4); hardsect_size[SD_MAJOR(i)] = sd_hardsizes + i * (SCSI_DISKS_PER_MAJOR << 4); max_sectors[SD_MAJOR(i)] = sd_max_sectors + i * (SCSI_DISKS_PER_MAJOR << 4); } /* * FIXME: should unregister blksize_size, hardsect_size and max_sectors when * the module is unloaded. */ sd = kmalloc((sd_template.dev_max << 4) * sizeof(struct hd_struct), GFP_ATOMIC); if (!sd) goto cleanup_sd; memset(sd, 0, (sd_template.dev_max << 4) * sizeof(struct hd_struct)); if (N_USED_SD_MAJORS > 1) sd_gendisks = kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), GFP_ATOMIC); if (!sd_gendisks) goto cleanup_sd_gendisks; for (i = 0; i < N_USED_SD_MAJORS; i++) { sd_gendisks[i] = sd_gendisk; sd_gendisks[i].de_arr = kmalloc (SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].de_arr, GFP_ATOMIC); if (!sd_gendisks[i].de_arr) goto cleanup_gendisks_de_arr; memset (sd_gendisks[i].de_arr, 0, SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].de_arr); sd_gendisks[i].flags = kmalloc (SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].flags, GFP_ATOMIC); if (!sd_gendisks[i].flags) goto cleanup_gendisks_flags; memset (sd_gendisks[i].flags, 0, SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].flags); sd_gendisks[i].major = SD_MAJOR(i); sd_gendisks[i].major_name = "sd"; sd_gendisks[i].minor_shift = 4; sd_gendisks[i].max_p = 1 << 4; sd_gendisks[i].part = sd + (i * SCSI_DISKS_PER_MAJOR << 4); sd_gendisks[i].sizes = sd_sizes + (i * SCSI_DISKS_PER_MAJOR << 4); sd_gendisks[i].nr_real = 0; sd_gendisks[i].real_devices = (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR); } return 0;cleanup_gendisks_flags: kfree(sd_gendisks[i].de_arr);cleanup_gendisks_de_arr: while (--i >= 0 ) { kfree(sd_gendisks[i].de_arr); kfree(sd_gendisks[i].flags); } if (sd_gendisks != &sd_gendisk) kfree(sd_gendisks);cleanup_sd_gendisks: kfree(sd);cleanup_sd: kfree(sd_max_sectors);cleanup_max_sectors: kfree(sd_hardsizes);cleanup_blocksizes: kfree(sd_blocksizes);cleanup_sizes: kfree(sd_sizes);cleanup_disks: kfree(rscsi_disks); rscsi_disks = NULL;cleanup_devfs: for (i = 0; i < N_USED_SD_MAJORS; i++) { devfs_unregister_blkdev(SD_MAJOR(i), "sd"); } sd_registered--; sd_template.dev_noticed = 0; return 1;}static void sd_finish(){ int i; for (i = 0; i < N_USED_SD_MAJORS; i++) { blk_dev[SD_MAJOR(i)].queue = sd_find_queue; add_gendisk(&sd_gendisks[i]); } for (i = 0; i < sd_template.dev_max; ++i) if (!rscsi_disks[i].capacity && rscsi_disks[i].device) { sd_init_onedisk(i); if (!rscsi_disks[i].has_part_table) { sd_sizes[i << 4] = rscsi_disks[i].capacity; register_disk(&SD_GENDISK(i), MKDEV_SD(i), 1<<4, &sd_fops, rscsi_disks[i].capacity); rscsi_disks[i].has_part_table = 1; } } /* If our host adapter is capable of scatter-gather, then we increase * the read-ahead to 60 blocks (120 sectors). If not, we use * a two block (4 sector) read ahead. We can only respect this with the * granularity of every 16 disks (one device major). */ for (i = 0; i < N_USED_SD_MAJORS; i++) { read_ahead[SD_MAJOR(i)] = (rscsi_disks[i * SCSI_DISKS_PER_MAJOR].device && rscsi_disks[i * SCSI_DISKS_PER_MAJOR].device->host->sg_tablesize) ? 120 /* 120 sector read-ahead */ : 4; /* 4 sector read-ahead */ } return;}static int sd_detect(Scsi_Device * SDp){ if (SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) return 0; sd_template.dev_noticed++; return 1;}static int sd_attach(Scsi_Device * SDp){ unsigned int devnum; Scsi_Disk *dpnt; int i; char nbuff[6]; if (SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) return 0; if (sd_template.nr_dev >= sd_template.dev_max || rscsi_disks == NULL) { SDp->attached--; return 1; } for (dpnt = rscsi_disks, i = 0; i < sd_template.dev_max; i++, dpnt++) if (!dpnt->device) break; if (i >= sd_template.dev_max) { printk(KERN_WARNING "scsi_devices corrupt (sd)," " nr_dev %d dev_max %d\n", sd_template.nr_dev, sd_template.dev_max); SDp->attached--; return 1; } rscsi_disks[i].device = SDp; rscsi_disks[i].has_part_table = 0; sd_template.nr_dev++; SD_GENDISK(i).nr_real++; devnum = i % SCSI_DISKS_PER_MAJOR; SD_GENDISK(i).de_arr[devnum] = SDp->de; if (SDp->removable) SD_GENDISK(i).flags[devnum] |= GENHD_FL_REMOVABLE; sd_devname(i, nbuff); printk("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;}#define DEVICE_BUSY rscsi_disks[target].device->busy#define ALLOW_REVALIDATE rscsi_disks[target].device->allow_revalidate#define USAGE rscsi_disks[target].device->access_count#define CAPACITY rscsi_disks[target].capacity#define MAYBE_REINIT sd_init_onedisk(target)/* This routine is called to flush all partitions and partition tables * for a changed scsi disk, and then re-read the new partition table. * If we are revalidating a disk because of a media change, then we * enter with usage == 0. If we are using an ioctl, we automatically have * usage == 1 (we need an open channel to use an ioctl :-), so this * is our limit. */int revalidate_scsidisk(kdev_t dev, int maxusage){ int target; int max_p; int start; int i; target = DEVICE_NR(dev); if (DEVICE_BUSY || (ALLOW_REVALIDATE == 0 && USAGE > maxusage)) { printk("Device busy for revalidation (usage=%d)\n", USAGE); return -EBUSY; } DEVICE_BUSY = 1; max_p = sd_gendisks->max_p; start = target << sd_gendisks->minor_shift; for (i = max_p - 1; i >= 0; i--) { int index = start + i; invalidate_device(MKDEV_SD_PARTITION(index), 1); sd_gendisks->part[index].start_sect = 0; sd_gendisks->part[index].nr_sects = 0; /* * Reset the blocksize for everything so that we can read * the partition table. Technically we will determine the * correct block size when we revalidate, but we do this just * to make sure that everything remains consistent. */ sd_blocksizes[index] = 1024; if (rscsi_disks[target].device->sector_size == 2048) sd_blocksizes[index] = 2048; else sd_blocksizes[index] = 1024; }#ifdef MAYBE_REINIT MAYBE_REINIT;#endif grok_partitions(&SD_GENDISK(target), target % SCSI_DISKS_PER_MAJOR, 1<<4, CAPACITY); DEVICE_BUSY = 0; return 0;}static int fop_revalidate_scsidisk(kdev_t dev){ return revalidate_scsidisk(dev, 0);}static void sd_detach(Scsi_Device * SDp){ Scsi_Disk *dpnt; int i, j; int max_p; int start; if (rscsi_disks == NULL) return; for (dpnt = rscsi_disks, i = 0; i < sd_template.dev_max; i++, dpnt++) if (dpnt->device == SDp) { /* If we are disconnecting a disk driver, sync and invalidate * everything */ max_p = sd_gendisk.max_p; start = i << sd_gendisk.minor_shift; for (j = max_p - 1; j >= 0; j--) { int index = start + j; invalidate_device(MKDEV_SD_PARTITION(index), 1); sd_gendisks->part[index].start_sect = 0; sd_gendisks->part[index].nr_sects = 0; sd_sizes[index] = 0; } devfs_register_partitions (&SD_GENDISK (i), SD_MINOR_NUMBER (start), 1); /* unregister_disk() */ dpnt->has_part_table = 0; dpnt->device = NULL; dpnt->capacity = 0; SDp->attached--; sd_template.dev_noticed--; sd_template.nr_dev--; SD_GENDISK(i).nr_real--; return; } return;}static int __init init_sd(void){ sd_template.module = THIS_MODULE; return scsi_register_module(MODULE_SCSI_DEV, &sd_template);}static void __exit exit_sd(void){ int i; scsi_unregister_module(MODULE_SCSI_DEV, &sd_template); for (i = 0; i < N_USED_SD_MAJORS; i++) devfs_unregister_blkdev(SD_MAJOR(i), "sd"); sd_registered--; if (rscsi_disks != NULL) { kfree(rscsi_disks); kfree(sd_sizes); kfree(sd_blocksizes); kfree(sd_hardsizes); kfree((char *) sd); } for (i = 0; i < N_USED_SD_MAJORS; i++) { del_gendisk(&sd_gendisks[i]); blk_size[SD_MAJOR(i)] = NULL; hardsect_size[SD_MAJOR(i)] = NULL; read_ahead[SD_MAJOR(i)] = 0; } sd_template.dev_max = 0; if (sd_gendisks != &sd_gendisk) kfree(sd_gendisks);}module_init(init_sd);module_exit(exit_sd);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -