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

📄 3w-xxxx.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	return numcards;} /* End tw_findcards() *//* This function will free up device extension resources */void tw_free_device_extension(TW_Device_Extension *tw_dev){	int i, imax;	imax = TW_Q_LENGTH;	dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n");	/* Free command packet and generic buffer memory */	for (i=0;i<imax;i++) {		if (tw_dev->command_packet_virtual_address[i]) 			kfree(tw_dev->command_packet_virtual_address[i]);		if (tw_dev->alignment_virtual_address[i])			kfree(tw_dev->alignment_virtual_address[i]);	}} /* End tw_free_device_extension() *//* Clean shutdown routine */static int tw_halt(struct notifier_block *nb, ulong event, void *buf){	int i;	for (i=0;i<tw_device_extension_count;i++) {		printk(KERN_NOTICE "3w-xxxx: Notifying card #%d\n", i);		tw_shutdown_device(tw_device_extension_list[i]);	}	unregister_reboot_notifier(&tw_notifier);	return NOTIFY_OK;} /* End tw_halt() *//* This function will send an initconnection command to controller */int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits) {	u32 command_que_addr, command_que_value;	u32 status_reg_addr, status_reg_value;	u32 response_que_addr;	TW_Command  *command_packet;	TW_Response_Queue response_queue;	int request_id = 0;	int i = 0;	int imax = 0;	dprintk(KERN_NOTICE "3w-xxxx: tw_initconnection()\n");	command_que_addr = tw_dev->registers.command_que_addr;	status_reg_addr = tw_dev->registers.status_reg_addr;	response_que_addr = tw_dev->registers.response_que_addr;	/* Initialize InitConnection command packet */	if (tw_dev->command_packet_virtual_address[request_id] == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet virtual address.\n");		return 1;	}	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];	memset(command_packet, 0, sizeof(TW_Sector));	command_packet->byte0.opcode = TW_OP_INIT_CONNECTION;	command_packet->byte0.sgl_offset = 0x0;	command_packet->size = TW_INIT_COMMAND_PACKET_SIZE;	command_packet->request_id = request_id;	command_packet->byte3.unit = 0x0;	command_packet->byte3.host_id = 0x0;	command_packet->status = 0x0;	command_packet->flags = 0x0;	command_packet->byte6.message_credits = message_credits; 	command_packet->byte8.init_connection.response_queue_pointer = 0x0;	command_que_value = tw_dev->command_packet_physical_address[request_id];	if (command_que_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet physical address.\n");		return 1;	}  	/* Send command packet to the board */	outl(command_que_value, command_que_addr);    	/* Poll for completion */	imax = TW_POLL_MAX_RETRIES;	for (i=0;i<imax;i++) {		mdelay(10);		status_reg_value = inl(status_reg_addr);		if (tw_check_bits(status_reg_value)) {			printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");			return 1;		}		if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {			response_queue.value = inl(response_que_addr);			request_id = (unsigned char)response_queue.u.response_id;			if (request_id != 0) {				/* unexpected request id */				printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected request id.\n");				return 1;			}			if (command_packet->status != 0) {				/* bad response */				printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);				return 1;			}			break;	/* Response was okay, so we exit */		}	}	return 0;} /* End tw_initconnection() *//* This function will initialize the fields of a device extension */int tw_initialize_device_extension(TW_Device_Extension *tw_dev){	int i, imax;	dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_device_extension()\n");	imax = TW_Q_LENGTH;	for (i=0; i<imax; i++) {		/* Initialize command packet buffers */		tw_allocate_memory(tw_dev, i, sizeof(TW_Sector), 0);		if (tw_dev->command_packet_virtual_address[i] == NULL) {			printk(KERN_WARNING "3w-xxxx: tw_initialize_device_extension(): Bad command packet virtual address.\n");			return 1;		}		memset(tw_dev->command_packet_virtual_address[i], 0, sizeof(TW_Sector));    		/* Initialize generic buffer */		tw_allocate_memory(tw_dev, i, sizeof(TW_Sector), 1);		if (tw_dev->alignment_virtual_address[i] == NULL) {			printk(KERN_WARNING "3w-xxxx: tw_initialize_device_extension(): Bad alignment virtual address.\n");			return 1;		}		memset(tw_dev->alignment_virtual_address[i], 0, sizeof(TW_Sector));		tw_dev->free_queue[i] = i;		tw_dev->state[i] = TW_S_INITIAL;		tw_dev->ioctl_size[i] = 0;		tw_dev->aen_queue[i] = 0;	}	for (i=0;i<TW_MAX_UNITS;i++)		tw_dev->is_unit_present[i] = 0;	tw_dev->num_units = 0;	tw_dev->num_aborts = 0;	tw_dev->num_resets = 0;	tw_dev->free_head = TW_Q_START;	tw_dev->free_tail = TW_Q_LENGTH - 1;	tw_dev->posted_request_count = 0;	tw_dev->max_posted_request_count = 0;	tw_dev->max_sgl_entries = 0;	tw_dev->sgl_entries = 0;	tw_dev->host = NULL;	tw_dev->pending_head = TW_Q_START;	tw_dev->pending_tail = TW_Q_START;	tw_dev->aen_head = 0;	tw_dev->aen_tail = 0;	tw_dev->sector_count = 0;	tw_dev->max_sector_count = 0;	spin_lock_init(&tw_dev->tw_lock);	tw_dev->flags = 0;	return 0;} /* End tw_initialize_device_extension() *//* This function will get unit info from the controller */int tw_initialize_units(TW_Device_Extension *tw_dev) {	int found = 0;	unsigned char request_id = 0;	TW_Command *command_packet;	TW_Param *param;	int i, imax, num_units = 0;	u32 status_reg_addr, status_reg_value;	u32 command_que_addr, command_que_value;	u32 response_que_addr;	TW_Response_Queue response_queue;	u32 param_value;	unsigned char *is_unit_present;	dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units()\n");	status_reg_addr = tw_dev->registers.status_reg_addr;	command_que_addr = tw_dev->registers.command_que_addr;	response_que_addr = tw_dev->registers.response_que_addr;  	/* Setup the command packet */	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];	if (command_packet == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): 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.block_count = 1;	/* Now setup the param */	if (tw_dev->alignment_virtual_address[request_id] == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): 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 = 3;       /* unit summary table */	param->parameter_id = 3;   /* unitstatus parameter */	param->parameter_size_bytes = TW_MAX_UNITS;	param_value = tw_dev->alignment_physical_address[request_id];	if (param_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): 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);	/* Post the command packet to the board */	command_que_value = tw_dev->command_packet_physical_address[request_id];	if (command_que_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet physical address.\n");		return 1;	}	outl(command_que_value, command_que_addr);	/* Poll for completion */	imax = TW_POLL_MAX_RETRIES;	for(i=0; i<imax; i++) {		mdelay(10);		status_reg_value = inl(status_reg_addr);		if (tw_check_bits(status_reg_value)) {			printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");			return 1;		}		if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {			response_queue.value = inl(response_que_addr);			request_id = (unsigned char)response_queue.u.response_id;			if (request_id != 0) {				/* unexpected request id */				printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected request id.\n");				return 1;			}			if (command_packet->status != 0) {				/* bad response */				printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);				return 1;			}			found = 1;			break;		}	}	if (found == 0) {		/* response never received */		printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): No response.\n");		return 1;	}	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];	is_unit_present = (unsigned char *)&(param->data[0]);  	/* Show all units present */	imax = TW_MAX_UNITS;	for(i=0; i<imax; i++) {		if (is_unit_present[i] == 0) {			tw_dev->is_unit_present[i] = FALSE;		} else {		  if (is_unit_present[i] & TW_UNIT_ONLINE) {			dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): Unit %d found.\n", i);			tw_dev->is_unit_present[i] = TRUE;			num_units++;		  }		}	}	tw_dev->num_units = num_units;	if (num_units == 0) {		printk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): No units found.\n");		return 1;	}  	return 0;} /* End tw_initialize_units() *//* This function is the interrupt service routine */static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs) {	int request_id;	u32 status_reg_addr, status_reg_value;	u32 response_que_addr;	TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;	TW_Response_Queue response_que;	int error = 0;	int do_response_interrupt=0;	int do_attention_interrupt=0;	int do_host_interrupt=0;	int do_command_interrupt=0;	int flags = 0;	int flags2 = 0;	TW_Command *command_packet;	if (test_and_set_bit(TW_IN_INTR, &tw_dev->flags))		return;	spin_lock_irqsave(&io_request_lock, flags);	if (tw_dev->tw_pci_dev->irq == irq) {		spin_lock_irqsave(&tw_dev->tw_lock, flags2);		dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt()\n");		/* Read the registers */		status_reg_addr = tw_dev->registers.status_reg_addr;		response_que_addr = tw_dev->registers.response_que_addr;		status_reg_value = inl(status_reg_addr);		/* Check which interrupt */		if (status_reg_value & TW_STATUS_HOST_INTERRUPT)			do_host_interrupt=1;		if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT)			do_attention_interrupt=1;		if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT)			do_command_interrupt=1;		if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT)			do_response_interrupt=1;		/* Handle host interrupt */		if (do_host_interrupt) {			dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");			tw_clear_host_interrupt(tw_dev);		}		/* Handle attention interrupt */		if (do_attention_interrupt) {			dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");			tw_state_request_start(tw_dev, &request_id);			error = tw_aen_read_queue(tw_dev, request_id);			if (error) {				printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error reading aen queue.\n");				tw_dev->state[request_id] = TW_S_COMPLETED;				tw_state_request_finish(tw_dev, request_id);			} else {				dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Clearing attention interrupt.\n");				tw_clear_attention_interrupt(tw_dev);			}		}		/* Handle command interrupt */		if (do_command_interrupt) {			/* Drain as many pending commands as we can */			while (tw_dev->pending_request_count > 0) {				request_id = tw_dev->pending_queue[tw_dev->pending_head];				if (tw_dev->state[request_id] != TW_S_PENDING) {					printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found request id that wasn't pending.\n");					break;				}				if (tw_post_command_packet(tw_dev, request_id)==0) {					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--;				} else {					break;				}			}			/* If there are no more pending requests, we mask command interrupt */			if (tw_dev->pending_request_count == 0) 				tw_mask_command_interrupt(tw_dev);		}		/* Handle response interrupt */		if (do_response_interrupt) {			/* Drain the response queue from the board */			while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {				response_que.value = inl(response_que_addr);				request_id = response_que.u.response_id;				command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];				if (command_packet->status != 0) {					printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);

⌨️ 快捷键说明

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