drivers/scsi/3w-xxxx.c

Source file repositories/reference/linux-study-clean/drivers/scsi/3w-xxxx.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/3w-xxxx.c
Extension
.c
Size
83867 bytes
Lines
2431
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations tw_fops = {
	.owner		= THIS_MODULE,
	.unlocked_ioctl	= tw_chrdev_ioctl,
	.compat_ioctl   = compat_ptr_ioctl,
	.open		= tw_chrdev_open,
	.release	= NULL,
	.llseek		= noop_llseek,
};

/* This function will free up device extension resources */
static void tw_free_device_extension(TW_Device_Extension *tw_dev)
{
	dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n");

	/* Free command packet and generic buffer memory */
	if (tw_dev->command_packet_virtual_address[0])
		dma_free_coherent(&tw_dev->tw_pci_dev->dev,
				sizeof(TW_Command) * TW_Q_LENGTH,
				tw_dev->command_packet_virtual_address[0],
				tw_dev->command_packet_physical_address[0]);

	if (tw_dev->alignment_virtual_address[0])
		dma_free_coherent(&tw_dev->tw_pci_dev->dev,
				sizeof(TW_Sector) * TW_Q_LENGTH,
				tw_dev->alignment_virtual_address[0],
				tw_dev->alignment_physical_address[0]);
} /* End tw_free_device_extension() */

/* This function will send an initconnection command to controller */
static int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits)
{
	unsigned long command_que_value;
	TW_Command  *command_packet;
	TW_Response_Queue response_queue;
	int request_id = 0;

	dprintk(KERN_NOTICE "3w-xxxx: tw_initconnection()\n");

	/* 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->opcode__sgloffset = TW_OPSGL_IN(0, TW_OP_INIT_CONNECTION);
	command_packet->size = TW_INIT_COMMAND_PACKET_SIZE;
	command_packet->request_id = request_id;
	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, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));

	/* Poll for completion */
	if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
		response_queue.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
		request_id = TW_RESID_OUT(response_queue.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 */
			tw_decode_sense(tw_dev, request_id, 0);
			return 1;
		}
	}
	return 0;
} /* End tw_initconnection() */

/* Set a value in the features table */
static int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size,
			 unsigned char *val)
{
	TW_Param *param;
	TW_Command  *command_packet;
	TW_Response_Queue response_queue;
	int request_id = 0;

Annotation

Implementation Notes