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

📄 sd.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 4 页
字号:
		    /* If we are allowed another sg chain, then increment 		     * counter so we can insert it.  Otherwise we will end 		     up truncating */		    		    if (SCpnt->use_sg < max_sg) SCpnt->use_sg++;		}  /* contiguous buffers */	    } /* for loop */	    	    /* This is actually how many we are going to transfer */	    this_count = counted; 	    	    if(count < SCpnt->use_sg || SCpnt->use_sg 	       > SCpnt->host->sg_tablesize){		bh = SCpnt->request.bh;		printk("Use sg, count %d %x %d\n", 		       SCpnt->use_sg, count, dma_free_sectors);		printk("maxsg = %x, counted = %d this_count = %d\n", 		       max_sg, counted, this_count);		while(bh){		    printk("[%p %lx] ", bh->b_data, bh->b_size);		    bh = bh->b_reqnext;		}		if(SCpnt->use_sg < 16)		    for(count=0; count<SCpnt->use_sg; count++)			printk("{%d:%p %p %d}  ", count,			       sgpnt[count].address,			       sgpnt[count].alt_address,			       sgpnt[count].length);		panic("Ooops");	    }	    	    if (SCpnt->request.cmd == WRITE)		for(count=0; count<SCpnt->use_sg; count++)		    if(sgpnt[count].alt_address)			memcpy(sgpnt[count].address, sgpnt[count].alt_address, 			       sgpnt[count].length);	}  /* Able to malloc sgpnt */    }  /* Host adapter capable of scatter-gather */        /* Now handle the possibility of DMA to addresses > 16Mb */        if(SCpnt->use_sg == 0){	if (((long) buff) + (this_count << 9) - 1 > ISA_DMA_THRESHOLD && 	    (SCpnt->host->unchecked_isa_dma)) {	    if(bounce_buffer)		buff = bounce_buffer;	    else		buff = (char *) scsi_malloc(this_count << 9);	    if(buff == NULL) {  /* Try backing off a bit if we are low on mem*/		this_count = SCpnt->request.current_nr_sectors;		buff = (char *) scsi_malloc(this_count << 9);		if(!buff) panic("Ran out of DMA buffers.");	    }	    if (SCpnt->request.cmd == WRITE)		memcpy(buff, (char *)SCpnt->request.buffer, this_count << 9);	}    }#ifdef DEBUG    printk("sd%c : %s %d/%d 512 byte blocks.\n", 	   'a' + devm,	   (SCpnt->request.cmd == WRITE) ? "writing" : "reading",	   this_count, SCpnt->request.nr_sectors);#endif        cmd[1] = (SCpnt->lun << 5) & 0xe0;        if (rscsi_disks[dev].sector_size == 1024){	if(block & 1) panic("sd.c:Bad block number requested");	if(this_count & 1) panic("sd.c:Bad block number requested");	block = block >> 1;	this_count = this_count >> 1;    }        if (rscsi_disks[dev].sector_size == 256){	block = block << 1;	this_count = this_count << 1;    }        if (((this_count > 0xff) ||  (block > 0x1fffff)) && rscsi_disks[dev].ten)    {	if (this_count > 0xffff)	    this_count = 0xffff;		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) (this_count >> 8) & 0xff;	cmd[8] = (unsigned char) this_count & 0xff;    }    else    {	if (this_count > 0xff)	    this_count = 0xff;		cmd[1] |= (unsigned char) ((block >> 16) & 0x1f);	cmd[2] = (unsigned char) ((block >> 8) & 0xff);	cmd[3] = (unsigned char) block & 0xff;	cmd[4] = (unsigned char) this_count;	cmd[5] = 0;    }        /*     * We shouldn't disconnect in the middle of a sector, so with a dumb      * host adapter, it's safe to assume that we can at least transfer      * this many bytes between each connect / disconnect.       */        SCpnt->transfersize = rscsi_disks[dev].sector_size;    SCpnt->underflow = this_count << 9;     scsi_do_cmd (SCpnt, (void *) cmd, buff, 		 this_count * rscsi_disks[dev].sector_size,		 rw_intr, 		 (SCpnt->device->type == TYPE_DISK ? 		  SD_TIMEOUT : SD_MOD_TIMEOUT),		 MAX_RETRIES);}static int check_scsidisk_media_change(kdev_t full_dev){    int retval;    int target;    struct inode inode;    int flag = 0;        target =  DEVICE_NR(full_dev);        if (target >= sd_template.dev_max ||	!rscsi_disks[target].device) {	printk("SCSI disk request error: invalid device.\n");	return 0;    }        if(!rscsi_disks[target].device->removable) return 0;        inode.i_rdev = full_dev;  /* This is all we really need here */    /* Using Start/Stop enables differentiation between drive with     * no cartridge loaded - NOT READY, drive with changed cartridge -     * UNIT ATTENTION, or with same cartridge - GOOD STATUS.     * This also handles drives that auto spin down. eg iomega jaz 1GB     * as this will spin up the drive.     */    retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_START_UNIT, 0);        if(retval){ /* Unable to test, unit probably not ready.  This usually		 * means there is no disc in the drive.  Mark as changed,		 * and we will figure it out later once the drive is		 * available again.  */		rscsi_disks[target].ready = 0;	rscsi_disks[target].device->changed = 1;	return 1; /* This will force a flush, if called from		   * check_disk_change */    }        /*      * for removable scsi disk ( FLOPTICAL ) we have to recognise the     * presence of disk in the drive. This is kept in the Scsi_Disk     * struct and tested at open !  Daniel Roche ( dan@lectra.fr )      */        rscsi_disks[target].ready = 1;	/* FLOPTICAL */    retval = rscsi_disks[target].device->changed;    if(!flag) rscsi_disks[target].device->changed = 0;    return retval;}static void sd_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);    }}static int sd_init_onedisk(int i){    unsigned char cmd[10];    unsigned char *buffer;    unsigned long spintime;    int the_result, retries;    Scsi_Cmnd * SCpnt;        /* We need to retry the READ_CAPACITY because a UNIT_ATTENTION is      * considered a fatal error, and many devices report such an error      * just after a scsi bus reset.      */        SCpnt = allocate_device(NULL, rscsi_disks[i].device, 1);    buffer = (unsigned char *) scsi_malloc(512);        spintime = 0;        /* Spin up drives, as required.  Only do this at boot time */    /* Spinup needs to be done for module loads too. */	do{	    retries = 0;	    while(retries < 3)	    {		cmd[0] = TEST_UNIT_READY;		cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;		memset ((void *) &cmd[2], 0, 8);		SCpnt->cmd_len = 0;		SCpnt->sense_buffer[0] = 0;		SCpnt->sense_buffer[2] = 0;		{		    struct semaphore sem = MUTEX_LOCKED;		    /* Mark as really busy again */		    SCpnt->request.rq_status = RQ_SCSI_BUSY;		    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;		retries++;		if(   the_result == 0		   || SCpnt->sense_buffer[2] != UNIT_ATTENTION)		    break;	    }	    	    /* Look for non-removable devices that return NOT_READY.  	     * Issue command to spin up drive for these cases. */	    if(the_result && !rscsi_disks[i].device->removable && 	       SCpnt->sense_buffer[2] == NOT_READY) {		unsigned long time1;		if(!spintime){#ifdef MACH                    printk( "sd%d: Spinning up disk...", i);#else		    printk( "sd%c: Spinning up disk...", 'a' + i );#endif		    cmd[0] = START_STOP;		    cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;		    cmd[1] |= 1;  /* Return immediately */		    memset ((void *) &cmd[2], 0, 8);		    cmd[4] = 1; /* Start spin cycle */		    SCpnt->cmd_len = 0;		    SCpnt->sense_buffer[0] = 0;		    SCpnt->sense_buffer[2] = 0;		    		    {		    	struct semaphore sem = MUTEX_LOCKED;			/* Mark as really busy again */			SCpnt->request.rq_status = RQ_SCSI_BUSY; 		    	SCpnt->request.sem = &sem;			scsi_do_cmd (SCpnt,				     (void *) cmd, (void *) buffer,				     512, sd_init_done,  SD_TIMEOUT,				     MAX_RETRIES);			down(&sem);		    }		    		    spintime = jiffies;		}				time1 = jiffies + HZ;		while(jiffies < time1); /* Wait 1 second for next try */		printk( "." );	    }	} while(the_result && spintime && spintime+100*HZ > jiffies);	if (spintime) {	    if (the_result)		printk( "not responding...\n" );	    else		printk( "ready\n" );	}        retries = 3;    do {	cmd[0] = READ_CAPACITY;	cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;	memset ((void *) &cmd[2], 0, 8);	memset ((void *) buffer, 0, 8);	SCpnt->cmd_len = 0;	SCpnt->sense_buffer[0] = 0;	SCpnt->sense_buffer[2] = 0;	{	    struct semaphore sem = MUTEX_LOCKED;	    /* Mark as really busy again */	    SCpnt->request.rq_status = RQ_SCSI_BUSY;	    SCpnt->request.sem = &sem;	    scsi_do_cmd (SCpnt,			 (void *) cmd, (void *) buffer,			 8, sd_init_done,  SD_TIMEOUT,			 MAX_RETRIES);	    down(&sem);	/* sleep until it is ready */	}		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);         /* Wake up a process waiting for device */        /*     * The SCSI standard says:      * "READ CAPACITY is necessary for self configuring software"     *  While not mandatory, support of READ CAPACITY is strongly encouraged.     *  We used to die if we couldn't successfully do a READ CAPACITY.     *  But, now we go on about our way.  The side effects of this are     *     *  1. We can't know block size with certainty. I have said "512 bytes      *     is it" as this is most common.     *     *  2. Recovery from when some one attempts to read past the end of the      *     raw device will be slower.     */        if (the_result)    {#ifdef MACH	printk ("sd%d : READ CAPACITY failed.\n"		"sd%d : status = %x, message = %02x, host = %d, driver = %02x \n",                i, i,#else	printk ("sd%c : READ CAPACITY failed.\n"		"sd%c : status = %x, message = %02x, host = %d, driver = %02x \n",		'a' + i, 'a' + i,#endif		status_byte(the_result),		msg_byte(the_result),		host_byte(the_result),		driver_byte(the_result)		);	if (driver_byte(the_result)  & DRIVER_SENSE)#ifdef MACH	    printk("sd%d : extended sense code = %1x \n", 		   i, SCpnt->sense_buffer[2] & 0xf);#else	    printk("sd%c : extended sense code = %1x \n", 		   'a' + i, SCpnt->sense_buffer[2] & 0xf);#endif	else#ifdef MACH	    printk("sd%d : sense not available. \n", i);#else	    printk("sd%c : sense not available. \n", 'a' + i);#endif#ifdef MACH	printk("sd%d : block size assumed to be 512 bytes, disk size 1GB.  \n",	       i);#else	printk("sd%c : block size assumed to be 512 bytes, disk size 1GB.  \n",	       'a' + i);#endif	rscsi_disks[i].capacity = 0x1fffff;	rscsi_disks[i].sector_size = 512;		/* Set dirty bit for removable devices if not ready - sometimes drives	 * will not report this properly. */	if(rscsi_disks[i].device->removable && 	   SCpnt->sense_buffer[2] == NOT_READY)	    rscsi_disks[i].device->changed = 1;	    }    else    {	/*	 * FLOPTICAL , if read_capa is ok , drive is assumed to be ready 	 */	rscsi_disks[i].ready = 1;	rscsi_disks[i].capacity = 1 + ((buffer[0] << 24) |				       (buffer[1] << 16) |				       (buffer[2] << 8) |				       buffer[3]);		rscsi_disks[i].sector_size = (buffer[4] << 24) |	    (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];	if (rscsi_disks[i].sector_size == 0) {	  rscsi_disks[i].sector_size = 512;#ifdef MACH	  printk("sd%d : sector size 0 reported, assuming 512.\n", i);#else	  printk("sd%c : sector size 0 reported, assuming 512.\n", 'a' + i);#endif	} 		if (rscsi_disks[i].sector_size != 512 &&	    rscsi_disks[i].sector_size != 1024 &&	    rscsi_disks[i].sector_size != 256)	{#ifdef MACH	    printk ("sd%d : unsupported sector size %d.\n",		    i, rscsi_disks[i].sector_size);#else	    printk ("sd%c : unsupported sector size %d.\n",		    'a' + i, rscsi_disks[i].sector_size);#endif	    if(rscsi_disks[i].device->removable){		rscsi_disks[i].capacity = 0;	    } else {		printk ("scsi : deleting disk entry.\n");		rscsi_disks[i].device = NULL;		sd_template.nr_dev--;		sd_gendisk.nr_real--;		return i;	    }	}    {	/*	 * The msdos fs needs to know the hardware sector size

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -