-#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-#define __3W_C /* let 3w-xxxx.h know it is use */
-
-#include "scsi.h"
-#include "hosts.h"
-
-#include "3w-xxxx.h"
-
-static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-static int tw_chrdev_open(struct inode *inode, struct file *file);
-static int tw_chrdev_release(struct inode *inode, struct file *file);
-static int tw_copy_info(TW_Info *info, char *fmt, ...);
-static void tw_copy_mem_info(TW_Info *info, char *data, int len);
-static int tw_halt(struct notifier_block *nb, ulong event, void *buf);
-static int tw_map_scsi_sg_data(struct pci_dev *pdev, Scsi_Cmnd *cmd);
-static u32 tw_map_scsi_single_data(struct pci_dev *pdev, Scsi_Cmnd *cmd);
-static void tw_unmap_scsi_data(struct pci_dev *pdev, Scsi_Cmnd *cmd);
-
-/* Notifier block to get a notify on system shutdown/halt/reboot */
-static struct notifier_block tw_notifier = {
- tw_halt, NULL, 0
-};
-
-/* File operations struct for character device */
-static struct file_operations tw_fops = {
- .owner = THIS_MODULE,
- .ioctl = tw_chrdev_ioctl,
- .open = tw_chrdev_open,
- .release = tw_chrdev_release
-};
-
-/* Globals */
-char *tw_driver_version="1.02.00.037";
-TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
-int tw_device_extension_count = 0;
-static int twe_major = -1;
-
-/* Functions */
-
-/* This function will complete an aen request from the isr */
-int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id)
-{
- TW_Param *param;
- unsigned short aen;
- int error = 0, table_max = 0;
-
- dprintk(KERN_WARNING "3w-xxxx: tw_aen_complete()\n");
- if (tw_dev->alignment_virtual_address[request_id] == NULL) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n");
- return 1;
- }
- param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
- aen = *(unsigned short *)(param->data);
- dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen);
-
- /* Print some useful info when certain aen codes come out */
- if (aen == 0x0ff) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no);
- } else {
- table_max = sizeof(tw_aen_string)/sizeof(char *);
- if ((aen & 0x0ff) < table_max) {
- if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
- printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8);
- } else {
- if (aen != 0x0)
- printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff]);
- }
- } else {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen);
- }
- }
- if (aen != TW_AEN_QUEUE_EMPTY) {
- tw_dev->aen_count++;
-
- /* Now queue the code */
- tw_dev->aen_queue[tw_dev->aen_tail] = aen;
- if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
- tw_dev->aen_tail = TW_Q_START;
- } else {
- tw_dev->aen_tail = tw_dev->aen_tail + 1;
- }
- if (tw_dev->aen_head == tw_dev->aen_tail) {
- if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
- tw_dev->aen_head = TW_Q_START;
- } else {
- tw_dev->aen_head = tw_dev->aen_head + 1;
- }
- }
-
- error = tw_aen_read_queue(tw_dev, request_id);
- if (error) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing AEN.\n", tw_dev->host->host_no);
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- }
- } else {
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- }
-
- return 0;
-} /* End tw_aen_complete() */
-
-/* This function will drain the aen queue after a soft reset */
-int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
-{
- TW_Command *command_packet;
- TW_Param *param;
- int request_id = 0;
- u32 command_que_addr;
- unsigned long command_que_value;
- unsigned long param_value;
- TW_Response_Queue response_queue;
- u32 response_que_addr;
- unsigned short aen;
- unsigned short aen_code;
- int finished = 0;
- int first_reset = 0;
- int queue = 0;
- int found = 0, table_max = 0;
-
- dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue()\n");
-
- command_que_addr = tw_dev->registers.command_que_addr;
- response_que_addr = tw_dev->registers.response_que_addr;
-
- if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT | TW_STATUS_MICROCONTROLLER_READY, 30)) {
- dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count);
- return 1;
- }
- tw_clear_attention_interrupt(tw_dev);
-
- /* Empty response queue */
- tw_empty_response_que(tw_dev);
-
- /* Initialize command packet */
- if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): 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_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;
- command_que_value = tw_dev->command_packet_physical_address[request_id];
- if (command_que_value == 0) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet physical address.\n");
- return 1;
- }
-
- /* Now setup the param */
- if (tw_dev->alignment_virtual_address[request_id] == NULL) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): 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 = 0x401; /* AEN table */
- param->parameter_id = 2; /* Unit code */
- param->parameter_size_bytes = 2;
- param_value = tw_dev->alignment_physical_address[request_id];
- if (param_value == 0) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): 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);
-
- /* Now drain the controller's aen queue */
- do {
- /* Post command packet */
- outl(command_que_value, command_que_addr);
-
- /* Now poll for completion */
- if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 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_aen_drain_queue(): Unexpected request id.\n");
- return 1;
- }
-
- if (command_packet->status != 0) {
- if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) {
- /* Bad response */
- tw_decode_sense(tw_dev, request_id, 0);
- return 1;
- } else {
- /* We know this is a 3w-1x00, and doesn't support aen's */
- return 0;
- }
- }
-
- /* Now check the aen */
- aen = *(unsigned short *)(param->data);
- aen_code = (aen & 0x0ff);
- queue = 0;
- switch (aen_code) {
- case TW_AEN_QUEUE_EMPTY:
- dprintk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
- if (first_reset != 1) {
- return 1;
- } else {
- finished = 1;
- }
- break;
- case TW_AEN_SOFT_RESET:
- if (first_reset == 0) {
- first_reset = 1;
- } else {
- printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
- tw_dev->aen_count++;
- queue = 1;
- }
- break;
- default:
- if (aen == 0x0ff) {
- printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n");
- } else {
- table_max = sizeof(tw_aen_string)/sizeof(char *);
- if ((aen & 0x0ff) < table_max) {
- if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
- printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8);
- } else {
- printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
- }
- } else
- printk(KERN_WARNING "3w-xxxx: Received AEN %d.\n", aen);
- }
- tw_dev->aen_count++;
- queue = 1;
- }
-
- /* Now put the aen on the aen_queue */
- if (queue == 1) {
- tw_dev->aen_queue[tw_dev->aen_tail] = aen;
- if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
- tw_dev->aen_tail = TW_Q_START;
- } else {
- tw_dev->aen_tail = tw_dev->aen_tail + 1;
- }
- if (tw_dev->aen_head == tw_dev->aen_tail) {
- if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
- tw_dev->aen_head = TW_Q_START;
- } else {
- tw_dev->aen_head = tw_dev->aen_head + 1;
- }
- }
- }
- found = 1;
- }
- if (found == 0) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Response never received.\n");
- return 1;
- }
- } while (finished == 0);
-
- return 0;
-} /* End tw_aen_drain_queue() */
-
-/* This function will read the aen queue from the isr */
-int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
-{
- TW_Command *command_packet;
- TW_Param *param;
- u32 command_que_addr;
- unsigned long command_que_value;
- u32 status_reg_value = 0, status_reg_addr;
- unsigned long param_value = 0;
-
- dprintk(KERN_NOTICE "3w-xxxx: tw_aen_read_queue()\n");
- command_que_addr = tw_dev->registers.command_que_addr;
- status_reg_addr = tw_dev->registers.status_reg_addr;
-
- status_reg_value = inl(status_reg_addr);
- if (tw_check_bits(status_reg_value)) {
- dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
- tw_decode_bits(tw_dev, status_reg_value, 1);
- return 1;
- }
- if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): 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_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;
- command_que_value = tw_dev->command_packet_physical_address[request_id];
- if (command_que_value == 0) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet physical address.\n");
- return 1;
- }
- /* Now setup the param */
- if (tw_dev->alignment_virtual_address[request_id] == NULL) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): 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 = 0x401; /* AEN table */
- param->parameter_id = 2; /* Unit code */
- param->parameter_size_bytes = 2;
- param_value = tw_dev->alignment_physical_address[request_id];
- if (param_value == 0) {
- printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): 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);
-
- /* Now post the command packet */
- if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
- dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post succeeded.\n");
- tw_dev->srb[request_id] = 0; /* Flag internal command */
- tw_dev->state[request_id] = TW_S_POSTED;
- outl(command_que_value, command_que_addr);
- } else {
- printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post failed, will retry.\n");
- return 1;
- }
-
- return 0;
-} /* End tw_aen_read_queue() */
-
-/* This function will allocate memory */
-int tw_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
-{
- int i;
- dma_addr_t dma_handle;
- unsigned long *cpu_addr = NULL;
-
- dprintk(KERN_NOTICE "3w-xxxx: tw_allocate_memory()\n");
-
- cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle);
- if (cpu_addr == NULL) {
- printk(KERN_WARNING "3w-xxxx: pci_alloc_consistent() failed.\n");
- return 1;
- }
-
- if ((unsigned long)cpu_addr % (tw_dev->tw_pci_dev->device == TW_DEVICE_ID ? TW_ALIGNMENT_6000 : TW_ALIGNMENT_7000)) {
- printk(KERN_WARNING "3w-xxxx: Couldn't allocate correctly aligned memory.\n");
- pci_free_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, cpu_addr, dma_handle);
- return 1;
- }
-
- memset(cpu_addr, 0, size*TW_Q_LENGTH);
-
- for (i=0;i<TW_Q_LENGTH;i++) {
- switch(which) {
- case 0:
- tw_dev->command_packet_physical_address[i] = dma_handle+(i*size);
- tw_dev->command_packet_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
- break;
- case 1:
- tw_dev->alignment_physical_address[i] = dma_handle+(i*size);
- tw_dev->alignment_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
- break;
- default:
- printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n");
- return 1;
- }
- }
-
- return 0;
-} /* End tw_allocate_memory() */
-
-/* This function will check the status register for unexpected bits */
-int tw_check_bits(u32 status_reg_value)
-{
- if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) {
- dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
- return 1;
- }
- if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {
- dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);
- return 1;
- }
-
- return 0;
-} /* End tw_check_bits() */
-
-/* This function will report controller error status */
-int tw_check_errors(TW_Device_Extension *tw_dev)
-{
- u32 status_reg_addr, status_reg_value;
-
- status_reg_addr = tw_dev->registers.status_reg_addr;
- status_reg_value = inl(status_reg_addr);
-
- if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value)) {
- tw_decode_bits(tw_dev, status_reg_value, 0);
- return 1;
- }
-
- return 0;
-} /* End tw_check_errors() */
-
-/* This function handles ioctl for the character device */
-static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- int error, request_id;
- dma_addr_t dma_handle;
- unsigned short tw_aen_code;
- unsigned long flags;
- unsigned int data_buffer_length = 0;
- unsigned long data_buffer_length_adjusted = 0;
- unsigned long *cpu_addr;
- long timeout;
- TW_New_Ioctl *tw_ioctl;
- TW_Passthru *passthru;
- TW_Device_Extension *tw_dev = tw_device_extension_list[iminor(inode)];
- int retval = -EFAULT;
-
- dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
-
- /* Only let one of these through at a time */
- if (down_interruptible(&tw_dev->ioctl_sem))
- return -EINTR;
-
- /* First copy down the buffer length */
- error = copy_from_user(&data_buffer_length, (void *)arg, sizeof(unsigned int));
- if (error)
- goto out;
-
- /* Check size */
- if (data_buffer_length > TW_MAX_SECTORS * 512) {
- retval = -EINVAL;
- goto out;
- }
-
- /* Hardware can only do multiple of 512 byte transfers */
- data_buffer_length_adjusted = (data_buffer_length + 511) & ~511;
-
- /* Now allocate ioctl buf memory */
- cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle);
- if (cpu_addr == NULL) {
- retval = -ENOMEM;
- goto out;
- }
-
- tw_ioctl = (TW_New_Ioctl *)cpu_addr;
-
- /* Now copy down the entire ioctl */
- error = copy_from_user(tw_ioctl, (void *)arg, data_buffer_length + sizeof(TW_New_Ioctl) - 1);
- if (error)
- goto out2;
-
- passthru = (TW_Passthru *)&tw_ioctl->firmware_command;
-
- /* See which ioctl we are doing */
- switch (cmd) {
- case TW_OP_NOP:
- dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_OP_NOP.\n");
- break;
- case TW_OP_AEN_LISTEN:
- dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_AEN_LISTEN.\n");
- memset(tw_ioctl->data_buffer, 0, tw_ioctl->data_buffer_length);
-
- spin_lock_irqsave(tw_dev->host->host_lock, flags);
- if (tw_dev->aen_head == tw_dev->aen_tail) {
- tw_aen_code = TW_AEN_QUEUE_EMPTY;
- } else {
- tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head];
- if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
- tw_dev->aen_head = TW_Q_START;
- } else {
- tw_dev->aen_head = tw_dev->aen_head + 1;
- }
- }
- spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
- memcpy(tw_ioctl->data_buffer, &tw_aen_code, sizeof(tw_aen_code));
- break;
- case TW_CMD_PACKET_WITH_DATA:
- dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n");
- spin_lock_irqsave(&tw_dev->tw_lock, flags);
-
- tw_state_request_start(tw_dev, &request_id);
-
- /* Flag internal command */
- tw_dev->srb[request_id] = 0;
-
- /* Flag chrdev ioctl */
- tw_dev->chrdev_request_id = request_id;
-
- tw_ioctl->firmware_command.request_id = request_id;
-
- /* Load the sg list */
- switch (tw_ioctl->firmware_command.byte0.sgl_offset) {
- case 2:
- tw_ioctl->firmware_command.byte8.param.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
- tw_ioctl->firmware_command.byte8.param.sgl[0].length = data_buffer_length_adjusted;
- break;
- case 3:
- tw_ioctl->firmware_command.byte8.io.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
- tw_ioctl->firmware_command.byte8.io.sgl[0].length = data_buffer_length_adjusted;
- break;
- case 5:
- passthru->sg_list[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
- passthru->sg_list[0].length = data_buffer_length_adjusted;
- break;
- }
-
- memcpy(tw_dev->command_packet_virtual_address[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command));
-
- /* Now post the command packet to the controller */
- tw_post_command_packet(tw_dev, request_id);
- spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
-
- timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ;
-
- /* Now wait for the command to complete */
- wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
-
- /* Check if we timed out, got a signal, or didn't get
- an interrupt */
- if ((timeout <= 0) && (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)) {
- /* Now we need to reset the board */
- if (timeout == -ERESTARTSYS) {
- retval = timeout;
- } else {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
- retval = -EIO;
- }
- spin_lock_irqsave(&tw_dev->tw_lock, flags);
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- tw_dev->posted_request_count--;
- if (tw_reset_device_extension(tw_dev)) {
- printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no);
- }
- spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
- goto out2;
- }
-
- /* Now copy in the command packet response */
- memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virtual_address[request_id], sizeof(TW_Command));
-
- /* Now complete the io */
- spin_lock_irqsave(&tw_dev->tw_lock, flags);
- tw_dev->posted_request_count--;
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
- break;
- default:
- retval = -ENOTTY;
- goto out2;
- }
-
- /* Now copy the response to userspace */
- error = copy_to_user((void *)arg, tw_ioctl, sizeof(TW_New_Ioctl) + tw_ioctl->data_buffer_length - 1);
- if (error == 0)
- retval = 0;
-out2:
- /* Now free ioctl buf memory */
- pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
-out:
- up(&tw_dev->ioctl_sem);
- return retval;
-} /* End tw_chrdev_ioctl() */
-
-/* This function handles open for the character device */
-static int tw_chrdev_open(struct inode *inode, struct file *file)
-{
- unsigned int minor_number;
-
- dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n");
-
- minor_number = iminor(inode);
- if (minor_number >= tw_device_extension_count)
- return -ENODEV;
-
- return 0;
-} /* End tw_chrdev_open() */
-
-/* This function handles close for the character device */
-static int tw_chrdev_release(struct inode *inode, struct file *file)
-{
- dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_release()\n");
-
- return 0;
-} /* End tw_chrdev_release() */
-
-/* This function will clear all interrupts on the controller */
-void tw_clear_all_interrupts(TW_Device_Extension *tw_dev)
-{
- u32 control_reg_addr, control_reg_value;
-
- control_reg_addr = tw_dev->registers.control_reg_addr;
- control_reg_value = TW_STATUS_VALID_INTERRUPT;
- outl(control_reg_value, control_reg_addr);
-} /* End tw_clear_all_interrupts() */
-
-/* This function will clear the attention interrupt */
-void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev)
-{
- u32 control_reg_addr, control_reg_value;
-
- control_reg_addr = tw_dev->registers.control_reg_addr;
- control_reg_value = TW_CONTROL_CLEAR_ATTENTION_INTERRUPT;
- outl(control_reg_value, control_reg_addr);
-} /* End tw_clear_attention_interrupt() */