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

📄 scsi_lib.c.txt

📁 linux内核学习笔记 希望想看的人可以很快下载到
💻 TXT
字号:
any problems, send mails to lysindybear@sina.com.cn


相关文件
	/drivers/scsi/sd.c
	
这个程序文件主要提供scsi驱动程序的统一接口,当上层的块设备驱动程序将request送下来以后,
他负责接收这些request并进行包装成scsi命令,然后选择相应的设备送下去。


这个就是接受从高层来的request队列的接口函数,也就是所有scsi层的开始
void scsi_request_fn(request_queue_t * q)
	while (1 == 1) {	//无限循环
		req = blkdev_entry_next_request(&q->queue_head);//从request队列中取一个request
		if (req->cmd == SPECIAL) {	//如果request是特殊的,比如失败的request等
			……			//分配scsi命令等处理
		} else {			//否则就是一个正常的request请求,也就是新来的
			STpnt = scsi_get_request_dev(req);//从这个request中取出要送到的设备
			……	//检查设备的有效性
			SCpnt = scsi_allocate_device(SDpnt, FALSE, FALSE);//生成一个scsi命令
			if (!SCpnt) {
				atomic_dec(&SHpnt->host_busy);
				break;
			}	//这里很重要,如果设备忙的话,可能分配不到scsi命令,就直接跳出
				//循环,因为request并没有从队列中摘掉,所以这个request还是有机会
				//被再次检索到,并分配scsi命令的
			if (SCpnt->request.cmd != SPECIAL) {	//如果是正常的scsi命令
				if (!SDpnt->scsi_init_io_fn(SCpnt)) {
				if (req->special != SCpnt)
					__scsi_release_command(SCpnt);
				atomic_dec(&SHpnt->host_busy);
				break;
			}	//这里的init主要做的事情是进行scatter_list操作
			if (!STpnt->init_command(SCpnt)) {	//这里进行真正的初始化操作
				……	//如果不成功,销毁这个request
			}
			scsi_init_cmd_errh(SCpnt);	//初始化这个scsi命令的错误处理部分
			atomic_inc(&SDpnt->device_busy);//相应设备的忙状态加一	
			blkdev_dequeue_request(req);	//将request从队列中摘掉
			if (req != &SCpnt->request && req != &SRpnt->sr_request ) {
				blkdev_release_request(req);	
			}//可以释放掉request,因为request中的数据都复制到了scsi命令中了
			scsi_dispatch_cmd(SCpnt);	//发布这个scsi命令
	}


从这个request中找到相应的scsi设备的模板,设备模板中就包含了各种各样的处理函数
struct Scsi_Device_Template *scsi_get_request_dev(struct request *req)
	for (spnt = scsi_devicelist; spnt; spnt = spnt->next) {	//循环查找scsi设备链
		if (spnt->blk && spnt->major == major) {	//如果找到了设备好一致的
			return spnt;				//返回给用户
		}
	}
	……	//错误处理


这个函数是当一个scsi命令处理完毕以后,进行后面的收尾工作,
void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
			int block_sectors)
		char *to = bh_kmap_irq(req->bh, &flags);	
		memcpy(to, SCpnt->buffer, SCpnt->bufflen);//将数据复制到bh中去
		bh_kunmap_irq(to, &flags);
		scsi_free(SCpnt->buffer, SCpnt->bufflen); //释放request中的内存

		SCpnt->buffer  = NULL;	//将scsi命令进行清理
		……			

		SCpnt = __scsi_end_request(SCpnt, 1, good_sectors,result == 0,1);//完成这个request
		……	//太复杂,不必细看






⌨️ 快捷键说明

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