?? sr.c
字號:
tries = 2; goto repeat; } if (scsi_CDs[dev].device->changed) {/* * quietly refuse to do anything to a changed disc until the changed bit has been reset */ /* printk("CD-ROM has been changed. Prohibiting further I/O.\n"); */ end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); tries = 2; goto repeat; } switch (SCpnt->request.cmd) { case WRITE: end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); goto repeat; break; case READ : cmd[0] = READ_6; break; default : panic ("Unknown sr command %d\n", SCpnt->request.cmd); } cmd[1] = (SCpnt->lun << 5) & 0xe0;/* Now do the grungy work of figuring out which sectors we need, and where in memory we are going to put them. The variables we need are: this_count= number of 512 byte sectors being read block = starting cdrom sector to read. realcount = # of cdrom sectors to read The major difference between a scsi disk and a scsi cdromis that we will always use scatter-gather if we can, because we canwork around the fact that the buffer cache has a block size of 1024,and we have 2048 byte sectors. This code should work for buffers thatare any multiple of 512 bytes long. */ SCpnt->use_sg = 0; if (SCpnt->host->sg_tablesize > 0 && (!need_isa_buffer || dma_free_sectors >= 10)) { struct buffer_head * bh; struct scatterlist * sgpnt; int count, this_count_max; bh = SCpnt->request.bh; this_count = 0; count = 0; this_count_max = (scsi_CDs[dev].ten ? 0xffff : 0xff) << 4; /* Calculate how many links we can use. First see if we need a padding record at the start */ this_count = SCpnt->request.sector % 4; if(this_count) count++; while(bh && count < SCpnt->host->sg_tablesize) { if ((this_count + (bh->b_size >> 9)) > this_count_max) break; this_count += (bh->b_size >> 9); count++; bh = bh->b_reqnext; }; /* Fix up in case of an odd record at the end */ end_rec = 0; if(this_count % 4) { if (count < SCpnt->host->sg_tablesize) { count++; end_rec = (4 - (this_count % 4)) << 9; this_count += 4 - (this_count % 4); } else { count--; this_count -= (this_count % 4); }; }; SCpnt->use_sg = count; /* Number of chains */ count = 512;/* scsi_malloc can only allocate in chunks of 512 bytes*/ while( count < (SCpnt->use_sg * sizeof(struct scatterlist))) count = count << 1; SCpnt->sglist_len = count; sgpnt = (struct scatterlist * ) scsi_malloc(count); if (!sgpnt) { printk("Warning - running *really* short on DMA buffers\n"); SCpnt->use_sg = 0; /* No memory left - bail out */ } else { buffer = (unsigned char *) sgpnt; count = 0; bh = SCpnt->request.bh; if(SCpnt->request.sector % 4) { sgpnt[count].length = (SCpnt->request.sector % 4) << 9; sgpnt[count].address = (char *) scsi_malloc(sgpnt[count].length); if(!sgpnt[count].address) panic("SCSI DMA pool exhausted."); sgpnt[count].alt_address = sgpnt[count].address; /* Flag to delete if needed */ count++; }; for(bh = SCpnt->request.bh; count < SCpnt->use_sg; count++, bh = bh->b_reqnext) { if (bh) { /* Need a placeholder at the end of the record? */ sgpnt[count].address = bh->b_data; sgpnt[count].length = bh->b_size; sgpnt[count].alt_address = NULL; } else { sgpnt[count].address = (char *) scsi_malloc(end_rec); if(!sgpnt[count].address) panic("SCSI DMA pool exhausted."); sgpnt[count].length = end_rec; sgpnt[count].alt_address = sgpnt[count].address; if (count+1 != SCpnt->use_sg) panic("Bad sr request list"); break; }; if (((int) sgpnt[count].address) + sgpnt[count].length > ISA_DMA_THRESHOLD & (SCpnt->host->unchecked_isa_dma)) { sgpnt[count].alt_address = sgpnt[count].address; /* We try and 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("SG: %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 (((int) 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 SCpnt->this_count = this_count; scsi_do_cmd (SCpnt, (void *) cmd, buffer, realcount * scsi_CDs[dev].sector_size, rw_intr, SR_TIMEOUT, MAX_RETRIES);}unsigned long sr_init1(unsigned long mem_start, unsigned long mem_end){ scsi_CDs = (Scsi_CD *) mem_start; mem_start += MAX_SR * sizeof(Scsi_CD); return mem_start;};void sr_attach(Scsi_Device * SDp){ scsi_CDs[NR_SR++].device = SDp; if(NR_SR > MAX_SR) panic ("scsi_devices corrupt (sr)");};static void sr_init_done (Scsi_Cmnd * SCpnt){ struct request * req; struct task_struct * p; req = &SCpnt->request; req->dev = 0xfffe; /* Busy, but indicate request done */ if ((p = req->waiting) != NULL) { req->waiting = NULL; p->state = TASK_RUNNING; if (p->counter > current->counter) need_resched = 1; }}static void get_sectorsize(int i){ unsigned char cmd[10]; unsigned char buffer[513]; int the_result, retries; Scsi_Cmnd * SCpnt; SCpnt = allocate_device(NULL, scsi_CDs[i].device->index, 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.dev = 0xffff; /* Mark as really busy */ memset(buffer, 0, 8); scsi_do_cmd (SCpnt, (void *) cmd, (void *) buffer, 512, sr_init_done, SR_TIMEOUT, MAX_RETRIES); if (current == task[0]) while(SCpnt->request.dev != 0xfffe); else if (SCpnt->request.dev != 0xfffe){ SCpnt->request.waiting = current; current->state = TASK_UNINTERRUPTIBLE; while (SCpnt->request.dev != 0xfffe) schedule(); }; the_result = SCpnt->result; retries--; } while(the_result && retries); SCpnt->request.dev = -1; /* Mark as not busy */ wake_up(&scsi_devices[SCpnt->index].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 = (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]; if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048; if(scsi_CDs[i].sector_size != 2048 && scsi_CDs[i].sector_size != 512) { printk ("scd%d : unsupported sector size %d.\n", i, scsi_CDs[i].sector_size); scsi_CDs[i].capacity = 0; scsi_CDs[i].needs_sector_size = 1; }; if(scsi_CDs[i].sector_size == 2048) scsi_CDs[i].capacity *= 4; scsi_CDs[i].needs_sector_size = 0; };}unsigned long sr_init(unsigned long memory_start, unsigned long memory_end){ int i; if (register_blkdev(MAJOR_NR,"sr",&sr_fops)) { printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR); return memory_start; } if(MAX_SR == 0) return memory_start; sr_sizes = (int *) memory_start; memory_start += MAX_SR * sizeof(int); memset(sr_sizes, 0, MAX_SR * sizeof(int)); sr_blocksizes = (int *) memory_start; memory_start += MAX_SR * sizeof(int); for(i=0;i<MAX_SR;i++) sr_blocksizes[i] = 2048; blksize_size[MAJOR_NR] = sr_blocksizes; for (i = 0; i < NR_SR; ++i) { get_sectorsize(i); printk("Scd sectorsize = %d bytes\n", scsi_CDs[i].sector_size); scsi_CDs[i].use = 1; scsi_CDs[i].ten = 1; scsi_CDs[i].remap = 1; sr_sizes[i] = scsi_CDs[i].capacity; } blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; blk_size[MAJOR_NR] = sr_sizes; /* 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->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 memory_start;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -