📄 sd.c
字号:
* 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);#ifdef MACH printk ("SCSI device sd%d: hdwr sector= %d bytes." " Sectors= %d [%d MB] [%d.%1d GB]\n", i, hard_sector, rscsi_disks[i].capacity, mb, sz_quot, sz_rem);#else printk ("SCSI device sd%c: hdwr sector= %d bytes." " Sectors= %d [%d MB] [%d.%1d GB]\n", i+'a', hard_sector, rscsi_disks[i].capacity, mb, sz_quot, sz_rem);#endif } 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); down(&sem); } the_result = SCpnt->result; SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */ wake_up(&SCpnt->device->device_wait); if ( the_result ) {#ifdef MACH printk ("sd%d: test WP failed, assume Write Protected\n",i);#else printk ("sd%c: test WP failed, assume Write Protected\n",i+'a');#endif rscsi_disks[i].write_prot = 1; } else { rscsi_disks[i].write_prot = ((buffer[2] & 0x80) != 0);#ifdef MACH printk ("sd%d: Write Protect is %s\n",i, rscsi_disks[i].write_prot ? "on" : "off");#else printk ("sd%c: Write Protect is %s\n",i+'a', rscsi_disks[i].write_prot ? "on" : "off");#endif } } /* check for write protect */ rscsi_disks[i].ten = 1; rscsi_disks[i].remap = 1; 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 = 0;static int sd_init(){ int i; if (sd_template.dev_noticed == 0) return 0; if(!sd_registered) { if (register_blkdev(MAJOR_NR,"sd",&sd_fops)) { printk("Unable to get major %d for SCSI disk\n",MAJOR_NR); return 1; } sd_registered++; } /* We do not support attaching loadable devices yet. */ if(rscsi_disks) return 0; sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS; 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)); 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; } blksize_size[MAJOR_NR] = sd_blocksizes; hardsect_size[MAJOR_NR] = sd_hardsizes; sd = (struct hd_struct *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(struct hd_struct), GFP_ATOMIC); sd_gendisk.max_nr = sd_template.dev_max; sd_gendisk.part = sd; sd_gendisk.sizes = sd_sizes; sd_gendisk.real_devices = (void *) rscsi_disks; return 0;}static void sd_finish(void){ struct gendisk *gendisk; int i; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; for (gendisk = gendisk_head; gendisk != NULL; gendisk = gendisk->next) if (gendisk == &sd_gendisk) break; if (gendisk == NULL) { sd_gendisk.next = gendisk_head; gendisk_head = &sd_gendisk; } 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(MAJOR_NR, i << 4), 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 16 blocks (32 sectors). If not, we use * a two block (4 sector) read ahead. */ if(rscsi_disks[0].device && rscsi_disks[0].device->host->sg_tablesize) read_ahead[MAJOR_NR] = 120; /* 120 sector read-ahead */ else read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */ return;}static int sd_detect(Scsi_Device * SDp){ if(SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) return 0;#ifdef MACH printk("Detected scsi %sdisk sd%d at scsi%d, channel %d, id %d, lun %d\n", SDp->removable ? "removable " : "", sd_template.dev_noticed++, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);#else printk("Detected scsi %sdisk sd%c at scsi%d, channel %d, id %d, lun %d\n", SDp->removable ? "removable " : "", 'a'+ (sd_template.dev_noticed++), SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);#endif 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.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)#define GENDISK_STRUCT sd_gendisk/* 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; struct gendisk * gdev; unsigned long flags; int max_p; int start; int i; target = DEVICE_NR(dev); gdev = &GENDISK_STRUCT; save_flags(flags); cli(); if (DEVICE_BUSY || USAGE > maxusage) { restore_flags(flags); printk("Device busy for revalidation (usage=%d)\n", USAGE); return -EBUSY; } DEVICE_BUSY = 1; restore_flags(flags); max_p = gdev->max_p; start = target << gdev->minor_shift; for (i=max_p - 1; i >=0 ; i--) { int minor = start+i; kdev_t devi = MKDEV(MAJOR_NR, minor); sync_dev(devi); invalidate_inodes(devi); invalidate_buffers(devi); gdev->part[minor].start_sect = 0; gdev->part[minor].nr_sects = 0; /* * Reset the blocksize for everything so that we can read * the partition table. */ blksize_size[MAJOR_NR][minor] = 1024; } #ifdef MAYBE_REINIT MAYBE_REINIT;#endif gdev->part[start].nr_sects = CAPACITY; resetup_one_dev(gdev, target); 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; 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 (i=max_p - 1; i >=0 ; i--) { int minor = start+i; kdev_t devi = MKDEV(MAJOR_NR, minor); sync_dev(devi); invalidate_inodes(devi); invalidate_buffers(devi); sd_gendisk.part[minor].start_sect = 0; sd_gendisk.part[minor].nr_sects = 0; sd_sizes[minor] = 0; } dpnt->has_part_table = 0; dpnt->device = NULL; dpnt->capacity = 0; SDp->attached--; sd_template.dev_noticed--; sd_template.nr_dev--; sd_gendisk.nr_real--; return; } return;}#ifdef MODULEint init_module(void) { sd_template.usage_count = &mod_use_count_; return scsi_register_module(MODULE_SCSI_DEV, &sd_template);}void cleanup_module( void) { struct gendisk * prev_sdgd; struct gendisk * sdgd; scsi_unregister_module(MODULE_SCSI_DEV, &sd_template); unregister_blkdev(SCSI_DISK_MAJOR, "sd"); sd_registered--; if( rscsi_disks != NULL ) { scsi_init_free((char *) rscsi_disks, (sd_template.dev_noticed + SD_EXTRA_DEVS) * 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_gendisk from the linked list */ sdgd = gendisk_head; prev_sdgd = NULL; while(sdgd != &sd_gendisk) { prev_sdgd = sdgd; sdgd = sdgd->next; } if(sdgd != &sd_gendisk) printk("sd_gendisk not in disk chain.\n"); else { if(prev_sdgd != NULL) prev_sdgd->next = sdgd->next; else gendisk_head = sdgd->next; } } blksize_size[MAJOR_NR] = NULL; blk_dev[MAJOR_NR].request_fn = NULL; blk_size[MAJOR_NR] = NULL; hardsect_size[MAJOR_NR] = NULL; read_ahead[MAJOR_NR] = 0; sd_template.dev_max = 0;}#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 + -