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 + -
显示快捷键?