📄 aic7xxx.c
字号:
#include <linux/ioport.h>#include <linux/delay.h>#include <linux/sched.h>#include <linux/pci.h>#include <linux/proc_fs.h>#include <linux/blk.h>#include <linux/tqueue.h>#include <linux/tasks.h>#include "sd.h"#include "scsi.h"#include "hosts.h"#include "aic7xxx.h"#include "aic7xxx/sequencer.h"#include "aic7xxx/scsi_message.h"#include "aic7xxx_reg.h"#include <scsi/scsicam.h>#include <linux/stat.h>#include <linux/malloc.h> /* for kmalloc() */#include <linux/config.h> /* for CONFIG_PCI *//* * To generate the correct addresses for the controller to issue * on the bus. Originally added for DEC Alpha support. */#define VIRT_TO_BUS(a) (unsigned int)virt_to_bus((void *)(a))struct proc_dir_entry proc_scsi_aic7xxx = { PROC_SCSI_AIC7XXX, 7, "aic7xxx", S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL};#define AIC7XXX_C_VERSION "5.1.13"#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))#define MIN(a,b) (((a) < (b)) ? (a) : (b))#define MAX(a,b) (((a) > (b)) ? (a) : (b))#define ALL_TARGETS -1#define ALL_CHANNELS -1#define ALL_LUNS -1#define MAX_TARGETS 16#define MAX_LUNS 8#ifndef TRUE# define TRUE 1#endif#ifndef FALSE# define FALSE 0#endif#ifndef KERNEL_VERSION# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))#endif/* * We need the bios32.h file if we are kernel version 2.1.92 or less. The * full set of pci_* changes wasn't in place until 2.1.93 */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92)# if defined(__sparc_v9__) || defined(__powerpc__)# error "PPC and Sparc platforms are only support under 2.1.92 and above"# endif# include <linux/bios32.h>#endif#if defined(__powerpc__)# define MMAPIO# ifdef mb# undef mb# endif# define mb() \ __asm__ __volatile__("eieio" ::: "memory")#elif defined(__i386__)# define MMAPIO# ifdef mb# undef mb# endif# define mb() \ __asm__ __volatile__("lock ; addl $0,0(%%esp)": : :"memory")#elif defined(__alpha__)# ifdef mb# undef mb# endif# define mb() \ __asm__ __volatile__("mb": : :"memory")#endif#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)# include <asm/spinlock.h># include <linux/smp.h># define cpuid smp_processor_id()# if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)# define DRIVER_LOCK_INIT \ spin_lock_init(&p->spin_lock);# define DRIVER_LOCK \ if(!p->cpu_lock_count[cpuid]) { \ spin_lock_irqsave(&p->spin_lock, cpu_flags); \ p->cpu_lock_count[cpuid]++; \ } else { \ p->cpu_lock_count[cpuid]++; \ }# define DRIVER_UNLOCK \ if(--p->cpu_lock_count[cpuid] == 0) \ spin_unlock_irqrestore(&p->spin_lock, cpu_flags);# else# define DRIVER_LOCK_INIT# define DRIVER_LOCK# define DRIVER_UNLOCK# endif#else# define cpuid 0# define DRIVER_LOCK_INIT# define DRIVER_LOCK \ save_flags(cpu_flags); \ cli();# define DRIVER_UNLOCK \ restore_flags(cpu_flags);# define le32_to_cpu(x) (x)# define cpu_to_le32(x) (x)#endif/* * You can try raising me if tagged queueing is enabled, or lowering * me if you only have 4 SCBs. */#ifdef CONFIG_AIC7XXX_CMDS_PER_DEVICE#define AIC7XXX_CMDS_PER_DEVICE CONFIG_AIC7XXX_CMDS_PER_DEVICE#else#define AIC7XXX_CMDS_PER_DEVICE 8#endif/* Set this to the delay in seconds after SCSI bus reset. */#ifdef CONFIG_AIC7XXX_RESET_DELAY#define AIC7XXX_RESET_DELAY CONFIG_AIC7XXX_RESET_DELAY#else#define AIC7XXX_RESET_DELAY 5#endif/* * Control collection of SCSI transfer statistics for the /proc filesystem. * * NOTE: Do NOT enable this when running on kernels version 1.2.x and below. * NOTE: This does affect performance since it has to maintain statistics. */#ifdef CONFIG_AIC7XXX_PROC_STATS#define AIC7XXX_PROC_STATS#endif/* * NOTE: Uncommenting the define below no longer has any effect, the * tagged queue value array is always active now. I've added * a setup option to set this particular array and I'm hoping * insmod will be smart enough to set it properly as well. It's * by use of this array that a person can enable tagged queueing. * The DEFAULT_TAG_COMMANDS define has been changed to disable * tagged queueing by default, so if your devices can handle tagged * queueing you will need to add a line to their lilo.conf file like: * append="aic7xxx=verbose,tag_info:{{32,32,32,32},{32,32,32,32}}" * which will result in the first four devices on the first two * controllers being set to a tagged queue depth of 32. * * Set this for defining the number of tagged commands on a device * by device, and controller by controller basis. The first set * of tagged commands will be used for the first detected aic7xxx * controller, the second set will be used for the second detected * aic7xxx controller, and so on. These values will *only* be used * for targets that are tagged queueing capable; these values will * be ignored in all other cases. The tag_commands is an array of * 16 to allow for wide and twin adapters. Twin adapters will use * indexes 0-7 for channel 0, and indexes 8-15 for channel 1. * * *** Determining commands per LUN *** * * When AIC7XXX_CMDS_PER_DEVICE is not defined, the driver will use its * own algorithm to determine the commands/LUN. If SCB paging is * enabled, which is always now, the default is 8 commands per lun * that indicates it supports tagged queueing. All non-tagged devices * use an internal queue depth of 3, with no more than one of those * three commands active at one time. *//* #define AIC7XXX_TAGGED_QUEUEING_BY_DEVICE */typedef struct{ unsigned char tag_commands[16]; /* Allow for wide/twin adapters. */} adapter_tag_info_t;/* * Make a define that will tell the driver not to use tagged queueing * by default. */#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT#define DEFAULT_TAG_COMMANDS {0, 0, 0, 0, 0, 0, 0, 0,\ 0, 0, 0, 0, 0, 0, 0, 0}#else#define DEFAULT_TAG_COMMANDS {255, 255, 255, 255, 255, 255, 255, 255,\ 255, 255, 255, 255, 255, 255, 255, 255}#endif/* * Modify this as you see fit for your system. By setting tag_commands * to 0, the driver will use it's own algorithm for determining the * number of commands to use (see above). When 255, the driver will * not enable tagged queueing for that particular device. When positive * (> 0) and (< 255) the values in the array are used for the queue_depth. * Note that the maximum value for an entry is 254, but you're insane if * you try to use that many commands on one device. * * In this example, the first line will disable tagged queueing for all * the devices on the first probed aic7xxx adapter. * * The second line enables tagged queueing with 4 commands/LUN for IDs * (1, 2-11, 13-15), disables tagged queueing for ID 12, and tells the * driver to use its own algorithm for ID 1. * * The third line is the same as the first line. * * The fourth line disables tagged queueing for devices 0 and 3. It * enables tagged queueing for the other IDs, with 16 commands/LUN * for IDs 1 and 4, 127 commands/LUN for ID 8, and 4 commands/LUN for * IDs 2, 5-7, and 9-15. *//* * NOTE: The below structure is for reference only, the actual structure * to modify in order to change things is located around line * number 1305adapter_tag_info_t aic7xxx_tag_info[] ={ {DEFAULT_TAG_COMMANDS}, {{4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 255, 4, 4, 4}}, {DEFAULT_TAG_COMMANDS}, {{255, 16, 4, 255, 16, 4, 4, 4, 127, 4, 4, 4, 4, 4, 4, 4}}};*/static adapter_tag_info_t aic7xxx_tag_info[] ={ {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}, {DEFAULT_TAG_COMMANDS}};/* * Define an array of board names that can be indexed by aha_type. * Don't forget to change this when changing the types! */static const char *board_names[] = { "AIC-7xxx Unknown", /* AIC_NONE */ "Adaptec AIC-7810 Hardware RAID Controller", /* AIC_7810 */ "Adaptec AIC-7770 SCSI host adapter", /* AIC_7770 */ "Adaptec AHA-274X SCSI host adapter", /* AIC_7771 */ "Adaptec AHA-284X SCSI host adapter", /* AIC_284x */ "Adaptec AIC-7850 SCSI host adapter", /* AIC_7850 */ "Adaptec AIC-7855 SCSI host adapter", /* AIC_7855 */ "Adaptec AIC-7860 Ultra SCSI host adapter", /* AIC_7860 */ "Adaptec AHA-2940A Ultra SCSI host adapter", /* AIC_7861 */ "Adaptec AIC-7870 SCSI host adapter", /* AIC_7870 */ "Adaptec AHA-294X SCSI host adapter", /* AIC_7871 */ "Adaptec AHA-394X SCSI host adapter", /* AIC_7872 */ "Adaptec AHA-398X SCSI host adapter", /* AIC_7873 */ "Adaptec AHA-2944 SCSI host adapter", /* AIC_7874 */ "Adaptec AIC-7880 Ultra SCSI host adapter", /* AIC_7880 */ "Adaptec AHA-294X Ultra SCSI host adapter", /* AIC_7881 */ "Adaptec AHA-394X Ultra SCSI host adapter", /* AIC_7882 */ "Adaptec AHA-398X Ultra SCSI host adapter", /* AIC_7883 */ "Adaptec AHA-2944 Ultra SCSI host adapter", /* AIC_7884 */ "Adaptec AIC-7895 Ultra SCSI host adapter", /* AIC_7895 */ "Adaptec AIC-7890/1 Ultra2 SCSI host adapter", /* AIC_7890 */ "Adaptec AHA-293X Ultra2 SCSI host adapter", /* AIC_7890 */ "Adaptec AHA-294X Ultra2 SCSI host adapter", /* AIC_7890 */ "Adaptec AIC-7896/7 Ultra2 SCSI host adapter", /* AIC_7896 */ "Adaptec AHA-394X Ultra2 SCSI host adapter", /* AIC_7897 */ "Adaptec AHA-395X Ultra2 SCSI host adapter", /* AIC_7897 */ "Adaptec PCMCIA SCSI controller", /* card bus stuff */ "Adaptec AIC-7892 Ultra 160/m SCSI host adapter", /* AIC_7892 */ "Adaptec AIC-7899 Ultra 160/m SCSI host adapter", /* AIC_7899 */};/* * There should be a specific return value for this in scsi.h, but * it seems that most drivers ignore it. */#define DID_UNDERFLOW DID_ERROR/* * What we want to do is have the higher level scsi driver requeue * the command to us. There is no specific driver status for this * condition, but the higher level scsi driver will requeue the * command on a DID_BUS_BUSY error. * * Upon further inspection and testing, it seems that DID_BUS_BUSY * will *always* retry the command. We can get into an infinite loop * if this happens when we really want some sort of counter that * will automatically abort/reset the command after so many retries. * Using DID_ERROR will do just that. (Made by a suggestion by * Doug Ledford 8/1/96) */#define DID_RETRY_COMMAND DID_ERROR#define HSCSIID 0x07#define SCSI_RESET 0x040/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -