/* * Initio A100 device driver for Linux. * * Copyright (c) 1994-1998 Initio Corporation * Copyright (c) 2003-2004 Christoph Hellwig * All rights reserved. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * 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. */ /* * Revision History: * 07/02/98 hl - v.91n Initial drivers. * 09/14/98 hl - v1.01 Support new Kernel. * 09/22/98 hl - v1.01a Support reset. * 09/24/98 hl - v1.01b Fixed reset. * 10/05/98 hl - v1.02 split the source code and release. * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up * 01/31/99 bv - v1.02b Use mdelay instead of waitForPause * 08/08/99 bv - v1.02c Use waitForPause again. * 06/25/02 Doug Ledford <[email protected]> - v1.02d * - Remove limit on number of controllers * - Port to DMA mapping API * - Clean up interrupt handler registration * - Fix memory leaks * - Fix allocation of scsi host structs and private data * 11/18/03 Christoph Hellwig <[email protected]> * - Port to new probing API * - Fix some more leaks in init failure cases * 9/28/04 Christoph Hellwig <[email protected]> * - merge the two source files * - remove internal queueing code * 14/06/07 Alan Cox <[email protected]> * - Grand cleanup and Linuxisation */ #include <linux/module.h> #include <linux/errno.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/blkdev.h> #include <linux/spinlock.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/ioport.h> #include <linux/dma-mapping.h> #include <asm/io.h> #include <asm/irq.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> #include "a100u2w.h" static struct orc_scb *__orc_alloc_scb(struct orc_host * host); static void inia100_scb_handler(struct orc_host *host, struct orc_scb *scb); static struct orc_nvram nvram, *nvramp = …; static u8 default_nvram[64] = …; static u8 wait_chip_ready(struct orc_host * host) { … } static u8 wait_firmware_ready(struct orc_host * host) { … } /***************************************************************************/ static u8 wait_scsi_reset_done(struct orc_host * host) { … } /***************************************************************************/ static u8 wait_HDO_off(struct orc_host * host) { … } /***************************************************************************/ static u8 wait_hdi_set(struct orc_host * host, u8 * data) { … } /***************************************************************************/ static unsigned short orc_read_fwrev(struct orc_host * host) { … } /***************************************************************************/ static u8 orc_nv_write(struct orc_host * host, unsigned char address, unsigned char value) { … } /***************************************************************************/ static u8 orc_nv_read(struct orc_host * host, u8 address, u8 *ptr) { … } /** * orc_exec_scb - Queue an SCB with the HA * @host: host adapter the SCB belongs to * @scb: SCB to queue for execution */ static void orc_exec_scb(struct orc_host * host, struct orc_scb * scb) { … } /** * se2_rd_all - read SCSI parameters from EEPROM * @host: Host whose EEPROM is being loaded * * Read SCSI H/A configuration parameters from serial EEPROM */ static int se2_rd_all(struct orc_host * host) { … } /** * se2_update_all - update the EEPROM * @host: Host whose EEPROM is being updated * * Update changed bytes in the EEPROM image. */ static void se2_update_all(struct orc_host * host) { … } /** * read_eeprom - load EEPROM * @host: Host EEPROM to read * * Read the EEPROM for a given host. If it is invalid or fails * the restore the defaults and use them. */ static void read_eeprom(struct orc_host * host) { … } /** * orc_load_firmware - initialise firmware * @host: Host to set up * * Load the firmware from the EEPROM into controller SRAM. This * is basically a 4K block copy and then a 4K block read to check * correctness. The rest is convulted by the indirect interfaces * in the hardware */ static u8 orc_load_firmware(struct orc_host * host) { … } /***************************************************************************/ static void setup_SCBs(struct orc_host * host) { … } /** * init_alloc_map - initialise allocation map * @host: host map to configure * * Initialise the allocation maps for this device. If the device * is not quiescent the caller must hold the allocation lock */ static void init_alloc_map(struct orc_host * host) { … } /** * init_orchid - initialise the host adapter * @host:host adapter to initialise * * Initialise the controller and if necessary load the firmware. * * Returns -1 if the initialisation fails. */ static int init_orchid(struct orc_host * host) { … } /** * orc_reset_scsi_bus - perform bus reset * @host: host being reset * * Perform a full bus reset on the adapter. */ static int orc_reset_scsi_bus(struct orc_host * host) { … } /** * orc_device_reset - device reset handler * @host: host to reset * @cmd: command causing the reset * @target: target device * * Reset registers, reset a hanging bus and kill active and disconnected * commands for target w/o soft reset */ static int orc_device_reset(struct orc_host * host, struct scsi_cmnd *cmd, unsigned int target) { … } /** * __orc_alloc_scb - allocate an SCB * @host: host to allocate from * * Allocate an SCB and return a pointer to the SCB object. NULL * is returned if no SCB is free. The caller must already hold * the allocator lock at this point. */ static struct orc_scb *__orc_alloc_scb(struct orc_host * host) { … } /** * orc_alloc_scb - allocate an SCB * @host: host to allocate from * * Allocate an SCB and return a pointer to the SCB object. NULL * is returned if no SCB is free. */ static struct orc_scb *orc_alloc_scb(struct orc_host * host) { … } /** * orc_release_scb - release an SCB * @host: host owning the SCB * @scb: SCB that is now free * * Called to return a completed SCB to the allocation pool. Before * calling the SCB must be out of use on both the host and the HA. */ static void orc_release_scb(struct orc_host *host, struct orc_scb *scb) { … } /* * orchid_abort_scb - abort a command * * Abort a queued command that has been passed to the firmware layer * if possible. This is all handled by the firmware. We aks the firmware * and it either aborts the command or fails */ static int orchid_abort_scb(struct orc_host * host, struct orc_scb * scb) { … } static int inia100_abort_cmd(struct orc_host * host, struct scsi_cmnd *cmd) { … } /** * orc_interrupt - IRQ processing * @host: Host causing the interrupt * * This function is called from the IRQ handler and protected * by the host lock. While the controller reports that there are * scb's for processing we pull them off the controller, turn the * index into a host address pointer to the scb and call the scb * handler. * * Returns IRQ_HANDLED if any SCBs were processed, IRQ_NONE otherwise */ static irqreturn_t orc_interrupt(struct orc_host * host) { … } /* End of I1060Interrupt() */ /** * inia100_build_scb - build SCB * @host: host owing the control block * @scb: control block to use * @cmd: Mid layer command * * Build a host adapter control block from the SCSI mid layer command */ static int inia100_build_scb(struct orc_host * host, struct orc_scb * scb, struct scsi_cmnd * cmd) { … } /** * inia100_queue_lck - queue command with host * @cmd: Command block * * Called by the mid layer to queue a command. Process the command * block, build the host specific scb structures and if there is room * queue the command down to the controller */ static int inia100_queue_lck(struct scsi_cmnd *cmd) { … } static DEF_SCSI_QCMD(inia100_queue) /***************************************************************************** Function name : inia100_abort Description : Abort a queued command. (commands that are on the bus can't be aborted easily) Input : host - Pointer to host adapter structure Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ static int inia100_abort(struct scsi_cmnd * cmd) { … } /***************************************************************************** Function name : inia100_reset Description : Reset registers, reset a hanging bus and kill active and disconnected commands for target w/o soft reset Input : host - Pointer to host adapter structure Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ static int inia100_bus_reset(struct scsi_cmnd * cmd) { … } /***************************************************************************** Function name : inia100_device_reset Description : Reset the device Input : host - Pointer to host adapter structure Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ static int inia100_device_reset(struct scsi_cmnd * cmd) { … } /** * inia100_scb_handler - interrupt callback * @host: Host causing the interrupt * @scb: SCB the controller returned as needing processing * * Perform completion processing on a control block. Do the conversions * from host to SCSI midlayer error coding, save any sense data and * the complete with the midlayer and recycle the scb. */ static void inia100_scb_handler(struct orc_host *host, struct orc_scb *scb) { … } /** * inia100_intr - interrupt handler * @irqno: Interrupt value * @devid: Host adapter * * Entry point for IRQ handling. All the real work is performed * by orc_interrupt. */ static irqreturn_t inia100_intr(int irqno, void *devid) { … } static const struct scsi_host_template inia100_template = …; static int inia100_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { … } static void inia100_remove_one(struct pci_dev *pdev) { … } static struct pci_device_id inia100_pci_tbl[] = …; MODULE_DEVICE_TABLE(pci, inia100_pci_tbl); static struct pci_driver inia100_pci_driver = …; module_pci_driver(…) …; MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …;