dc395x.c
来自「linux 内核源代码」· C语言 代码 · 共 2,191 行 · 第 1/5 页
C
2,191 行
* 101 150ns, 6.6 MHz * 110 175ns, 5.7 MHz * 111 200ns, 5.0 MHz *//*static u8 clock_period[] = {12,19,25,31,37,44,50,62};*//* real period:48ns,76ns,100ns,124ns,148ns,176ns,200ns,248ns */static u8 clock_period[] = { 12, 18, 25, 31, 37, 43, 50, 62 };static u16 clock_speed[] = { 200, 133, 100, 80, 67, 58, 50, 40 };/*--------------------------------------------------------------------------- Configuration ---------------------------------------------------------------------------*//* * Module/boot parameters currently effect *all* instances of the * card in the system. *//* * Command line parameters are stored in a structure below. * These are the index's into the structure for the various * command line options. */#define CFG_ADAPTER_ID 0#define CFG_MAX_SPEED 1#define CFG_DEV_MODE 2#define CFG_ADAPTER_MODE 3#define CFG_TAGS 4#define CFG_RESET_DELAY 5#define CFG_NUM 6 /* number of configuration items *//* * Value used to indicate that a command line override * hasn't been used to modify the value. */#define CFG_PARAM_UNSET -1/* * Hold command line parameters. */struct ParameterData { int value; /* value of this setting */ int min; /* minimum value */ int max; /* maximum value */ int def; /* default value */ int safe; /* safe value */};static struct ParameterData __devinitdata cfg_data[] = { { /* adapter id */ CFG_PARAM_UNSET, 0, 15, 7, 7 }, { /* max speed */ CFG_PARAM_UNSET, 0, 7, 1, /* 13.3Mhz */ 4, /* 6.7Hmz */ }, { /* dev mode */ CFG_PARAM_UNSET, 0, 0x3f, NTC_DO_PARITY_CHK | NTC_DO_DISCONNECT | NTC_DO_SYNC_NEGO | NTC_DO_WIDE_NEGO | NTC_DO_TAG_QUEUEING | NTC_DO_SEND_START, NTC_DO_PARITY_CHK | NTC_DO_SEND_START }, { /* adapter mode */ CFG_PARAM_UNSET, 0, 0x2f,#ifdef CONFIG_SCSI_MULTI_LUN NAC_SCANLUN |#endif NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET /*| NAC_ACTIVE_NEG*/, NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET | 0x08 }, { /* tags */ CFG_PARAM_UNSET, 0, 5, 3, /* 16 tags (??) */ 2, }, { /* reset delay */ CFG_PARAM_UNSET, 0, 180, 1, /* 1 second */ 10, /* 10 seconds */ }};/* * Safe settings. If set to zero the BIOS/default values with * command line overrides will be used. If set to 1 then safe and * slow settings will be used. */static int use_safe_settings = 0;module_param_named(safe, use_safe_settings, bool, 0);MODULE_PARM_DESC(safe, "Use safe and slow settings only. Default: false");module_param_named(adapter_id, cfg_data[CFG_ADAPTER_ID].value, int, 0);MODULE_PARM_DESC(adapter_id, "Adapter SCSI ID. Default 7 (0-15)");module_param_named(max_speed, cfg_data[CFG_MAX_SPEED].value, int, 0);MODULE_PARM_DESC(max_speed, "Maximum bus speed. Default 1 (0-7) Speeds: 0=20, 1=13.3, 2=10, 3=8, 4=6.7, 5=5.8, 6=5, 7=4 Mhz");module_param_named(dev_mode, cfg_data[CFG_DEV_MODE].value, int, 0);MODULE_PARM_DESC(dev_mode, "Device mode.");module_param_named(adapter_mode, cfg_data[CFG_ADAPTER_MODE].value, int, 0);MODULE_PARM_DESC(adapter_mode, "Adapter mode.");module_param_named(tags, cfg_data[CFG_TAGS].value, int, 0);MODULE_PARM_DESC(tags, "Number of tags (1<<x). Default 3 (0-5)");module_param_named(reset_delay, cfg_data[CFG_RESET_DELAY].value, int, 0);MODULE_PARM_DESC(reset_delay, "Reset delay in seconds. Default 1 (0-180)");/** * set_safe_settings - if the use_safe_settings option is set then * set all values to the safe and slow values. **/static void __devinit set_safe_settings(void){ if (use_safe_settings) { int i; dprintkl(KERN_INFO, "Using safe settings.\n"); for (i = 0; i < CFG_NUM; i++) { cfg_data[i].value = cfg_data[i].safe; } }}/** * fix_settings - reset any boot parameters which are out of range * back to the default values. **/static void __devinit fix_settings(void){ int i; dprintkdbg(DBG_1, "setup: AdapterId=%08x MaxSpeed=%08x DevMode=%08x " "AdapterMode=%08x Tags=%08x ResetDelay=%08x\n", cfg_data[CFG_ADAPTER_ID].value, cfg_data[CFG_MAX_SPEED].value, cfg_data[CFG_DEV_MODE].value, cfg_data[CFG_ADAPTER_MODE].value, cfg_data[CFG_TAGS].value, cfg_data[CFG_RESET_DELAY].value); for (i = 0; i < CFG_NUM; i++) { if (cfg_data[i].value < cfg_data[i].min || cfg_data[i].value > cfg_data[i].max) cfg_data[i].value = cfg_data[i].def; }}/* * Mapping from the eeprom delay index value (index into this array) * to the number of actual seconds that the delay should be for. */static char __devinitdata eeprom_index_to_delay_map[] = { 1, 3, 5, 10, 16, 30, 60, 120 };/** * eeprom_index_to_delay - Take the eeprom delay setting and convert it * into a number of seconds. * * @eeprom: The eeprom structure in which we find the delay index to map. **/static void __devinit eeprom_index_to_delay(struct NvRamType *eeprom){ eeprom->delay_time = eeprom_index_to_delay_map[eeprom->delay_time];}/** * delay_to_eeprom_index - Take a delay in seconds and return the * closest eeprom index which will delay for at least that amount of * seconds. * * @delay: The delay, in seconds, to find the eeprom index for. **/static int __devinit delay_to_eeprom_index(int delay){ u8 idx = 0; while (idx < 7 && eeprom_index_to_delay_map[idx] < delay) idx++; return idx;}/** * eeprom_override - Override the eeprom settings, in the provided * eeprom structure, with values that have been set on the command * line. * * @eeprom: The eeprom data to override with command line options. **/static void __devinit eeprom_override(struct NvRamType *eeprom){ u8 id; /* Adapter Settings */ if (cfg_data[CFG_ADAPTER_ID].value != CFG_PARAM_UNSET) eeprom->scsi_id = (u8)cfg_data[CFG_ADAPTER_ID].value; if (cfg_data[CFG_ADAPTER_MODE].value != CFG_PARAM_UNSET) eeprom->channel_cfg = (u8)cfg_data[CFG_ADAPTER_MODE].value; if (cfg_data[CFG_RESET_DELAY].value != CFG_PARAM_UNSET) eeprom->delay_time = delay_to_eeprom_index( cfg_data[CFG_RESET_DELAY].value); if (cfg_data[CFG_TAGS].value != CFG_PARAM_UNSET) eeprom->max_tag = (u8)cfg_data[CFG_TAGS].value; /* Device Settings */ for (id = 0; id < DC395x_MAX_SCSI_ID; id++) { if (cfg_data[CFG_DEV_MODE].value != CFG_PARAM_UNSET) eeprom->target[id].cfg0 = (u8)cfg_data[CFG_DEV_MODE].value; if (cfg_data[CFG_MAX_SPEED].value != CFG_PARAM_UNSET) eeprom->target[id].period = (u8)cfg_data[CFG_MAX_SPEED].value; }}/*--------------------------------------------------------------------------- ---------------------------------------------------------------------------*/static unsigned int list_size(struct list_head *head){ unsigned int count = 0; struct list_head *pos; list_for_each(pos, head) count++; return count;}static struct DeviceCtlBlk *dcb_get_next(struct list_head *head, struct DeviceCtlBlk *pos){ int use_next = 0; struct DeviceCtlBlk* next = NULL; struct DeviceCtlBlk* i; if (list_empty(head)) return NULL; /* find supplied dcb and then select the next one */ list_for_each_entry(i, head, list) if (use_next) { next = i; break; } else if (i == pos) { use_next = 1; } /* if no next one take the head one (ie, wraparound) */ if (!next) list_for_each_entry(i, head, list) { next = i; break; } return next;}static void free_tag(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb){ if (srb->tag_number < 255) { dcb->tag_mask &= ~(1 << srb->tag_number); /* free tag mask */ srb->tag_number = 255; }}/* Find cmd in SRB list */static inline struct ScsiReqBlk *find_cmd(struct scsi_cmnd *cmd, struct list_head *head){ struct ScsiReqBlk *i; list_for_each_entry(i, head, list) if (i->cmd == cmd) return i; return NULL;}static struct ScsiReqBlk *srb_get_free(struct AdapterCtlBlk *acb){ struct list_head *head = &acb->srb_free_list; struct ScsiReqBlk *srb = NULL; if (!list_empty(head)) { srb = list_entry(head->next, struct ScsiReqBlk, list); list_del(head->next); dprintkdbg(DBG_0, "srb_get_free: srb=%p\n", srb); } return srb;}static void srb_free_insert(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb){ dprintkdbg(DBG_0, "srb_free_insert: srb=%p\n", srb); list_add_tail(&srb->list, &acb->srb_free_list);}static void srb_waiting_insert(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb){ dprintkdbg(DBG_0, "srb_waiting_insert: (pid#%li) <%02i-%i> srb=%p\n", srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_add(&srb->list, &dcb->srb_waiting_list);}static void srb_waiting_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb){ dprintkdbg(DBG_0, "srb_waiting_append: (pid#%li) <%02i-%i> srb=%p\n", srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_add_tail(&srb->list, &dcb->srb_waiting_list);}static void srb_going_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb){ dprintkdbg(DBG_0, "srb_going_append: (pid#%li) <%02i-%i> srb=%p\n", srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_add_tail(&srb->list, &dcb->srb_going_list);}static void srb_going_remove(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb){ struct ScsiReqBlk *i; struct ScsiReqBlk *tmp; dprintkdbg(DBG_0, "srb_going_remove: (pid#%li) <%02i-%i> srb=%p\n", srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_for_each_entry_safe(i, tmp, &dcb->srb_going_list, list) if (i == srb) { list_del(&srb->list); break; }}static void srb_waiting_remove(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb){ struct ScsiReqBlk *i; struct ScsiReqBlk *tmp; dprintkdbg(DBG_0, "srb_waiting_remove: (pid#%li) <%02i-%i> srb=%p\n", srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_for_each_entry_safe(i, tmp, &dcb->srb_waiting_list, list) if (i == srb) { list_del(&srb->list); break; }}static void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb){ dprintkdbg(DBG_0, "srb_going_to_waiting_move: (pid#%li) <%02i-%i> srb=%p\n", srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_move(&srb->list, &dcb->srb_waiting_list);}static void srb_waiting_to_going_move(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb){ dprintkdbg(DBG_0, "srb_waiting_to_going_move: (pid#%li) <%02i-%i> srb=%p\n", srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_move(&srb->list, &dcb->srb_going_list);}/* Sets the timer to wake us up */static void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to){ if (timer_pending(&acb->waiting_timer)) return; init_timer(&acb->waiting_timer); acb->waiting_timer.function = waiting_timeout; acb->waiting_timer.data = (unsigned long) acb; if (time_before(jiffies + to, acb->scsi_host->last_reset - HZ / 2)) acb->waiting_timer.expires = acb->scsi_host->last_reset - HZ / 2 + 1; else acb->waiting_timer.expires = jiffies + to + 1; add_timer(&acb->waiting_timer);}/* Send the next command from the waiting list to the bus */static void waiting_process_next(struct AdapterCtlBlk *acb){ struct DeviceCtlBlk *start = NULL; struct DeviceCtlBlk *pos; struct DeviceCtlBlk *dcb; struct ScsiReqBlk *srb; struct list_head *dcb_list_head = &acb->dcb_list;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?