📄 sr.c
字号:
}; if (((long) sgpnt[count].address) + sgpnt[count].length - 1 > ISA_DMA_THRESHOLD && SCpnt->host->unchecked_isa_dma) { sgpnt[count].alt_address = sgpnt[count].address; /* We try to avoid exhausting the DMA pool, since it is easier * to control usage here. In other places we might have a more * pressing need, and we would be screwed if we ran out */ if(dma_free_sectors < (sgpnt[count].length >> 9) + 5) { sgpnt[count].address = NULL; } else { sgpnt[count].address = (char *) scsi_malloc(sgpnt[count].length); }; /* If we start running low on DMA buffers, we abort the scatter-gather * operation, and free all of the memory we have allocated. We want to * ensure that all scsi operations are able to do at least a non-scatter/gather * operation */ if(sgpnt[count].address == NULL){ /* Out of dma memory */ printk("Warning: Running low on SCSI DMA buffers"); /* Try switching back to a non scatter-gather operation. */ while(--count >= 0){ if(sgpnt[count].alt_address) scsi_free(sgpnt[count].address, sgpnt[count].length); }; SCpnt->use_sg = 0; scsi_free(buffer, SCpnt->sglist_len); break; }; /* if address == NULL */ }; /* if need DMA fixup */ }; /* for loop to fill list */#ifdef DEBUG printk("SR: %d %d %d %d %d *** ",SCpnt->use_sg, SCpnt->request.sector, this_count, SCpnt->request.current_nr_sectors, SCpnt->request.nr_sectors); for(count=0; count<SCpnt->use_sg; count++) printk("SGlist: %d %x %x %x\n", count, sgpnt[count].address, sgpnt[count].alt_address, sgpnt[count].length);#endif }; /* Able to allocate scatter-gather list */ }; if (SCpnt->use_sg == 0){ /* We cannot use scatter-gather. Do this the old fashion way */ if (!SCpnt->request.bh) this_count = SCpnt->request.nr_sectors; else this_count = (SCpnt->request.bh->b_size >> 9); start = block % 4; if (start) { this_count = ((this_count > 4 - start) ? (4 - start) : (this_count)); buffer = (unsigned char *) scsi_malloc(2048); } else if (this_count < 4) { buffer = (unsigned char *) scsi_malloc(2048); } else { this_count -= this_count % 4; buffer = (unsigned char *) SCpnt->request.buffer; if (((long) buffer) + (this_count << 9) > ISA_DMA_THRESHOLD && SCpnt->host->unchecked_isa_dma) buffer = (unsigned char *) scsi_malloc(this_count << 9); } }; if (scsi_CDs[dev].sector_size == 2048) block = block >> 2; /* These are the sectors that the cdrom uses */ else block = block & 0xfffffffc; realcount = (this_count + 3) / 4; if (scsi_CDs[dev].sector_size == 512) realcount = realcount << 2; if (((realcount > 0xff) || (block > 0x1fffff)) && scsi_CDs[dev].ten) { if (realcount > 0xffff) { realcount = 0xffff; this_count = realcount * (scsi_CDs[dev].sector_size >> 9); } cmd[0] += READ_10 - READ_6 ; cmd[2] = (unsigned char) (block >> 24) & 0xff; cmd[3] = (unsigned char) (block >> 16) & 0xff; cmd[4] = (unsigned char) (block >> 8) & 0xff; cmd[5] = (unsigned char) block & 0xff; cmd[6] = cmd[9] = 0; cmd[7] = (unsigned char) (realcount >> 8) & 0xff; cmd[8] = (unsigned char) realcount & 0xff; } else { if (realcount > 0xff) { realcount = 0xff; this_count = realcount * (scsi_CDs[dev].sector_size >> 9); } cmd[1] |= (unsigned char) ((block >> 16) & 0x1f); cmd[2] = (unsigned char) ((block >> 8) & 0xff); cmd[3] = (unsigned char) block & 0xff; cmd[4] = (unsigned char) realcount; cmd[5] = 0; } #ifdef DEBUG { int i; printk("ReadCD: %d %d %d %d\n",block, realcount, buffer, this_count); printk("Use sg: %d\n", SCpnt->use_sg); printk("Dumping command: "); for(i=0; i<12; i++) printk("%2.2x ", cmd[i]); printk("\n"); };#endif /* Some dumb host adapters can speed transfers by knowing the * minimum transfersize in advance. * * We shouldn't disconnect in the middle of a sector, but the cdrom * sector size can be larger than the size of a buffer and the * transfer may be split to the size of a buffer. So it's safe to * assume that we can at least transfer the minimum of the buffer * size (1024) and the sector size between each connect / disconnect. */ SCpnt->transfersize = (scsi_CDs[dev].sector_size > 1024) ? 1024 : scsi_CDs[dev].sector_size; SCpnt->this_count = this_count; scsi_do_cmd (SCpnt, (void *) cmd, buffer, realcount * scsi_CDs[dev].sector_size, rw_intr, SR_TIMEOUT, MAX_RETRIES);}static int sr_detect(Scsi_Device * SDp){ if(SDp->type != TYPE_ROM && SDp->type != TYPE_WORM) return 0;#ifdef MACH printk("Detected scsi CD-ROM cd%d at scsi%d, channel %d, id %d, lun %d\n",#else printk("Detected scsi CD-ROM sr%d at scsi%d, channel %d, id %d, lun %d\n",#endif sr_template.dev_noticed++, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); return 1;}static int sr_attach(Scsi_Device * SDp){ Scsi_CD * cpnt; int i; if(SDp->type != TYPE_ROM && SDp->type != TYPE_WORM) return 1; if (sr_template.nr_dev >= sr_template.dev_max) { SDp->attached--; return 1; } for(cpnt = scsi_CDs, i=0; i<sr_template.dev_max; i++, cpnt++) if(!cpnt->device) break; if(i >= sr_template.dev_max) panic ("scsi_devices corrupt (sr)"); SDp->scsi_request_fn = do_sr_request; scsi_CDs[i].device = SDp; sr_template.nr_dev++; if(sr_template.nr_dev > sr_template.dev_max) panic ("scsi_devices corrupt (sr)"); return 0;}static void sr_init_done (Scsi_Cmnd * SCpnt){ struct request * req; req = &SCpnt->request; req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ if (req->sem != NULL) { up(req->sem); }}void get_sectorsize(int i){ unsigned char cmd[10]; unsigned char *buffer; int the_result, retries; Scsi_Cmnd * SCpnt; buffer = (unsigned char *) scsi_malloc(512); SCpnt = allocate_device(NULL, scsi_CDs[i].device, 1); retries = 3; do { cmd[0] = READ_CAPACITY; cmd[1] = (scsi_CDs[i].device->lun << 5) & 0xe0; memset ((void *) &cmd[2], 0, 8); SCpnt->request.rq_status = RQ_SCSI_BUSY; /* Mark as really busy */ SCpnt->cmd_len = 0; memset(buffer, 0, 8); /* Do the command and wait.. */ { struct semaphore sem = MUTEX_LOCKED; SCpnt->request.sem = &sem; scsi_do_cmd (SCpnt, (void *) cmd, (void *) buffer, 512, sr_init_done, SR_TIMEOUT, MAX_RETRIES); down(&sem); } the_result = SCpnt->result; retries--; } while(the_result && retries); SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */ wake_up(&SCpnt->device->device_wait); if (the_result) { scsi_CDs[i].capacity = 0x1fffff; scsi_CDs[i].sector_size = 2048; /* A guess, just in case */ scsi_CDs[i].needs_sector_size = 1; } else { scsi_CDs[i].capacity = 1 + ((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]); scsi_CDs[i].sector_size = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; switch (scsi_CDs[i].sector_size) { /* * HP 4020i CD-Recorder reports 2340 byte sectors * Philips CD-Writers report 2352 byte sectors * * Use 2k sectors for them.. */ case 0: case 2340: case 2352: scsi_CDs[i].sector_size = 2048; /* fall through */ case 2048: scsi_CDs[i].capacity *= 4; /* fall through */ case 512: break; default:#ifdef MACH printk ("cd%d : unsupported sector size %d.\n", i, scsi_CDs[i].sector_size);#else printk ("scd%d : unsupported sector size %d.\n", i, scsi_CDs[i].sector_size);#endif scsi_CDs[i].capacity = 0; scsi_CDs[i].needs_sector_size = 1; } scsi_CDs[i].needs_sector_size = 0; sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9); }; scsi_free(buffer, 512);}static int sr_registered = 0;static int sr_init(){ int i; if(sr_template.dev_noticed == 0) return 0; if(!sr_registered) { if (register_blkdev(MAJOR_NR,"sr",&sr_fops)) { printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR); return 1; } sr_registered++; } if (scsi_CDs) return 0; sr_template.dev_max = sr_template.dev_noticed + SR_EXTRA_DEVS; scsi_CDs = (Scsi_CD *) scsi_init_malloc(sr_template.dev_max * sizeof(Scsi_CD), GFP_ATOMIC); memset(scsi_CDs, 0, sr_template.dev_max * sizeof(Scsi_CD)); sr_sizes = (int *) scsi_init_malloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC); memset(sr_sizes, 0, sr_template.dev_max * sizeof(int)); sr_blocksizes = (int *) scsi_init_malloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC); for(i=0;i<sr_template.dev_max;i++) sr_blocksizes[i] = 2048; blksize_size[MAJOR_NR] = sr_blocksizes; return 0;}void sr_finish(){ int i; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; blk_size[MAJOR_NR] = sr_sizes; for (i = 0; i < sr_template.nr_dev; ++i) { /* If we have already seen this, then skip it. Comes up * with loadable modules. */ if (scsi_CDs[i].capacity) continue; scsi_CDs[i].capacity = 0x1fffff; scsi_CDs[i].sector_size = 2048; /* A guess, just in case */ scsi_CDs[i].needs_sector_size = 1;#if 0 /* seems better to leave this for later */ get_sectorsize(i); printk("Scd sectorsize = %d bytes.\n", scsi_CDs[i].sector_size);#endif scsi_CDs[i].use = 1; scsi_CDs[i].ten = 1; scsi_CDs[i].remap = 1; scsi_CDs[i].auto_eject = 0; /* Default is not to eject upon unmount. */ sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9); } /* 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(scsi_CDs[0].device && scsi_CDs[0].device->host->sg_tablesize) read_ahead[MAJOR_NR] = 32; /* 32 sector read-ahead. Always removable. */ else read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */ return;} static void sr_detach(Scsi_Device * SDp){ Scsi_CD * cpnt; int i; for(cpnt = scsi_CDs, i=0; i<sr_template.dev_max; i++, cpnt++) if(cpnt->device == SDp) { kdev_t devi = MKDEV(MAJOR_NR, i); /* * Since the cdrom is read-only, no need to sync the device. * We should be kind to our buffer cache, however. */ invalidate_inodes(devi); invalidate_buffers(devi); /* * Reset things back to a sane state so that one can re-load a new * driver (perhaps the same one). */ cpnt->device = NULL; cpnt->capacity = 0; SDp->attached--; sr_template.nr_dev--; sr_template.dev_noticed--; sr_sizes[i] = 0; return; } return;}#ifdef MODULEint init_module(void) { sr_template.usage_count = &mod_use_count_; return scsi_register_module(MODULE_SCSI_DEV, &sr_template);}void cleanup_module( void) { scsi_unregister_module(MODULE_SCSI_DEV, &sr_template); unregister_blkdev(SCSI_CDROM_MAJOR, "sr"); sr_registered--; if(scsi_CDs != NULL) { scsi_init_free((char *) scsi_CDs, (sr_template.dev_noticed + SR_EXTRA_DEVS) * sizeof(Scsi_CD)); scsi_init_free((char *) sr_sizes, sr_template.dev_max * sizeof(int)); scsi_init_free((char *) sr_blocksizes, sr_template.dev_max * sizeof(int)); } blksize_size[MAJOR_NR] = NULL; blk_dev[MAJOR_NR].request_fn = NULL; blk_size[MAJOR_NR] = NULL; read_ahead[MAJOR_NR] = 0; sr_template.dev_max = 0;}#endif /* MODULE *//* * Overrides for Emacs so that we 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 + -