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

📄 3w-xxxx.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* Empty the response queue again */		error = tw_empty_response_que(tw_dev);		if (error) {			printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't empty response queue for card %d.\n", tw_dev->host->host_no);			tries++;			continue;		}		/* Now the controller is in a good state */		break;	}	if (tries >= TW_MAX_RESET_TRIES) {		printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller error or no attention interrupt: giving up for card %d.\n", tw_dev->host->host_no);		return 1;	}	error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);	if (error) {		printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no);		return 1;	}	/* Re-enable interrupts */	tw_enable_interrupts(tw_dev);	return 0;} /* End tw_reset_sequence() *//* This funciton returns unit geometry in cylinders/heads/sectors */int tw_scsi_biosparam(Disk *disk, kdev_t dev, int geom[]) {	int heads, sectors, cylinders;	TW_Device_Extension *tw_dev;		dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam()\n");	tw_dev = (TW_Device_Extension *)disk->device->host->hostdata;	heads = 64;	sectors = 32;	cylinders = disk->capacity / (heads * sectors);	if (disk->capacity >= 0x200000) {		heads = 255;		sectors = 63;		cylinders = disk->capacity / (heads * sectors);	}	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam(): heads = %d, sectors = %d, cylinders = %d\n", heads, sectors, cylinders);	geom[0] = heads;			 	geom[1] = sectors;	geom[2] = cylinders;	return 0;} /* End tw_scsi_biosparam() *//* This function will find and initialize any cards */int tw_scsi_detect(Scsi_Host_Template *tw_host){	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_detect()\n");	/* Check if the kernel has PCI interface compiled in */	if (!pci_present()) {		printk(KERN_WARNING "3w-xxxx: tw_scsi_detect(): No pci interface present.\n");		return 0;	}	return(tw_findcards(tw_host));} /* End tw_scsi_detect() *//* This is the new scsi eh abort function */int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt) {	TW_Device_Extension *tw_dev=NULL;	int i = 0;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_abort()\n");	if (!SCpnt) {		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Invalid Scsi_Cmnd.\n");		return (FAILED);	}	tw_dev = (TW_Device_Extension *)SCpnt->host->hostdata;	if (tw_dev == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Invalid device extension.\n");		return (FAILED);	}	spin_lock(&tw_dev->tw_lock);	tw_dev->num_aborts++;	/* If the command hasn't been posted yet, we can do the abort */	for (i=0;i<TW_Q_LENGTH;i++) {		if (tw_dev->srb[i] == SCpnt) {			if (tw_dev->state[i] == TW_S_STARTED) {				printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for started Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]);				tw_dev->state[i] = TW_S_COMPLETED;				tw_state_request_finish(tw_dev, i);				spin_unlock(&tw_dev->tw_lock);				return (SUCCESS);			}			if (tw_dev->state[i] == TW_S_PENDING) {				printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for pending Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]);				if (tw_dev->pending_head == TW_Q_LENGTH-1) {					tw_dev->pending_head = TW_Q_START;				} else {					tw_dev->pending_head = tw_dev->pending_head + 1;				}				tw_dev->pending_request_count--;				tw_dev->state[i] = TW_S_COMPLETED;				tw_state_request_finish(tw_dev, i);				spin_unlock(&tw_dev->tw_lock);				return (SUCCESS);			}		}	}	/* If the command has already been posted, we have to reset the card */	printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort failed for unknown Scsi_Cmnd 0x%x, resetting card %d.\n", (u32)SCpnt, tw_dev->host->host_no);	if (tw_reset_device_extension(tw_dev)) {		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);		spin_unlock(&tw_dev->tw_lock);		return (FAILED);	}	spin_unlock(&tw_dev->tw_lock);	return (SUCCESS);} /* End tw_scsi_eh_abort() *//* This is the new scsi eh reset function */int tw_scsi_eh_reset(Scsi_Cmnd *SCpnt) {	TW_Device_Extension *tw_dev=NULL;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_reset()\n");	if (!SCpnt) {		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Invalid Scsi_Cmnd.\n");		return (FAILED);	}	tw_dev = (TW_Device_Extension *)SCpnt->host->hostdata;	if (tw_dev == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Invalid device extension.\n");		return (FAILED);	}	spin_lock(&tw_dev->tw_lock);	tw_dev->num_resets++;	/* Now reset the card and some of the device extension data */	if (tw_reset_device_extension(tw_dev)) {		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset failed for card %d.\n", tw_dev->host->host_no);		spin_unlock(&tw_dev->tw_lock);		return (FAILED);	}	printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset succeeded for card %d.\n", tw_dev->host->host_no);	spin_unlock(&tw_dev->tw_lock);	return (SUCCESS);} /* End tw_scsi_eh_reset() *//* This function handles input and output from /proc/scsi/3w-xxxx/x */int tw_scsi_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout) {	TW_Device_Extension *tw_dev = NULL;	TW_Info info;	int i;	int j;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_proc_info()\n");	/* Find the correct device extension */	for (i=0;i<tw_device_extension_count;i++) 		if (tw_device_extension_list[i]->host->host_no == hostno) 			tw_dev = tw_device_extension_list[i];	if (tw_dev == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsi_proc_info(): Couldn't locate device extension.\n");		return (-EINVAL);	}	info.buffer = buffer;	info.length = length;	info.offset = offset;	info.position = 0;		if (inout) {		/* Write */		if (strncmp(buffer, "debug", 5) == 0) {			printk(KERN_INFO "3w-xxxx: Posted commands:\n");			for (j=0;j<TW_Q_LENGTH;j++) {				if (tw_dev->state[j] == TW_S_POSTED) {					TW_Command *command = (TW_Command *)tw_dev->command_packet_virtual_address[j];					printk(KERN_INFO "3w-xxxx: Request_id: %d\n", j);					printk(KERN_INFO "Opcode: 0x%x\n", command->byte0.opcode);					printk(KERN_INFO "Block_count: 0x%x\n", command->byte6.block_count);					printk(KERN_INFO "LBA: 0x%x\n", (u32)command->byte8.io.lba);					printk(KERN_INFO "Physical command packet addr: 0x%x\n", tw_dev->command_packet_physical_address[j]);					printk(KERN_INFO "Scsi_Cmnd: 0x%x\n", (u32)tw_dev->srb[j]);				}			}			printk(KERN_INFO "3w-xxxx: Free_head: %3d\n", tw_dev->free_head);			printk(KERN_INFO "3w-xxxx: Free_tail: %3d\n", tw_dev->free_tail);		} 		return length;	} else {		/* Read */		if (start) {			*start = buffer;		}		tw_copy_info(&info, "scsi%d: 3ware Storage Controller\n", hostno);		tw_copy_info(&info, "Driver version: %s\n", tw_driver_version);		tw_copy_info(&info, "Current commands posted:       %3d\n", tw_dev->posted_request_count);		tw_copy_info(&info, "Max commands posted:           %3d\n", tw_dev->max_posted_request_count);		tw_copy_info(&info, "Current pending commands:      %3d\n", tw_dev->pending_request_count);		tw_copy_info(&info, "Max pending commands:          %3d\n", tw_dev->max_pending_request_count);		tw_copy_info(&info, "Last sgl length:               %3d\n", tw_dev->sgl_entries);		tw_copy_info(&info, "Max sgl length:                %3d\n", tw_dev->max_sgl_entries);		tw_copy_info(&info, "Last sector count:             %3d\n", tw_dev->sector_count);		tw_copy_info(&info, "Max sector count:              %3d\n", tw_dev->max_sector_count);		tw_copy_info(&info, "Resets:                        %3d\n", tw_dev->num_resets);		tw_copy_info(&info, "Aborts:                        %3d\n", tw_dev->num_aborts);	}	if (info.position > info.offset) {		return (info.position - info.offset);	} else { 		return 0;	}} /* End tw_scsi_proc_info() *//* This is the main scsi queue function to handle scsi opcodes */int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {	unsigned char *command = SCpnt->cmnd;	int request_id = 0;	int error = 0;	int flags = 0;	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->host->hostdata;	spin_lock_irqsave(&tw_dev->tw_lock, flags);	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue()\n");	/* Skip scsi command if it isn't for us */	if ((tw_dev->is_unit_present[SCpnt->target] == FALSE) || (SCpnt->lun != 0)) {		SCpnt->result = (DID_BAD_TARGET << 16);		done(SCpnt);		spin_unlock_irqrestore(&tw_dev->tw_lock, flags);		return 0;	}	if (done == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid done function.\n");		SCpnt->result = (DID_ERROR << 16);		done(SCpnt);		spin_unlock_irqrestore(&tw_dev->tw_lock, flags);		return 0;	}	if (tw_dev == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid device extension.\n");		SCpnt->result = (DID_ERROR << 16);		done(SCpnt);		spin_unlock_irqrestore(&tw_dev->tw_lock, flags);		return 0;	}		/* Save done function into Scsi_Cmnd struct */	SCpnt->scsi_done = done;		 	/* Queue the command and get a request id */	tw_state_request_start(tw_dev, &request_id);	/* Save the scsi command for use by the ISR */	tw_dev->srb[request_id] = SCpnt;	switch (*command) {		case READ_10:			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_10.\n");		case READ_6:			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_6.\n");		case WRITE_10:			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_10.\n");		case WRITE_6:			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_6.\n");			error = tw_scsiop_read_write(tw_dev, request_id);			break;		case TEST_UNIT_READY:			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TEST_UNIT_READY.\n");			error = tw_scsiop_test_unit_ready(tw_dev, request_id);			break;		case INQUIRY:			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught INQUIRY.\n");			error = tw_scsiop_inquiry(tw_dev, request_id);			break;		case READ_CAPACITY:			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_CAPACITY.\n");			error = tw_scsiop_read_capacity(tw_dev, request_id);			break;		case TW_IOCTL:			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TW_SCSI_IOCTL.\n");			error = tw_ioctl(tw_dev, request_id);			break;		default:			printk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): Unknown scsi opcode: 0x%x\n", *command);			tw_dev->state[request_id] = TW_S_COMPLETED;			tw_state_request_finish(tw_dev, request_id);			SCpnt->result = (DID_BAD_TARGET << 16);			done(SCpnt);	}	if (error) {		tw_dev->state[request_id] = TW_S_COMPLETED;		tw_state_request_finish(tw_dev, request_id);		SCpnt->result = (DID_ERROR << 16);		done(SCpnt);	}	spin_unlock_irqrestore(&tw_dev->tw_lock, flags);	return 0;} /* End tw_scsi_queue() *//* This function will release the resources on an rmmod call */int tw_scsi_release(struct Scsi_Host *tw_host) {	TW_Device_Extension *tw_dev;	tw_dev = (TW_Device_Extension *)tw_host->hostdata;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_release()\n");	/* Free up the IO region */	release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);	/* Free up the IRQ */	free_irq(tw_dev->tw_pci_dev->irq, tw_dev);	/* Free up device extension resources */	tw_free_device_extension(tw_dev);	/* Tell kernel scsi-layer we are gone */	scsi_unregister(tw_host);		/* Fake like we just shut down, so notify the card that	 * we "shut down cleanly".	 */	tw_halt(0, 0, 0);  // parameters aren't actually used	return 0;} /* End tw_scsi_release() *//* This function handles scsi inquiry commands */int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id){	TW_Param *param;	TW_Command *command_packet;	u32 command_que_value, command_que_addr;	u32 param_value;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry()\n");	/* Initialize command packet */	command_que_addr = tw_dev->registers.command_que_addr;	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];	if (command_packet == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet virtual address.\n");		return 1;	}	memset(command_packet, 0, sizeof(TW_Sector));	command_packet->byte0.opcode = TW_OP_GET_PARAM;	command_packet->byte0.sgl_offset = 2;	command_packet->size = 4;	command_packet->request_id = request_id;	command_packet->byte3.unit = 0;	command_packet->byte3.host_id = 0;	command_packet->status = 0;	command_packet->flags = 0;	command_packet->byte6.parameter_count = 1;	/* Now setup the param */	if (tw_dev->alignment_virtual_address[request_id] == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_in

⌨️ 快捷键说明

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