📄 adwlib.c
字号:
/* * Low level routines for Second Generation * Advanced Systems Inc. SCSI controllers chips * * Copyright (c) 1998 Justin Gibbs. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: adwlib.c,v 1.2 1999/01/08 19:17:43 bde Exp $ *//* * Ported from: * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters * * Copyright (c) 1995-1998 Advanced System Products, Inc. * All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that redistributions of source * code retain the above copyright notice and this comment without * modification. */#include <sys/types.h>#include <sys/systm.h>#include <machine/bus_pio.h>#include <machine/bus_memio.h>#include <machine/bus.h>#include <machine/clock.h>#include <cam/cam.h>#include <cam/scsi/scsi_all.h>#include <dev/advansys/adwlib.h>struct adw_eeprom adw_default_eeprom = { ADW_EEPROM_BIOS_ENABLE, /* cfg_lsw */ 0x0000, /* cfg_msw */ 0xFFFF, /* disc_enable */ 0xFFFF, /* wdtr_able */ 0xFFFF, /* sdtr_able */ 0xFFFF, /* start_motor */ 0xFFFF, /* tagqng_able */ 0xFFFF, /* bios_scan */ 0, /* scam_tolerant */ 7, /* adapter_scsi_id */ 0, /* bios_boot_delay */ 3, /* scsi_reset_delay */ 0, /* bios_id_lun */ 0, /* termination */ 0, /* reserved1 */ { /* Bios Ctrl */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }, 0xFFFF, /* ultra_able */ 0, /* reserved2 */ ADW_DEF_MAX_HOST_QNG, /* max_host_qng */ ADW_DEF_MAX_DVC_QNG, /* max_dvc_qng */ 0, /* dvc_cntl */ 0, /* bug_fix */ { 0, 0, 0 }, /* serial_number */ 0, /* check_sum */ { /* oem_name[16] */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, /* dvc_err_code */ 0, /* adv_err_code */ 0, /* adv_err_addr */ 0, /* saved_dvc_err_code */ 0, /* saved_adv_err_code */ 0, /* saved_adv_err_addr */ 0 /* num_of_err */};static u_int16_t adw_eeprom_read_16(struct adw_softc *adw, int addr);static void adw_eeprom_write_16(struct adw_softc *adw, int addr, u_int data);static void adw_eeprom_wait(struct adw_softc *adw);intadw_find_signature(bus_space_tag_t tag, bus_space_handle_t bsh){ if (bus_space_read_1(tag, bsh, ADW_SIGNATURE_BYTE) == ADW_CHIP_ID_BYTE && bus_space_read_2(tag, bsh, ADW_SIGNATURE_WORD) == ADW_CHIP_ID_WORD) return (1); return (0);}/* * Reset Chip. */voidadw_reset_chip(struct adw_softc *adw){ adw_outw(adw, ADW_CTRL_REG, ADW_CTRL_REG_CMD_RESET); DELAY(100); adw_outw(adw, ADW_CTRL_REG, ADW_CTRL_REG_CMD_WR_IO_REG); /* * Initialize Chip registers. */ adw_outb(adw, ADW_MEM_CFG, adw_inb(adw, ADW_MEM_CFG) | ADW_MEM_CFG_RAM_SZ_8KB); adw_outw(adw, ADW_SCSI_CFG1, adw_inw(adw, ADW_SCSI_CFG1) & ~ADW_SCSI_CFG1_BIG_ENDIAN); /* * Setting the START_CTL_EM_FU 3:2 bits sets a FIFO threshold * of 128 bytes. This register is only accessible to the host. */ adw_outb(adw, ADW_DMA_CFG0, ADW_DMA_CFG0_START_CTL_EM_FU|ADW_DMA_CFG0_READ_CMD_MRM);}/* * Read the specified EEPROM location */static u_int16_tadw_eeprom_read_16(struct adw_softc *adw, int addr){ adw_outw(adw, ADW_EEP_CMD, ADW_EEP_CMD_READ | addr); adw_eeprom_wait(adw); return (adw_inw(adw, ADW_EEP_DATA));}static voidadw_eeprom_write_16(struct adw_softc *adw, int addr, u_int data){ adw_outw(adw, ADW_EEP_DATA, data); adw_outw(adw, ADW_EEP_CMD, ADW_EEP_CMD_WRITE | addr); adw_eeprom_wait(adw);}/* * Wait for and EEPROM command to complete */static voidadw_eeprom_wait(struct adw_softc *adw){ int i; for (i = 0; i < ADW_EEP_DELAY_MS; i++) { if ((adw_inw(adw, ADW_EEP_CMD) & ADW_EEP_CMD_DONE) != 0) break; DELAY(1000); } if (i == ADW_EEP_DELAY_MS) panic("%s: Timedout Reading EEPROM", adw_name(adw));}/* * Read EEPROM configuration into the specified buffer. * * Return a checksum based on the EEPROM configuration read. */u_int16_tadw_eeprom_read(struct adw_softc *adw, struct adw_eeprom *eep_buf){ u_int16_t *wbuf; u_int16_t wval; u_int16_t chksum; int eep_addr; wbuf = (u_int16_t *)eep_buf; chksum = 0; for (eep_addr = ADW_EEP_DVC_CFG_BEGIN; eep_addr < ADW_EEP_DVC_CFG_END; eep_addr++, wbuf++) { wval = adw_eeprom_read_16(adw, eep_addr); chksum += wval; *wbuf = wval; } /* checksum field is not counted in the checksum */ *wbuf = adw_eeprom_read_16(adw, eep_addr); wbuf++; /* Driver seeprom variables are not included in the checksum */ for (eep_addr = ADW_EEP_DVC_CTL_BEGIN; eep_addr < ADW_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) *wbuf = adw_eeprom_read_16(adw, eep_addr); return (chksum);}voidadw_eeprom_write(struct adw_softc *adw, struct adw_eeprom *eep_buf){ u_int16_t *wbuf; u_int16_t addr; u_int16_t chksum; wbuf = (u_int16_t *)eep_buf; chksum = 0; adw_outw(adw, ADW_EEP_CMD, ADW_EEP_CMD_WRITE_ABLE); adw_eeprom_wait(adw); /* * Write EEPROM until checksum. */ for (addr = ADW_EEP_DVC_CFG_BEGIN; addr < ADW_EEP_DVC_CFG_END; addr++, wbuf++) { chksum += *wbuf; adw_eeprom_write_16(adw, addr, *wbuf); } /* * Write calculated EEPROM checksum */ adw_eeprom_write_16(adw, addr, chksum); /* skip over buffer's checksum */ wbuf++; /* * Write the rest. */ for (addr = ADW_EEP_DVC_CTL_BEGIN; addr < ADW_EEP_MAX_WORD_ADDR; addr++, wbuf++) adw_eeprom_write_16(adw, addr, *wbuf); adw_outw(adw, ADW_EEP_CMD, ADW_EEP_CMD_WRITE_DISABLE); adw_eeprom_wait(adw);}intadw_init_chip(struct adw_softc *adw, u_int term_scsicfg1){ u_int8_t biosmem[ADW_MC_BIOSLEN]; u_int16_t *mcodebuf; u_int addr; u_int end_addr; u_int checksum; u_int scsicfg1; u_int i; /* * Save the RISC memory BIOS region before writing the microcode. * The BIOS may already be loaded and using its RISC LRAM region * so its region must be saved and restored. */ for (addr = 0; addr < ADW_MC_BIOSLEN; addr++) biosmem[addr] = adw_lram_read_8(adw, ADW_MC_BIOSMEM + addr); /* * Load the Microcode. Casting here was less work than * reformatting the supplied microcode into an array of * 16bit values... */ mcodebuf = (u_int16_t *)adw_mcode; adw_outw(adw, ADW_RAM_ADDR, 0); for (addr = 0; addr < adw_mcode_size/2; addr++) adw_outw(adw, ADW_RAM_DATA, mcodebuf[addr]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -