⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sr.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 3 页
字号:
		};		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 + -