⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qla_sup.c

📁 h内核
💻 C
字号:
/****************************************************************************** *                  QLOGIC LINUX SOFTWARE * * QLogic ISP2x00 device driver for Linux 2.6.x * Copyright (C) 2003-2004 QLogic Corporation * (www.qlogic.com) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * ******************************************************************************/#include "qla_def.h"#include <linux/delay.h>#include <asm/uaccess.h>static uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t);static void qla2x00_nv_deselect(scsi_qla_host_t *);static void qla2x00_nv_write(scsi_qla_host_t *, uint16_t);/* * NVRAM support routines *//** * qla2x00_lock_nvram_access() -  * @ha: HA context */voidqla2x00_lock_nvram_access(scsi_qla_host_t *ha){	uint16_t data;	device_reg_t __iomem *reg = ha->iobase;	if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {		data = RD_REG_WORD(&reg->nvram);		while (data & NVR_BUSY) {			udelay(100);			data = RD_REG_WORD(&reg->nvram);		}		/* Lock resource */		WRT_REG_WORD(&reg->u.isp2300.host_semaphore, 0x1);		RD_REG_WORD(&reg->u.isp2300.host_semaphore);		udelay(5);		data = RD_REG_WORD(&reg->u.isp2300.host_semaphore);		while ((data & BIT_0) == 0) {			/* Lock failed */			udelay(100);			WRT_REG_WORD(&reg->u.isp2300.host_semaphore, 0x1);			RD_REG_WORD(&reg->u.isp2300.host_semaphore);			udelay(5);			data = RD_REG_WORD(&reg->u.isp2300.host_semaphore);		}	}}/** * qla2x00_unlock_nvram_access() -  * @ha: HA context */voidqla2x00_unlock_nvram_access(scsi_qla_host_t *ha){	device_reg_t __iomem *reg = ha->iobase;	if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {		WRT_REG_WORD(&reg->u.isp2300.host_semaphore, 0);		RD_REG_WORD(&reg->u.isp2300.host_semaphore);	}}/** * qla2x00_release_nvram_protection() -  * @ha: HA context */voidqla2x00_release_nvram_protection(scsi_qla_host_t *ha){	device_reg_t *reg;	uint32_t word;	reg = ha->iobase;	/* Release NVRAM write protection. */	if (IS_QLA2322(ha) || IS_QLA6322(ha)) {		/* Write enable. */		qla2x00_nv_write(ha, NVR_DATA_OUT);		qla2x00_nv_write(ha, 0);		qla2x00_nv_write(ha, 0);		for (word = 0; word < 8; word++)			qla2x00_nv_write(ha, NVR_DATA_OUT);		qla2x00_nv_deselect(ha);		/* Enable protection register. */		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);		qla2x00_nv_write(ha, NVR_PR_ENABLE);		qla2x00_nv_write(ha, NVR_PR_ENABLE);		for (word = 0; word < 8; word++)			qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);		qla2x00_nv_deselect(ha);		/* Clear protection register (ffff is cleared). */		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);		for (word = 0; word < 8; word++)			qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);		qla2x00_nv_deselect(ha);		/* Wait for NVRAM to become ready. */		WRT_REG_WORD(&reg->nvram, NVR_SELECT);		do {			NVRAM_DELAY();			word = RD_REG_WORD(&reg->nvram);		} while ((word & NVR_DATA_IN) == 0);	}}/** * qla2x00_get_nvram_word() - Calculates word position in NVRAM and calls the *	request routine to get the word from NVRAM. * @ha: HA context * @addr: Address in NVRAM to read * * Returns the word read from nvram @addr. */uint16_tqla2x00_get_nvram_word(scsi_qla_host_t *ha, uint32_t addr){	uint16_t	data;	uint32_t	nv_cmd;	nv_cmd = addr << 16;	nv_cmd |= NV_READ_OP;	data = qla2x00_nvram_request(ha, nv_cmd);	return (data);}/** * qla2x00_write_nvram_word() - Write NVRAM data. * @ha: HA context * @addr: Address in NVRAM to write * @data: word to program */voidqla2x00_write_nvram_word(scsi_qla_host_t *ha, uint32_t addr, uint16_t data){	int count;	uint16_t word;	uint32_t nv_cmd;	device_reg_t __iomem *reg = ha->iobase;	qla2x00_nv_write(ha, NVR_DATA_OUT);	qla2x00_nv_write(ha, 0);	qla2x00_nv_write(ha, 0);	for (word = 0; word < 8; word++)		qla2x00_nv_write(ha, NVR_DATA_OUT);	qla2x00_nv_deselect(ha);	/* Write data */	nv_cmd = (addr << 16) | NV_WRITE_OP;	nv_cmd |= data;	nv_cmd <<= 5;	for (count = 0; count < 27; count++) {		if (nv_cmd & BIT_31)			qla2x00_nv_write(ha, NVR_DATA_OUT);		else			qla2x00_nv_write(ha, 0);		nv_cmd <<= 1;	}	qla2x00_nv_deselect(ha);	/* Wait for NVRAM to become ready */	WRT_REG_WORD(&reg->nvram, NVR_SELECT);	do {		NVRAM_DELAY();		word = RD_REG_WORD(&reg->nvram);	} while ((word & NVR_DATA_IN) == 0);	qla2x00_nv_deselect(ha);	/* Disable writes */	qla2x00_nv_write(ha, NVR_DATA_OUT);	for (count = 0; count < 10; count++)		qla2x00_nv_write(ha, 0);	qla2x00_nv_deselect(ha);}/** * qla2x00_nvram_request() - Sends read command to NVRAM and gets data from *	NVRAM. * @ha: HA context * @nv_cmd: NVRAM command * * Bit definitions for NVRAM command: * *	Bit 26     = start bit *	Bit 25, 24 = opcode *	Bit 23-16  = address *	Bit 15-0   = write data * * Returns the word read from nvram @addr. */static uint16_tqla2x00_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd){	uint8_t		cnt;	device_reg_t __iomem *reg = ha->iobase;	uint16_t	data = 0;	uint16_t	reg_data;	/* Send command to NVRAM. */	nv_cmd <<= 5;	for (cnt = 0; cnt < 11; cnt++) {		if (nv_cmd & BIT_31)			qla2x00_nv_write(ha, NVR_DATA_OUT);		else			qla2x00_nv_write(ha, 0);		nv_cmd <<= 1;	}	/* Read data from NVRAM. */	for (cnt = 0; cnt < 16; cnt++) {		WRT_REG_WORD(&reg->nvram, NVR_SELECT | NVR_CLOCK);		NVRAM_DELAY();		data <<= 1;		reg_data = RD_REG_WORD(&reg->nvram);		if (reg_data & NVR_DATA_IN)			data |= BIT_0;		WRT_REG_WORD(&reg->nvram, NVR_SELECT);		RD_REG_WORD(&reg->nvram);	/* PCI Posting. */		NVRAM_DELAY();	}	/* Deselect chip. */	WRT_REG_WORD(&reg->nvram, NVR_DESELECT);	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */	NVRAM_DELAY();	return (data);}/** * qla2x00_nv_write() - Clean NVRAM operations. * @ha: HA context */static voidqla2x00_nv_deselect(scsi_qla_host_t *ha){	device_reg_t __iomem *reg = ha->iobase;	WRT_REG_WORD(&reg->nvram, NVR_DESELECT);	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */	NVRAM_DELAY();}/** * qla2x00_nv_write() - Prepare for NVRAM read/write operation. * @ha: HA context * @data: Serial interface selector */static voidqla2x00_nv_write(scsi_qla_host_t *ha, uint16_t data){	device_reg_t __iomem *reg = ha->iobase;	WRT_REG_WORD(&reg->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */	NVRAM_DELAY();	WRT_REG_WORD(&reg->nvram, data | NVR_SELECT| NVR_CLOCK |	    NVR_WRT_ENABLE);	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */	NVRAM_DELAY();	WRT_REG_WORD(&reg->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */	NVRAM_DELAY();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -