^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Generic Generic NCR5380 driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 1993, Drew Eckhardt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Visionary Computing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (Unix and Linux consulting and custom programming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * drew@colorado.edu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * +1 (303) 440-4894
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * K.Lentin@cs.monash.edu.au
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * NCR53C400A extensions (c) 1996, Ingmar Baumgart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * ingmar@gonzo.schwaben.de
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * DTC3181E extensions (c) 1997, Ronald van Cuijlenborg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * ronald.van.cuijlenborg@tip.nl or nutty@dds.nl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Added ISAPNP support for DTC436 adapters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Thomas Sailer, sailer@ife.ee.ethz.ch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * See Documentation/scsi/g_NCR5380.rst for more info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/isa.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/pnp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* Definitions for the core NCR5380 driver. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define NCR5380_read(reg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ioread8(hostdata->io + hostdata->offset + (reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define NCR5380_write(reg, value) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) iowrite8(value, hostdata->io + hostdata->offset + (reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define NCR5380_implementation_fields \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int offset; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int c400_ctl_status; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int c400_blk_cnt; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int c400_host_buf; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int io_width; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int pdma_residual; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int board
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define NCR5380_dma_xfer_len generic_NCR5380_dma_xfer_len
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define NCR5380_dma_recv_setup generic_NCR5380_precv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define NCR5380_dma_send_setup generic_NCR5380_psend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define NCR5380_dma_residual generic_NCR5380_dma_residual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define NCR5380_intr generic_NCR5380_intr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define NCR5380_queue_command generic_NCR5380_queue_command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define NCR5380_abort generic_NCR5380_abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define NCR5380_host_reset generic_NCR5380_host_reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define NCR5380_info generic_NCR5380_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define NCR5380_io_delay(x) udelay(x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #include "NCR5380.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define DRV_MODULE_NAME "g_NCR5380"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define NCR53C400_mem_base 0x3880
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define NCR53C400_host_buffer 0x3900
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define NCR53C400_region_size 0x3a00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define BOARD_NCR5380 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define BOARD_NCR53C400 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define BOARD_NCR53C400A 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define BOARD_DTC3181E 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define BOARD_HP_C2502 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define IRQ_AUTO 254
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define MAX_CARDS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define DMA_MAX_SIZE 32768
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* old-style parameters for compatibility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int ncr_irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static int ncr_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int ncr_5380;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int ncr_53c400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static int ncr_53c400a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int dtc_3181e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int hp_c2502;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) module_param_hw(ncr_irq, int, irq, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) module_param_hw(ncr_addr, int, ioport, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) module_param(ncr_5380, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) module_param(ncr_53c400, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) module_param(ncr_53c400a, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) module_param(dtc_3181e, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) module_param(hp_c2502, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int irq[] = { -1, -1, -1, -1, -1, -1, -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) module_param_hw_array(irq, int, irq, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) MODULE_PARM_DESC(irq, "IRQ number(s) (0=none, 254=auto [default])");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int base[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) module_param_hw_array(base, int, ioport, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) MODULE_PARM_DESC(base, "base address(es)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int card[] = { -1, -1, -1, -1, -1, -1, -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) module_param_array(card, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) MODULE_PARM_DESC(card, "card type (0=NCR5380, 1=NCR53C400, 2=NCR53C400A, 3=DTC3181E, 4=HP C2502)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) MODULE_ALIAS("g_NCR5380_mmio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static void g_NCR5380_trigger_irq(struct Scsi_Host *instance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct NCR5380_hostdata *hostdata = shost_priv(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * An interrupt is triggered whenever BSY = false, SEL = true
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * and a bit set in the SELECT_ENABLE_REG is asserted on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * SCSI bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * Note that the bus is only driven when the phase control signals
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * (I/O, C/D, and MSG) match those in the TCR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) NCR5380_write(TARGET_COMMAND_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) NCR5380_write(INITIATOR_COMMAND_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) NCR5380_write(SELECT_ENABLE_REG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) NCR5380_write(TARGET_COMMAND_REG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * g_NCR5380_probe_irq - find the IRQ of a NCR5380 or equivalent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * @instance: SCSI host instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * Autoprobe for the IRQ line used by the card by triggering an IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * and then looking to see what interrupt actually turned up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int g_NCR5380_probe_irq(struct Scsi_Host *instance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct NCR5380_hostdata *hostdata = shost_priv(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int irq_mask, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) irq_mask = probe_irq_on();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) g_NCR5380_trigger_irq(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) irq = probe_irq_off(irq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return NO_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * Configure I/O address of 53C400A or DTC436 by writing magic numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * to ports 0x779 and 0x379.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static void magic_configure(int idx, u8 irq, u8 magic[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u8 cfg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) outb(magic[0], 0x779);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) outb(magic[1], 0x379);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) outb(magic[2], 0x379);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) outb(magic[3], 0x379);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) outb(magic[4], 0x379);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (irq == 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) irq = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (idx >= 0 && idx <= 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) cfg = 0x80 | idx | (irq << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) outb(cfg, 0x379);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static irqreturn_t legacy_empty_irq_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static int legacy_find_free_irq(int *irq_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) while (*irq_table != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (!request_irq(*irq_table, legacy_empty_irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) IRQF_PROBE_SHARED, "Test IRQ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) (void *)irq_table)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) free_irq(*irq_table, (void *) irq_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return *irq_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) irq_table++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static unsigned int ncr_53c400a_ports[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static unsigned int dtc_3181e_ports[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static u8 ncr_53c400a_magic[] = { /* 53C400A & DTC436 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 0x59, 0xb9, 0xc5, 0xae, 0xa6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static u8 hp_c2502_magic[] = { /* HP C2502 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 0x0f, 0x22, 0xf0, 0x20, 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static int hp_c2502_irqs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 9, 5, 7, 3, 4, -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static int generic_NCR5380_init_one(struct scsi_host_template *tpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct device *pdev, int base, int irq, int board)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) bool is_pmio = base <= 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) unsigned int *ports = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u8 *magic = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int port_idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) unsigned long region_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct Scsi_Host *instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct NCR5380_hostdata *hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) u8 __iomem *iomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) switch (board) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) case BOARD_NCR5380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) flags = FLAG_NO_PSEUDO_DMA | FLAG_DMA_FIXUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) case BOARD_NCR53C400A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ports = ncr_53c400a_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) magic = ncr_53c400a_magic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) case BOARD_HP_C2502:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ports = ncr_53c400a_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) magic = hp_c2502_magic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) case BOARD_DTC3181E:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ports = dtc_3181e_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) magic = ncr_53c400a_magic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (is_pmio && ports && magic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* wakeup sequence for the NCR53C400A and DTC3181E */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* Disable the adapter and look for a free io port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) magic_configure(-1, 0, magic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) region_size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) for (i = 0; ports[i]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (base == ports[i]) { /* index found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!request_region(ports[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) region_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) "ncr53c80"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) for (i = 0; ports[i]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!request_region(ports[i], region_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) "ncr53c80"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (inb(ports[i]) == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) release_region(ports[i], region_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (ports[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /* At this point we have our region reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) magic_configure(i, 0, magic); /* no IRQ yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) base = ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) outb(0xc0, base + 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (inb(base + 9) != 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) goto out_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) port_idx = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) } else if (is_pmio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* NCR5380 - no configuration, just grab */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) region_size = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!base || !request_region(base, region_size, "ncr5380"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) } else { /* MMIO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) region_size = NCR53C400_region_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (!request_mem_region(base, region_size, "ncr5380"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (is_pmio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) iomem = ioport_map(base, region_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) iomem = ioremap(base, region_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (!iomem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) goto out_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) instance = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (instance == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto out_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) hostdata = shost_priv(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) hostdata->board = board;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) hostdata->io = iomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) hostdata->region_size = region_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (is_pmio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) hostdata->io_port = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) hostdata->io_width = 1; /* 8-bit PDMA by default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) hostdata->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * On NCR53C400 boards, NCR5380 registers are mapped 8 past
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * the base address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) switch (board) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) case BOARD_NCR53C400:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) hostdata->io_port += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) hostdata->c400_ctl_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) hostdata->c400_blk_cnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) hostdata->c400_host_buf = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) case BOARD_DTC3181E:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) hostdata->io_width = 2; /* 16-bit PDMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case BOARD_NCR53C400A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) case BOARD_HP_C2502:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) hostdata->c400_ctl_status = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) hostdata->c400_blk_cnt = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) hostdata->c400_host_buf = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) hostdata->base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) hostdata->offset = NCR53C400_mem_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) switch (board) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) case BOARD_NCR53C400:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) hostdata->c400_ctl_status = 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) hostdata->c400_blk_cnt = 0x101;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) hostdata->c400_host_buf = 0x104;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) case BOARD_DTC3181E:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) case BOARD_NCR53C400A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) case BOARD_HP_C2502:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) pr_err(DRV_MODULE_NAME ": unknown register offsets\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) goto out_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /* Check for vacant slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) NCR5380_write(MODE_REG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (NCR5380_read(MODE_REG) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) goto out_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) ret = NCR5380_init(instance, flags | FLAG_LATE_DMA_SETUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) goto out_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) switch (board) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) case BOARD_NCR53C400:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) case BOARD_DTC3181E:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) case BOARD_NCR53C400A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case BOARD_HP_C2502:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) NCR5380_maybe_reset_bus(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* Compatibility with documented NCR5380 kernel parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (irq == 255 || irq == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) irq = NO_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) else if (irq == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) irq = IRQ_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (board == BOARD_HP_C2502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int *irq_table = hp_c2502_irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) int board_irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) switch (irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) case NO_IRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) board_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) case IRQ_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) board_irq = legacy_find_free_irq(irq_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) while (*irq_table != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (*irq_table++ == irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) board_irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (board_irq <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) board_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) irq = NO_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) magic_configure(port_idx, board_irq, magic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (irq == IRQ_AUTO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) instance->irq = g_NCR5380_probe_irq(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (instance->irq == NO_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) shost_printk(KERN_INFO, instance, "no irq detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) instance->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (instance->irq == NO_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) shost_printk(KERN_INFO, instance, "no irq provided\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (instance->irq != NO_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (request_irq(instance->irq, generic_NCR5380_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 0, "NCR5380", instance)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) instance->irq = NO_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) shost_printk(KERN_INFO, instance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) "irq %d denied\n", instance->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) shost_printk(KERN_INFO, instance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) "irq %d acquired\n", instance->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ret = scsi_add_host(instance, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) goto out_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) scsi_scan_host(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) dev_set_drvdata(pdev, instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) out_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (instance->irq != NO_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) free_irq(instance->irq, instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) NCR5380_exit(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) out_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) scsi_host_put(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) out_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) iounmap(iomem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) out_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (is_pmio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) release_region(base, region_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) release_mem_region(base, region_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static void generic_NCR5380_release_resources(struct Scsi_Host *instance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct NCR5380_hostdata *hostdata = shost_priv(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) void __iomem *iomem = hostdata->io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) unsigned long io_port = hostdata->io_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) unsigned long base = hostdata->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) unsigned long region_size = hostdata->region_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) scsi_remove_host(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (instance->irq != NO_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) free_irq(instance->irq, instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) NCR5380_exit(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) scsi_host_put(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) iounmap(iomem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (io_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) release_region(io_port, region_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) release_mem_region(base, region_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /* wait_for_53c80_access - wait for 53C80 registers to become accessible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * @hostdata: scsi host private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * The registers within the 53C80 logic block are inaccessible until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * bit 7 in the 53C400 control status register gets asserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static void wait_for_53c80_access(struct NCR5380_hostdata *hostdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) int count = 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (hostdata->board == BOARD_DTC3181E)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) udelay(4); /* DTC436 chip hangs without this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) } while (--count > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) scmd_printk(KERN_ERR, hostdata->connected,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) "53c80 registers not accessible, device will be reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * generic_NCR5380_precv - pseudo DMA receive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * @hostdata: scsi host private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * @dst: buffer to write into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * @len: transfer size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * Perform a pseudo DMA mode receive from a 53C400 or equivalent device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) unsigned char *dst, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) int residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) int start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) NCR5380_write(hostdata->c400_blk_cnt, len / 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (start == len - 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /* Ignore End of DMA interrupt for the final buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (NCR5380_poll_politely(hostdata, hostdata->c400_ctl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) CSR_HOST_BUF_NOT_RDY, 0, HZ / 64) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) CSR_HOST_BUF_NOT_RDY, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) hostdata->c400_ctl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) CSR_GATED_53C80_IRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) CSR_GATED_53C80_IRQ, HZ / 64) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (hostdata->io_port && hostdata->io_width == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) insw(hostdata->io_port + hostdata->c400_host_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) dst + start, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) else if (hostdata->io_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) insb(hostdata->io_port + hostdata->c400_host_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) dst + start, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) memcpy_fromio(dst + start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) hostdata->io + NCR53C400_host_buffer, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) start += 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) } while (start < len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) residual = len - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (residual != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) /* 53c80 interrupt or transfer timeout. Reset 53c400 logic. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) wait_for_53c80_access(hostdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (residual == 0 && NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) BASR_END_DMA_TRANSFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) BASR_END_DMA_TRANSFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) HZ / 64) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) scmd_printk(KERN_ERR, hostdata->connected, "%s: End of DMA timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) hostdata->pdma_residual = residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * generic_NCR5380_psend - pseudo DMA send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * @hostdata: scsi host private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * @src: buffer to read from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * @len: transfer size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * Perform a pseudo DMA mode send to a 53C400 or equivalent device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static inline int generic_NCR5380_psend(struct NCR5380_hostdata *hostdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) unsigned char *src, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) int residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) int start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) NCR5380_write(hostdata->c400_blk_cnt, len / 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) CSR_HOST_BUF_NOT_RDY, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) hostdata->c400_ctl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) CSR_GATED_53C80_IRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) CSR_GATED_53C80_IRQ, HZ / 64) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /* Both 128 B buffers are in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (start >= 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) start -= 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (start >= 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) start -= 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (start >= len && NCR5380_read(hostdata->c400_blk_cnt) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /* Host buffer is empty, other one is in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (start >= 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) start -= 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (start >= len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (hostdata->io_port && hostdata->io_width == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) outsw(hostdata->io_port + hostdata->c400_host_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) src + start, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) else if (hostdata->io_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) outsb(hostdata->io_port + hostdata->c400_host_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) src + start, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) memcpy_toio(hostdata->io + NCR53C400_host_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) src + start, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) start += 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) residual = len - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (residual != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) /* 53c80 interrupt or transfer timeout. Reset 53c400 logic. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) wait_for_53c80_access(hostdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (residual == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) TCR_LAST_BYTE_SENT, TCR_LAST_BYTE_SENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) HZ / 64) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) scmd_printk(KERN_ERR, hostdata->connected,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) "%s: Last Byte Sent timeout\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) BASR_END_DMA_TRANSFER, BASR_END_DMA_TRANSFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) HZ / 64) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) scmd_printk(KERN_ERR, hostdata->connected, "%s: End of DMA timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) hostdata->pdma_residual = residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static int generic_NCR5380_dma_xfer_len(struct NCR5380_hostdata *hostdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct scsi_cmnd *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) int transfersize = cmd->SCp.this_residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (hostdata->flags & FLAG_NO_PSEUDO_DMA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) /* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (transfersize % 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /* Limit PDMA send to 512 B to avoid random corruption on DTC3181E */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (hostdata->board == BOARD_DTC3181E &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) cmd->sc_data_direction == DMA_TO_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) transfersize = min(cmd->SCp.this_residual, 512);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return min(transfersize, DMA_MAX_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) static int generic_NCR5380_dma_residual(struct NCR5380_hostdata *hostdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return hostdata->pdma_residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /* Include the core driver code. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) #include "NCR5380.c"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static struct scsi_host_template driver_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) .module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) .proc_name = DRV_MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) .name = "Generic NCR5380/NCR53C400 SCSI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) .info = generic_NCR5380_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) .queuecommand = generic_NCR5380_queue_command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) .eh_abort_handler = generic_NCR5380_abort,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) .eh_host_reset_handler = generic_NCR5380_host_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .can_queue = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) .this_id = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) .sg_tablesize = SG_ALL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) .cmd_per_lun = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) .dma_boundary = PAGE_SIZE - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) .cmd_size = NCR5380_CMD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) .max_sectors = 128,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static int generic_NCR5380_isa_match(struct device *pdev, unsigned int ndev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) int ret = generic_NCR5380_init_one(&driver_template, pdev, base[ndev],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) irq[ndev], card[ndev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (base[ndev])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) printk(KERN_WARNING "Card not found at address 0x%03x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) base[ndev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) static int generic_NCR5380_isa_remove(struct device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) unsigned int ndev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) generic_NCR5380_release_resources(dev_get_drvdata(pdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) dev_set_drvdata(pdev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) static struct isa_driver generic_NCR5380_isa_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) .match = generic_NCR5380_isa_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) .remove = generic_NCR5380_isa_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) .name = DRV_MODULE_NAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static const struct pnp_device_id generic_NCR5380_pnp_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) { .id = "DTC436e", .driver_data = BOARD_DTC3181E },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) { .id = "" }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) MODULE_DEVICE_TABLE(pnp, generic_NCR5380_pnp_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) static int generic_NCR5380_pnp_probe(struct pnp_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) const struct pnp_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) int base, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (pnp_activate_dev(pdev) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) base = pnp_port_start(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) irq = pnp_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return generic_NCR5380_init_one(&driver_template, &pdev->dev, base, irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) id->driver_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static void generic_NCR5380_pnp_remove(struct pnp_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) generic_NCR5380_release_resources(pnp_get_drvdata(pdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) pnp_set_drvdata(pdev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) static struct pnp_driver generic_NCR5380_pnp_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) .name = DRV_MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .id_table = generic_NCR5380_pnp_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .probe = generic_NCR5380_pnp_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .remove = generic_NCR5380_pnp_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) #endif /* defined(CONFIG_PNP) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) static int pnp_registered, isa_registered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) static int __init generic_NCR5380_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) /* compatibility with old-style parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (irq[0] == -1 && base[0] == 0 && card[0] == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) irq[0] = ncr_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) base[0] = ncr_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (ncr_5380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) card[0] = BOARD_NCR5380;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (ncr_53c400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) card[0] = BOARD_NCR53C400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (ncr_53c400a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) card[0] = BOARD_NCR53C400A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (dtc_3181e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) card[0] = BOARD_DTC3181E;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (hp_c2502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) card[0] = BOARD_HP_C2502;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (!pnp_register_driver(&generic_NCR5380_pnp_driver))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) pnp_registered = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) ret = isa_register_driver(&generic_NCR5380_isa_driver, MAX_CARDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) isa_registered = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return (pnp_registered || isa_registered) ? 0 : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) static void __exit generic_NCR5380_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (pnp_registered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) pnp_unregister_driver(&generic_NCR5380_pnp_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (isa_registered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) isa_unregister_driver(&generic_NCR5380_isa_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) module_init(generic_NCR5380_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) module_exit(generic_NCR5380_exit);