📄 sr.c
字号:
}; if (!SCpnt) return; /* Could not find anything to do */ wake_up(&wait_for_request);/* Queue command */ requeue_sr_request(SCpnt); }; /* While */} void requeue_sr_request (Scsi_Cmnd * SCpnt){ unsigned int dev, block, realcount; unsigned char cmd[10], *buffer, tries; int this_count, start, end_rec; tries = 2; repeat: if(SCpnt->request.dev <= 0) return do_sr_request(); dev = MINOR(SCpnt->request.dev); block = SCpnt->request.sector; buffer = NULL; this_count = 0; if (dev >= NR_SR) { /* printk("CD-ROM request error: invalid device.\n"); */ end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); tries = 2; goto repeat; } if (!scsi_CDs[dev].use) { /* printk("CD-ROM request error: device marked not in use.\n"); */ end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); 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 : printk ("Unknown sr command %d\r\n", SCpnt->request.cmd); panic(""); } 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 (scsi_hosts[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 < scsi_hosts[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 < scsi_hosts[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 = (char *) sgpnt; count = 0; bh = SCpnt->request.bh; if(SCpnt->request.sector % 4) { sgpnt[count].length = (SCpnt->request.sector % 4) << 9; sgpnt[count].address = 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 = 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 & (scsi_hosts[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 = 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){ 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 = scsi_malloc(2048); } else if (this_count < 4) { buffer = scsi_malloc(2048); } else { this_count -= this_count % 4; buffer = SCpnt->request.buffer; if (((int) buffer) + (this_count << 9) > ISA_DMA_THRESHOLD & (scsi_hosts[SCpnt->host].unchecked_isa_dma)) buffer = scsi_malloc(this_count << 9); } }; block = block >> 2; /* These are the sectors that the cdrom uses */ realcount = (this_count + 3) / 4; if (((realcount > 0xff) || (block > 0x1fffff)) && scsi_CDs[dev].ten) { if (realcount > 0xffff) { realcount = 0xffff; this_count = realcount * 4; } 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 * 4; } 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 printk("ReadCD: %d %d %d\n",block, realcount, buffer);#endif SCpnt->this_count = this_count; scsi_do_cmd (SCpnt, (void *) cmd, buffer, realcount << 11, 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)");};unsigned long sr_init(unsigned long memory_start, unsigned long memory_end){ int i; 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)); for (i = 0; i < NR_SR; ++i) { scsi_CDs[i].capacity = 0x1fffff; scsi_CDs[i].sector_size = 2048; 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 8 blocks (16 sectors). If not, we use a two block (4 sector) read ahead. */ if(scsi_hosts[scsi_CDs[0].device->host_no].sg_tablesize) read_ahead[MAJOR_NR] = 16; /* 16 sector read-ahead */ else read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */ blkdev_fops[MAJOR_NR] = &sr_fops; return memory_start;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -