11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AUTOSENSE
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PSEUDO_DMA
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DONT_USE_INTR
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UNSAFE			/* Leave interrupts enabled during pseudo-dma I/O */
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define xNDEBUG (NDEBUG_INTR+NDEBUG_RESELECTION+\
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 NDEBUG_SELECTION+NDEBUG_ARBITRATION)
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DMA_WORKS_RIGHT
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DTC 3180/3280 driver, by
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Ray Van Tassle	rayvt@comm.mot.com
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	taken from ...
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Trantor T128/T128F/T228 driver by...
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	Drew Eckhardt
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Visionary Computing
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	(Unix and Linux consulting and custom programming)
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	drew@colorado.edu
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      +1 (303) 440-4894
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DISTRIBUTION RELEASE 1.
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For more information, please consult
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NCR 5380 Family
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCSI Protocol Controller
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Databook
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Options :
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      for commands that return with a CHECK CONDITION status.
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * increase compared to polled I/O.
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PARITY - enable parity checking.  Not supported.
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		You probably want this.
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The card is detected and initialized in one of several ways :
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1.  Autoprobe (default) - since the board is memory mapped,
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     a BIOS signature is scanned for to locate the registers.
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     An interrupt is triggered to autoprobe for the interrupt
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     line.
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2.  With command line overrides - dtc=address,irq may be
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     used on the LILO command line to override the defaults.
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*----------------------------------------------------------------*/
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* the following will set the monitor border color (useful to find
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds where something crashed or gets stuck at */
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1 = blue
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2 = green
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3 = cyan
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4 = red
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5 = magenta
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6 = yellow
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7 = white
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define rtrc(i) {inb(0x3da); outb(0x31, 0x3c0); outb((i), 0x3c0);}
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define rtrc(i) {}
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h>
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h>
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stat.h>
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
8353d5ed627df852ba8bab7f70df25290bd733792cMatthew Wilcox#include <linux/io.h>
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "scsi.h"
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_host.h>
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "dtc.h"
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AUTOPROBE_IRQ
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "NCR5380.h"
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DTC_PUBLIC_RELEASE 2
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The DTC3180 & 3280 boards are memory mapped.
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Offset from DTC_5380_OFFSET */
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DTC_CONTROL_REG		0x100	/* rw */
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define D_CR_ACCESS		0x80	/* ro set=can access 3280 registers */
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR_DIR_READ		0x40	/* rw direction, 1 = read 0 = write */
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR_RESET              0x80	/* wo  Resets 53c400 */
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR_5380_REG           0x80	/* ro  5380 registers can be accessed */
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR_TRANS_DIR          0x40	/* rw  Data transfer direction */
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR_SCSI_BUFF_INTR     0x20	/* rw  Enable int on transfer ready */
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR_5380_INTR          0x10	/* rw  Enable 5380 interrupts */
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR_SHARED_INTR        0x08	/* rw  Interrupt sharing */
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR_HOST_BUF_NOT_RDY   0x04	/* ro  Host buffer not ready */
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR_SCSI_BUF_RDY       0x02	/* ro  SCSI buffer ready */
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR_GATED_5380_IRQ     0x01	/* ro  Last block xferred */
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR_INT_BASE (CSR_SCSI_BUFF_INTR | CSR_5380_INTR)
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DTC_BLK_CNT		0x101	/* rw
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 * # of 128-byte blocks to transfer */
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define D_CR_ACCESS             0x80	/* ro set=can access 3280 registers */
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DTC_SWITCH_REG		0x3982	/* ro - DIP switches */
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DTC_RESUME_XFER		0x3982	/* wo - resume data xfer
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 * after disconnect/reconnect*/
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DTC_5380_OFFSET		0x3880	/* 8 registers here, see NCR5380.h */
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DTC_DATA_BUF		0x3900	/* rw 128 bytes long */
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct override {
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int address;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int irq;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} overrides
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef OVERRIDE
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds[] __initdata = OVERRIDE;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
1391fbe85292f50ce6186619b83ed04d1bb91dda569Alan Cox[4] __initdata = {
1401fbe85292f50ce6186619b83ed04d1bb91dda569Alan Cox	{ 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }
1411fbe85292f50ce6186619b83ed04d1bb91dda569Alan Cox};
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1446391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser#define NO_OVERRIDES ARRAY_SIZE(overrides)
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct base {
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long address;
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int noauto;
1496391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser} bases[] __initdata = {
1506391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser	{ 0xcc000, 0 },
1516391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser	{ 0xc8000, 0 },
1526391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser	{ 0xdc000, 0 },
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0xd8000, 0 }
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1566391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser#define NO_BASES ARRAY_SIZE(bases)
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const struct signature {
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *string;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int offset;
1616391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser} signatures[] = {
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{"DATA TECHNOLOGY CORPORATION BIOS", 0x25},
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1656391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser#define NO_SIGNATURES ARRAY_SIZE(signatures)
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef MODULE
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function : dtc_setup(char *str, int *ints)
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : LILO command line initialization of the overrides array,
1726391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser *
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Inputs : str - unused, ints - array of integer parameters with ints[0]
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	equal to the number of ints.
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1761fbe85292f50ce6186619b83ed04d1bb91dda569Alan Cox */
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init dtc_setup(char *str, int *ints)
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static int commandline_current = 0;
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ints[0] != 2)
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("dtc_setup: usage dtc=address,irq\n");
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (commandline_current < NO_OVERRIDES) {
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		overrides[commandline_current].address = ints[1];
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		overrides[commandline_current].irq = ints[2];
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < NO_BASES; ++i)
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (bases[i].address == ints[1]) {
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bases[i].noauto = 1;
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		++commandline_current;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
198d0be4a7d29ad0bd3ce2209dd9e46d410b632db59Christoph Hellwig * Function : int dtc_detect(struct scsi_host_template * tpnt)
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : detects and initializes DTC 3180/3280 controllers
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	that were autoprobed, overridden on the LILO command line,
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	or specified at compile time.
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Inputs : tpnt - template for this SCSI adapter.
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns : 1 if a host adapter was found, 0 if not.
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
210d0be4a7d29ad0bd3ce2209dd9e46d410b632db59Christoph Hellwigstatic int __init dtc_detect(struct scsi_host_template * tpnt)
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static int current_override = 0, current_base = 0;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Scsi_Host *instance;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int addr;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *base;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int sig, count;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tpnt->proc_name = "dtc3x80";
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tpnt->proc_info = &dtc_proc_info;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		addr = 0;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		base = NULL;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (overrides[current_override].address) {
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			addr = overrides[current_override].address;
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			base = ioremap(addr, 0x2000);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!base)
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				addr = 0;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (; !addr && (current_base < NO_BASES); ++current_base) {
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if (DTCDEBUG & DTCDEBUG_INIT)
2331fbe85292f50ce6186619b83ed04d1bb91dda569Alan Cox				printk(KERN_DEBUG "scsi-dtc : probing address %08x\n", bases[current_base].address);
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (bases[current_base].noauto)
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					continue;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				base = ioremap(bases[current_base].address, 0x2000);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!base)
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					continue;
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				for (sig = 0; sig < NO_SIGNATURES; ++sig) {
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) {
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						addr = bases[current_base].address;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if (DTCDEBUG & DTCDEBUG_INIT)
2445307b1e8b050f309901acc9c6121061206a70ba5Alan Cox						printk(KERN_DEBUG "scsi-dtc : detected board.\n");
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						goto found;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				iounmap(base);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
2531fbe85292f50ce6186619b83ed04d1bb91dda569Alan Cox		printk(KERN_DEBUG "scsi-dtc : base = %08x\n", addr);
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!addr)
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfound:
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (instance == NULL)
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		instance->base = addr;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		((struct NCR5380_hostdata *)(instance)->hostdata)->base = base;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NCR5380_init(instance, 0);
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);	/* Enable int's */
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (overrides[current_override].irq != IRQ_AUTO)
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			instance->irq = overrides[current_override].irq;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef DONT_USE_INTR
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* With interrupts enabled, it will sometimes hang when doing heavy
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * reads. So better not enable them until I finger it out. */
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (instance->irq != SCSI_IRQ_NONE)
2791e641664301744f0d381de43ae1e12343e60b479Jeff Garzik			if (request_irq(instance->irq, dtc_intr, IRQF_DISABLED,
2801e641664301744f0d381de43ae1e12343e60b479Jeff Garzik					"dtc", instance)) {
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				instance->irq = SCSI_IRQ_NONE;
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (instance->irq == SCSI_IRQ_NONE) {
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (instance->irq != SCSI_IRQ_NONE)
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		instance->irq = SCSI_IRQ_NONE;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_INFO "scsi%d : at 0x%05X", instance->host_no, (int) instance->base);
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (instance->irq == SCSI_IRQ_NONE)
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(" interrupts disabled");
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(" irq %d", instance->irq);
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE);
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NCR5380_print_options(instance);
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("\n");
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		++current_override;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		++count;
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function : int dtc_biosparam(Disk * disk, struct block_device *dev, int *ip)
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	the specified device / size.
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Inputs : size = size of device in sectors (512 bytes), dev = block device
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	major / minor, ip[] = {heads, sectors, cylinders}
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns : always 0 (success), initializes ip
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX Most SCSI boards use this mapping, I could be incorrect.  Some one
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * using hard disks on a trantor should verify that this mapping corresponds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to that used by the BIOS / ASPI driver by running the linux fdisk program
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and matching the H_C_S coordinates to what DOS uses.
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev,
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 sector_t capacity, int *ip)
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int size = capacity;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ip[0] = 64;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ip[1] = 32;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ip[2] = size >> 11;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function : int NCR5380_pread (struct Scsi_Host *instance,
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	unsigned char *dst, int len)
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : Fast 5380 pseudo-dma read function, reads len bytes to
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	dst
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Inputs : dst = destination, len = length in bytes
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns : 0 on success, non zero on a failure such as a watchdog
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	timeout.
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int dtc_maxi = 0;
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int dtc_wmaxi = 0;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *d = dst;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;			/* For counting time spent in the poll-loop */
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_local_declare();
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_setup(instance);
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = 0;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (instance->irq == SCSI_IRQ_NONE)
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_write(DTC_BLK_CNT, len >> 7);	/* Block count */
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rtrc(1);
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (len > 0) {
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rtrc(2);
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			++i;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rtrc(3);
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy_fromio(d, base + DTC_DATA_BUF, 128);
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d += 128;
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len -= 128;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rtrc(7);
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*** with int's on, it sometimes hangs after here.
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Looks like something makes HBNR go away. */
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rtrc(4);
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		++i;
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_write(MODE_REG, 0);	/* Clear the operating mode */
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rtrc(0);
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (i > dtc_maxi)
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dtc_maxi = i;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function : int NCR5380_pwrite (struct Scsi_Host *instance,
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	unsigned char *src, int len)
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	src
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Inputs : src = source, len = length in bytes
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns : 0 on success, non zero on a failure such as a watchdog
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	timeout.
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_local_declare();
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_setup(instance);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* set direction (write) */
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (instance->irq == SCSI_IRQ_NONE)
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NCR5380_write(DTC_CONTROL_REG, 0);
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_write(DTC_BLK_CNT, len >> 7);	/* Block count */
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; len > 0; ++i) {
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rtrc(5);
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Poll until the host buffer can accept data. */
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			++i;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rtrc(3);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy_toio(base + DTC_DATA_BUF, src, 128);
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		src += 128;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len -= 128;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rtrc(4);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		++i;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rtrc(6);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Wait until the last byte has been sent to the disk */
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		++i;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rtrc(7);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check for parity error here. fixme. */
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_write(MODE_REG, 0);	/* Clear the operating mode */
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rtrc(0);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (i > dtc_wmaxi)
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dtc_wmaxi = i;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "NCR5380.c"
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int dtc_release(struct Scsi_Host *shost)
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_local_declare();
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_setup(shost);
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (shost->irq)
4621e641664301744f0d381de43ae1e12343e60b479Jeff Garzik		free_irq(shost->irq, shost);
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NCR5380_exit(shost);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (shost->io_port && shost->n_io_port)
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		release_region(shost->io_port, shost->n_io_port);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scsi_unregister(shost);
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(base);
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
471d0be4a7d29ad0bd3ce2209dd9e46d410b632db59Christoph Hellwigstatic struct scsi_host_template driver_template = {
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name				= "DTC 3180/3280 ",
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.detect				= dtc_detect,
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.release			= dtc_release,
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.queuecommand			= dtc_queue_command,
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.eh_abort_handler		= dtc_abort,
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.eh_bus_reset_handler		= dtc_bus_reset,
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.bios_param     		= dtc_biosparam,
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.can_queue      		= CAN_QUEUE,
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.this_id        		= 7,
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.sg_tablesize   		= SG_ALL,
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.cmd_per_lun    		= CMD_PER_LUN,
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.use_clustering 		= DISABLE_CLUSTERING,
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "scsi_module.c"
486