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

📄 3w-xxxx.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct scsi_cmnd *cmd = tw_dev->srb[request_id];	void *buf;	unsigned int transfer_len;	unsigned long flags = 0;	struct scatterlist *sg = scsi_sglist(cmd);	local_irq_save(flags);	buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;	transfer_len = min(sg->length, len);	memcpy(buf, data, transfer_len);	kunmap_atomic(buf - sg->offset, KM_IRQ0);	local_irq_restore(flags);}/* This function is called by the isr to complete an inquiry command */static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id){	unsigned char *is_unit_present;	unsigned char request_buffer[36];	TW_Param *param;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n");	memset(request_buffer, 0, sizeof(request_buffer));	request_buffer[0] = TYPE_DISK; /* Peripheral device type */	request_buffer[1] = 0;	       /* Device type modifier */	request_buffer[2] = 0;	       /* No ansi/iso compliance */	request_buffer[4] = 31;	       /* Additional length */	memcpy(&request_buffer[8], "3ware   ", 8);	 /* Vendor ID */	sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id);	memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3);	tw_transfer_internal(tw_dev, request_id, request_buffer,			     sizeof(request_buffer));	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];	if (param == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Bad alignment virtual address.\n");		return 1;	}	is_unit_present = &(param->data[0]);	if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) {		tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 1;	} else {		tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 0;		tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);		return TW_ISR_DONT_RESULT;	}	return 0;} /* End tw_scsiop_inquiry_complete() *//* This function handles scsi mode_sense commands */static int tw_scsiop_mode_sense(TW_Device_Extension *tw_dev, int request_id){	TW_Param *param;	TW_Command *command_packet;	unsigned long command_que_value;	unsigned long param_value;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense()\n");	/* Only page control = 0, page code = 0x8 (cache page) supported */	if (tw_dev->srb[request_id]->cmnd[2] != 0x8) {		tw_dev->state[request_id] = TW_S_COMPLETED;		tw_state_request_finish(tw_dev, request_id);		tw_dev->srb[request_id]->result = (DID_OK << 16);		tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);		return 0;	}	/* Now read firmware cache setting for this unit */	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];	if (command_packet == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet virtual address.\n");		return 1;	}	/* Setup the command packet */	memset(command_packet, 0, sizeof(TW_Sector));	command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);	command_packet->size = 4;	command_packet->request_id = request_id;	command_packet->status = 0;	command_packet->flags = 0;	command_packet->byte6.parameter_count = 1;	/* Setup the param */	if (tw_dev->alignment_virtual_address[request_id] == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment virtual address.\n");		return 1;	}	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];	memset(param, 0, sizeof(TW_Sector));	param->table_id = TW_UNIT_INFORMATION_TABLE_BASE + tw_dev->srb[request_id]->device->id;	param->parameter_id = 7; /* unit flags */	param->parameter_size_bytes = 1;	param_value = tw_dev->alignment_physical_address[request_id];	if (param_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment physical address.\n");		return 1;	}	command_packet->byte8.param.sgl[0].address = param_value;	command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);	command_que_value = tw_dev->command_packet_physical_address[request_id];	if (command_que_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet physical address.\n");		return 1;	}	/* Now try to post the command packet */	tw_post_command_packet(tw_dev, request_id);		return 0;} /* End tw_scsiop_mode_sense() *//* This function is called by the isr to complete a mode sense command */static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int request_id){	TW_Param *param;	unsigned char *flags;	unsigned char request_buffer[8];	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n");	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];	if (param == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense_complete(): Bad alignment virtual address.\n");		return 1;	}	flags = (char *)&(param->data[0]);	memset(request_buffer, 0, sizeof(request_buffer));	request_buffer[0] = 0xf;        /* mode data length */	request_buffer[1] = 0;          /* default medium type */	request_buffer[2] = 0x10;       /* dpo/fua support on */	request_buffer[3] = 0;          /* no block descriptors */	request_buffer[4] = 0x8;        /* caching page */	request_buffer[5] = 0xa;        /* page length */	if (*flags & 0x1)		request_buffer[6] = 0x5;        /* WCE on, RCD on */	else		request_buffer[6] = 0x1;        /* WCE off, RCD on */	tw_transfer_internal(tw_dev, request_id, request_buffer,			     sizeof(request_buffer));	return 0;} /* End tw_scsiop_mode_sense_complete() *//* This function handles scsi read_capacity commands */static int tw_scsiop_read_capacity(TW_Device_Extension *tw_dev, int request_id) {	TW_Param *param;	TW_Command *command_packet;	unsigned long command_que_value;	unsigned long param_value;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity()\n");	/* Initialize command packet */	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];	if (command_packet == NULL) {		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet virtual address.\n");		return 1;	}	memset(command_packet, 0, sizeof(TW_Sector));	command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);	command_packet->size = 4;	command_packet->request_id = request_id;	command_packet->unit__hostid = TW_UNITHOST_IN(0, tw_dev->srb[request_id]->device->id);	command_packet->status = 0;	command_packet->flags = 0;	command_packet->byte6.block_count = 1;	/* Now setup the param */	if (tw_dev->alignment_virtual_address[request_id] == NULL) {		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment virtual address.\n");		return 1;	}	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];	memset(param, 0, sizeof(TW_Sector));	param->table_id = TW_UNIT_INFORMATION_TABLE_BASE + 	tw_dev->srb[request_id]->device->id;	param->parameter_id = 4;	/* unitcapacity parameter */	param->parameter_size_bytes = 4;	param_value = tw_dev->alignment_physical_address[request_id];	if (param_value == 0) {		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment physical address.\n");		return 1;	}  	command_packet->byte8.param.sgl[0].address = param_value;	command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);	command_que_value = tw_dev->command_packet_physical_address[request_id];	if (command_que_value == 0) {		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet physical address.\n");		return 1;	}	/* Now try to post the command to the board */	tw_post_command_packet(tw_dev, request_id);  	return 0;} /* End tw_scsiop_read_capacity() *//* This function is called by the isr to complete a readcapacity command */static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int request_id){	unsigned char *param_data;	u32 capacity;	char buff[8];	TW_Param *param;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n");	memset(buff, 0, sizeof(buff));	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];	if (param == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");		return 1;	}	param_data = &(param->data[0]);	capacity = (param_data[3] << 24) | (param_data[2] << 16) | 		   (param_data[1] << 8) | param_data[0];	/* Subtract one sector to fix get last sector ioctl */	capacity -= 1;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete(): Capacity = 0x%x.\n", capacity);	/* Number of LBA's */	buff[0] = (capacity >> 24);	buff[1] = (capacity >> 16) & 0xff;	buff[2] = (capacity >> 8) & 0xff;	buff[3] = capacity & 0xff;	/* Block size in bytes (512) */	buff[4] = (TW_BLOCK_SIZE >> 24);	buff[5] = (TW_BLOCK_SIZE >> 16) & 0xff;	buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff;	buff[7] = TW_BLOCK_SIZE & 0xff;	tw_transfer_internal(tw_dev, request_id, buff, sizeof(buff));	return 0;} /* End tw_scsiop_read_capacity_complete() *//* This function handles scsi read or write commands */static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) {	TW_Command *command_packet;	unsigned long command_que_value;	u32 lba = 0x0, num_sectors = 0x0;	int i, use_sg;	struct scsi_cmnd *srb;	struct scatterlist *sglist, *sg;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n");	srb = tw_dev->srb[request_id];	sglist = scsi_sglist(srb);	if (!sglist) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");		return 1;	}	/* Initialize command packet */	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];	if (command_packet == NULL) {		dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): Bad command packet virtual address.\n");		return 1;	}	if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == READ_10) {		command_packet->opcode__sgloffset = TW_OPSGL_IN(3, TW_OP_READ);	} else {		command_packet->opcode__sgloffset = TW_OPSGL_IN(3, TW_OP_WRITE);	}	command_packet->size = 3;	command_packet->request_id = request_id;	command_packet->unit__hostid = TW_UNITHOST_IN(0, srb->device->id);	command_packet->status = 0;	command_packet->flags = 0;	if (srb->cmnd[0] == WRITE_10) {		if ((srb->cmnd[1] & 0x8) || (srb->cmnd[1] & 0x10))			command_packet->flags = 1;	}	if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == WRITE_6) {		lba = ((u32)srb->cmnd[1] << 16) | ((u32)srb->cmnd[2] << 8) | (u32)srb->cmnd[3];		num_sectors = (u32)srb->cmnd[4];	} else {		lba = ((u32)srb->cmnd[2] << 24) | ((u32)srb->cmnd[3] << 16) | ((u32)srb->cmnd[4] << 8) | (u32)srb->cmnd[5];		num_sectors = (u32)srb->cmnd[8] | ((u32)srb->cmnd[7] << 8);	}  	/* Update sector statistic */	tw_dev->sector_count = num_sectors;	if (tw_dev->sector_count > tw_dev->max_sector_count)		tw_dev->max_sector_count = tw_dev->sector_count;  	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): lba = 0x%x num_sectors = 0x%x\n", lba, num_sectors);	command_packet->byte8.io.lba = lba;	command_packet->byte6.block_count = num_sectors;	use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);	if (!use_sg)		return 1;	scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {		command_packet->byte8.io.sgl[i].address = sg_dma_address(sg);		command_packet->byte8.io.sgl[i].length = sg_dma_len(sg);		command_packet->size+=2;	}	/* Update SG statistics */	tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);	if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)		tw_dev->max_sgl_entries = tw_dev->sgl_entries;	command_que_value = tw_dev->command_packet_physical_address[request_id];	if (command_que_value == 0) {		dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Bad command packet physical address.\n");		return 1;	}      	/* Now try to post the command to the board */	tw_post_command_packet(tw_dev, request_id);	return 0;} /* End tw_scsiop_read_write() *//* This function will handle the request sense scsi command */static int tw_scsiop_request_sense(TW_Device_Extension *tw_dev, int request_id){	char request_buffer[18];	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_request_sense()\n");	memset(request_buffer, 0, sizeof(request_buffer));	request_buffer[0] = 0x70; /* Immediate fixed format */	request_buffer[7] = 10;	/* minimum size per SPC: 18 bytes */	/* leave all other fields zero, giving effectively NO_SENSE return */	tw_transfer_internal(tw_dev, request_id, request_buffer,			     sizeof(request_buffer));	tw_dev->state[request_id] = TW_S_COMPLETED;	tw_state_request_finish(tw_dev, request_id);	/* If we got a request_sense, we probably want a reset, return error */	tw_dev->srb[request_id]->result = (DID_ERROR << 16);	tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);	return 0

⌨️ 快捷键说明

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