📄 sd.c
字号:
} } { /* * 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, mb; int sz_quot, sz_rem; int hard_sector = rscsi_disks[i].sector_size; /* There are 16 minors allocated for each major device */ for (m=i<<4; m<((i+1)<<4); m++){ sd_hardsizes[m] = hard_sector; } mb = rscsi_disks[i].capacity / 1024 * hard_sector / 1024; /* sz = div(m/100, 10); this seems to not be in the libr */ m = (mb + 50) / 100; sz_quot = m / 10; sz_rem = m - (10 * sz_quot); printk ("SCSI device %s: hdwr sector= %d bytes." " Sectors= %d [%d MB] [%d.%1d GB]\n", nbuff, hard_sector, rscsi_disks[i].capacity, mb, sz_quot, sz_rem); } if(rscsi_disks[i].sector_size == 4096) rscsi_disks[i].capacity <<= 3; if(rscsi_disks[i].sector_size == 2048) rscsi_disks[i].capacity <<= 2; /* Change into 512 byte sectors */ if(rscsi_disks[i].sector_size == 1024) rscsi_disks[i].capacity <<= 1; /* Change into 512 byte sectors */ if(rscsi_disks[i].sector_size == 256) rscsi_disks[i].capacity >>= 1; /* Change into 512 byte sectors */ } /* * 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 ) */ memset ((void *) &cmd[0], 0, 8); cmd[0] = MODE_SENSE; cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0; cmd[2] = 1; /* page code 1 ?? */ cmd[4] = 12; SCpnt->cmd_len = 0; SCpnt->sense_buffer[0] = 0; SCpnt->sense_buffer[2] = 0; /* same code as READCAPA !! */ { struct semaphore sem = MUTEX_LOCKED; SCpnt->request.rq_status = RQ_SCSI_BUSY; /* Mark as really busy again */ SCpnt->request.sem = &sem; scsi_do_cmd (SCpnt, (void *) cmd, (void *) buffer, 512, sd_init_done, SD_TIMEOUT, MAX_RETRIES); spin_unlock_irq(&io_request_lock); down(&sem); spin_lock_irq(&io_request_lock); SCpnt->request.sem = NULL; } the_result = SCpnt->result; if ( the_result ) { printk ("%s: test WP failed, assume Write Protected\n",nbuff); rscsi_disks[i].write_prot = 1; } 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 */ /* Wake up a process waiting for device */ wake_up(&SCpnt->device->device_wait); scsi_release_command(SCpnt); SCpnt = NULL; rscsi_disks[i].ten = 1; rscsi_disks[i].remap = 1; scsi_free(buffer, 512); spin_unlock_irq(&io_request_lock); 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 = 0;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 <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) { if (register_blkdev(SD_MAJOR(i),"sd",&sd_fops)) { printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(i)); return 1; } } sd_registered++; } /* We do not support attaching loadable devices yet. */ if(rscsi_disks) return 0; rscsi_disks = (Scsi_Disk *) scsi_init_malloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC); memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk)); /* for every (necessary) major: */ sd_sizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int)); sd_blocksizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC); for(i=0; i < sd_template.dev_max << 4; i++) { sd_blocksizes[i] = 1024; sd_hardsizes[i] = 512; } 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); } sd = (struct hd_struct *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(struct hd_struct), GFP_ATOMIC); if (N_USED_SD_MAJORS > 1) sd_gendisks = (struct gendisk *) kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), GFP_ATOMIC); for (i=0; i < N_USED_SD_MAJORS; i++) { 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].max_nr = SCSI_DISKS_PER_MAJOR; sd_gendisks[i].init = sd_geninit; 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].next = sd_gendisks + i + 1; sd_gendisks[i].real_devices = (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR); } LAST_SD_GENDISK.max_nr = (sd_template.dev_max -1 ) % SCSI_DISKS_PER_MAJOR + 1; LAST_SD_GENDISK.next = NULL; return 0;}/* * sd_get_queue() returns the queue which corresponds to a given device. */static struct request **sd_get_queue (kdev_t dev){ return &blk_dev[MAJOR_NR].current_request;}static void sd_finish(){ struct gendisk *gendisk; int i; for (i=0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) { /* FIXME: After 2.2 we should implement multiple sd queues */ blk_dev[SD_MAJOR(i)].request_fn = DEVICE_REQUEST; if (i) blk_dev[SD_MAJOR(i)].queue = sd_get_queue; } for (gendisk = gendisk_head; gendisk != NULL; gendisk = gendisk->next) if (gendisk == sd_gendisks) break; if (gendisk == NULL) { LAST_SD_GENDISK.next = gendisk_head; gendisk_head = sd_gendisks; } for (i = 0; i < sd_template.dev_max; ++i) if (!rscsi_disks[i].capacity && rscsi_disks[i].device) { if (MODULE_FLAG && !rscsi_disks[i].has_part_table) { sd_sizes[i << 4] = rscsi_disks[i].capacity; /* revalidate does sd_init_onedisk via MAYBE_REINIT*/ revalidate_scsidisk(MKDEV_SD(i), 0); } else i=sd_init_onedisk(i); 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){ char nbuff[6]; if(SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) return 0; sd_devname(sd_template.dev_noticed++, nbuff); printk("Detected 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 1;}static int sd_attach(Scsi_Device * SDp){ Scsi_Disk * dpnt; int i; if(SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) return 0; if(sd_template.nr_dev >= sd_template.dev_max) { 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) panic ("scsi_devices corrupt (sd)"); SDp->scsi_request_fn = do_sd_request; rscsi_disks[i].device = SDp; rscsi_disks[i].has_part_table = 0; sd_template.nr_dev++; SD_GENDISK(i).nr_real++; return 0;}#define DEVICE_BUSY rscsi_disks[target].device->busy#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 || 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; kdev_t devi = MKDEV_SD_PARTITION(index); struct super_block *sb = get_super(devi); sync_dev(devi); if (sb) invalidate_inodes(sb); invalidate_buffers(devi); 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].sector_size == 2048 ) sd_blocksizes[index] = 2048; else sd_blocksizes[index] = 1024; }#ifdef MAYBE_REINIT MAYBE_REINIT;#endif sd_gendisks->part[start].nr_sects = CAPACITY; resetup_one_dev(&SD_GENDISK(target), target % SCSI_DISKS_PER_MAJOR); 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; 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; kdev_t devi = MKDEV_SD_PARTITION(index); struct super_block *sb = get_super(devi); sync_dev(devi); if (sb) invalidate_inodes(sb); invalidate_buffers(devi); sd_gendisks->part[index].start_sect = 0; sd_gendisks->part[index].nr_sects = 0; sd_sizes[index] = 0; } 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;}#ifdef MODULEint init_module(void) { sd_template.module = &__this_module; return scsi_register_module(MODULE_SCSI_DEV, &sd_template);}void cleanup_module( void){ struct gendisk ** prev_sdgd_link; struct gendisk * sdgd; int i; int removed = 0; scsi_unregister_module(MODULE_SCSI_DEV, &sd_template); for (i=0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) unregister_blkdev(SD_MAJOR(i),"sd"); sd_registered--; if( rscsi_disks != NULL ) { scsi_init_free((char *) rscsi_disks, sd_template.dev_max * sizeof(Scsi_Disk)); scsi_init_free((char *) sd_sizes, sd_template.dev_max * sizeof(int)); scsi_init_free((char *) sd_blocksizes, sd_template.dev_max * sizeof(int)); scsi_init_free((char *) sd_hardsizes, sd_template.dev_max * sizeof(int)); scsi_init_free((char *) sd, (sd_template.dev_max << 4) * sizeof(struct hd_struct)); /* * Now remove sd_gendisks from the linked list */ prev_sdgd_link = &gendisk_head; while ((sdgd = *prev_sdgd_link) != NULL) { if (sdgd >= sd_gendisks && sdgd <= &LAST_SD_GENDISK) { removed++; *prev_sdgd_link = sdgd->next; continue; } prev_sdgd_link = &sdgd->next; } if (removed != N_USED_SD_MAJORS) printk("%s %d sd_gendisks in disk chain", removed > N_USED_SD_MAJORS ? "total" : "just", removed); } for (i=0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) { blk_dev[SD_MAJOR(i)].request_fn = NULL; 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);}#endif /* MODULE *//* * Overrides for Emacs so that we almost 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: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -