home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC-Online 1996 May
/
PCOnline_05_1996.bin
/
linux
/
source
/
kernel-s
/
v1.1
/
scsi
/
ncr53c40.9
/
ncr53c40
Wrap
Text File
|
1995-10-10
|
22KB
|
806 lines
diff -u linux/arch/i386/config.in:1.1.1.2 linux/arch/i386/config.in:1.2.2.1
--- linux/arch/i386/config.in:1.1.1.2 Fri Sep 9 16:49:48 1994
+++ linux/arch/i386/config.in Fri Sep 9 16:49:48 1994
@@ -60,6 +60,7 @@
bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 n
bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR n
bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n
+bool 'NCR53c406 SCSI support' CONFIG_SCSI_NCR53C406 y
#bool 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG n
fi
diff -u linux/drivers/scsi/Makefile:1.1.1.1 linux/drivers/scsi/Makefile:1.2
--- linux/drivers/scsi/Makefile:1.1.1.1 Fri Sep 9 16:49:52 1994
+++ linux/drivers/scsi/Makefile Fri Sep 9 16:49:52 1994
@@ -122,6 +122,10 @@
SCSI_SRCS := $(SCSI_SRCS) ultrastor.c
endif
+ifdef CONFIG_SCSI_NCR53C406
+SCSI_OBJS := $(SCSI_OBJS) NCR53c406.o
+SCSI_SCRS := $(SCSI_SRCS) NCR53c406.c
+endif
scsi.a: $(SCSI_OBJS)
diff -u /dev/null linux/drivers/scsi/NCR53c406.c:1.1.2.5
--- /dev/null Fri Sep 9 16:49:52 1994
+++ linux/drivers/scsi/NCR53c406.c Fri Sep 9 16:49:52 1994
@@ -0,0 +1,629 @@
+/*
+ * NCR53c406.c
+ * Low-level SCSI driver for NCR53c406a (Acculogic ISApport)
+ * Copyright (C) 1994 Normunds Saumanis (saumanis@cps.msu.edu)
+ *
+ * PIO mode support based on code from Qlogic FAS408 driver by
+ * Tom Zerucha and Michael A. Griffith.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#ifndef _NCR53C406_C
+#define _NCR53C406_C
+
+#define NCR53C406_DEBUG 0
+#define VERBOSE_NCR53C406_DEBUG 0
+
+#define USE_BIOS 1
+/* #define BIOS_ADDR 0xD8000 */ /* define this if autoprobe fails */
+/* #define PORT_BASE 0x330 */ /* define this if autoprobe fails */
+#define IRQ_LEV 11
+#define DMA_CHAN 5
+
+/* Set either USE_DMA or USE_PIO, not both or neither! */
+#define USE_DMA 0
+#define USE_PIO 1
+
+/* Default configuration */
+#define C1_IMG 0x07 /* ID=7 */
+#define C2_IMG 0x40 /* FE */
+#if USE_DMA
+#define C3_IMG 0x01 /* TE */
+#else
+#define C3_IMG 0x00
+#endif
+#define C4_IMG 0x04 /* ANE */
+#define C5_IMG 0xb6 /* AA PI SIE POL */
+
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include "/linux/tools/version.h"
+#include "../block/blk.h"
+#include "scsi.h"
+#include "hosts.h"
+#include "sd.h"
+
+#include "NCR53c406.h"
+
+#define REG0 (outb(C4_IMG, CONFIG4))
+#define REG1 (outb(C5_IMG, CONFIG5))
+
+#if NCR53C406_DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+#if VERBOSE_NCR53C406_DEBUG
+#define VDEB(x) x
+#else
+#define VDEB(x)
+#endif
+
+enum {
+ data_out,
+ data_in,
+ command,
+ status,
+ message_out,
+ message_in
+};
+
+#if USE_BIOS
+static void *bios_base = (void *)0;
+#endif
+static int port_base = 0;
+static int irq_level = 0;
+#if USE_DMA
+static int dma_chan = 0;
+#endif
+static Scsi_Cmnd *current_SC = NULL;
+static int in_command = 0;
+static int in_reset = 0;
+
+/* possible BIOS locations */
+#if USE_BIOS
+static void *addresses[] = {
+ (void *)0xd8000,
+ (void *)0xc8000
+};
+#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
+#endif USE_BIOS
+
+/* possible i/o port addresses */
+static unsigned short ports[] = { 0x230, 0x330 };
+#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
+
+/* possible interrupt channels */
+static unsigned short ints[] = { 10, 11, 12, 15 };
+
+/* signatures for NCR 53c406a based controllers */
+#if USE_BIOS
+struct signature {
+ char *signature;
+ int sig_offset;
+ int sig_length;
+} signatures[] = {
+ /* 1 2 3 4 5 6 */
+ /* 123456789012345678901234567890123456789012345678901234567890 */
+ { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82 },
+};
+#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
+#endif USE_BIOS
+
+#if (USE_DMA)
+static __inline__ int
+NCR53c406_dma_setup (unsigned char *ptr,
+ unsigned int count,
+ unsigned char mode) {
+ unsigned limit;
+ DEB(printk("dma: before count=%d ", count));
+ if (dma_chan <=3) {
+ if (count > 65536)
+ count = 65536;
+ limit = 65536 - (((unsigned) ptr) & 0xFFFF);
+ } else {
+ if (count > 65536 * 2)
+ count = 65536 * 2;
+ limit = 65536* 2 - (((unsigned) ptr) & 0x1FFFF);
+ }
+
+ if (count > limit) count = limit;
+
+ DEB(printk("after count=%d\n", count));
+ if ((count & 1) || (((unsigned) ptr) & 1))
+ panic ("NCR53c406 : attempted unaligned DMA transfer\n");
+
+ cli();
+ disable_dma(dma_chan);
+ clear_dma_ff(dma_chan);
+ set_dma_addr(dma_chan, (long) ptr);
+ set_dma_count(dma_chan, count);
+ set_dma_mode(dma_chan, mode);
+ enable_dma(dma_chan);
+ sti();
+
+ return count;
+}
+
+static __inline__ int
+NCR53c406_dma_write(unsigned char *src, unsigned int count) {
+ return NCR53c406_dma_setup (src, count, DMA_MODE_WRITE);
+}
+
+static __inline__ int
+NCR53c406_dma_read(unsigned char *src, unsigned int count) {
+ return NCR53c406_dma_setup (src, count, DMA_MODE_READ);
+}
+
+static __inline__ int
+NCR53c406_dma_residual (void) {
+ register int tmp;
+
+ cli();
+ clear_dma_ff(dma_chan);
+ tmp = get_dma_residue(dma_chan);
+ sti();
+
+ return tmp;
+}
+#endif /* USE_DMA */
+
+#if USE_PIO
+static __inline__ int NCR53c406_pio(unsigned char *request,
+ unsigned int reqlen,
+ unsigned char mode )
+{
+ int i,j;
+ int ilen; /* incremental transfer length */
+
+ j = 0;
+ REG1;
+ if (mode == DMA_MODE_READ) { /* in */
+ while (reqlen) {
+ i = inb(PIO_STATUS);
+ DEB(printk("pio_status=%x\n", i));
+ j |= i & 0x40;
+ switch( i & 0x1e ) {
+ default:
+ case 0x10:ilen=0;break;
+ case 0x0:ilen=1;break;
+ case 0x8:ilen=42;break;
+ case 0xc:ilen=84;break;
+ case 0xe:ilen=128;break;
+ }
+ if( !ilen ) {
+ if( j )
+ break; /* core int && fifo empty */
+ else
+ continue;
+ }
+ if( ilen > reqlen )
+ ilen = reqlen;
+ cli();
+ if( ilen > 3 ) {
+ insl(PIO_FIFO,request,ilen>>2);
+ request += ilen & 0xfc;
+ reqlen -= ilen & 0xfc;
+ }
+ else while(ilen--) {
+ *request++ = inb(PIO_FIFO);
+ reqlen--;
+ }
+ sti();
+ }
+ }
+ else { /* out */
+ while (!j && reqlen) {
+ i = inb(PIO_STATUS);
+ DEB(printk("pio_status=%x\n", i));
+ j |= i & 0x40;
+ switch( i & 0x1e ) {
+ case 0x10:ilen=128;break;
+ case 0x0:ilen=84;break;
+ case 0x8:ilen=42;break;
+ case 0xc:ilen=1;break;
+ default:
+ case 0xe:ilen=0;break;
+ }
+ if( !ilen )
+ continue;
+ if( ilen > reqlen )
+ ilen = reqlen;
+ cli();
+ if( ilen > 3 ) {
+ outsl(PIO_FIFO,request,ilen>>2);
+ request += ilen & 0xfc;
+ reqlen -= ilen & 0xfc;
+ }
+ else while(ilen--) {
+ outb(*request++, PIO_FIFO);
+ reqlen--;
+ }
+ sti();
+ }
+ }
+
+ /* maybe return reqlen */
+ return 0;
+}
+
+static __inline__ int NCR53c406_pio_read(unsigned char *request,
+ unsigned int reqlen)
+{
+ return NCR53c406_pio (request, reqlen, DMA_MODE_READ);
+}
+
+static __inline__ int NCR53c406_pio_write(unsigned char *request,
+ unsigned int reqlen)
+{
+ return NCR53c406_pio (request, reqlen, DMA_MODE_WRITE);
+}
+#endif USE_PIO
+
+int
+NCR53c406_detect(Scsi_Host_Template * tpnt){
+#ifndef PORT_BASE
+ int i, j, k;
+#endif
+
+#if USE_BIOS
+ int ii, jj;
+ bios_base = 0;
+ /* look for a valid signature */
+ for( ii=0; ii < ADDRESS_COUNT && !bios_base; ii++)
+ for( jj=0; (jj < SIGNATURE_COUNT) && !bios_base; jj++)
+ if(!memcmp((void *) addresses[ii]+signatures[jj].sig_offset,
+ (void *) signatures[jj].signature,
+ (int) signatures[jj].sig_length))
+ bios_base=addresses[ii];
+
+ if(!bios_base){
+ printk("NCR53c406: BIOS signature not found\n");
+ return 0;
+ }
+
+ DEB(printk("NCR53c406 BIOS found at %X\n", (unsigned int) bios_base);)
+#endif /* USE_BIOS */
+
+#ifdef PORT_BASE
+ port_base = PORT_BASE;
+ if (check_region(port_base, 0x10)) /* ports already snatched */
+ port_base = 0;
+#else /* autodetect */
+ port_base = 0;
+ for(i=0; i<PORT_COUNT && !port_base; i++){
+ if(check_region(ports[i], 0x10)){
+ DEB(printk("NCR53c406: port %x in use\n", ports[i]));
+ }
+ else {
+ VDEB(printk("NCR53c406: port %x available\n", ports[i]));
+ outb(C5_IMG, ports[i] + 0x0d); /* reg set 1 */
+ k=0;
+ for (j=0; j< 6; j++) {
+ if((inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7) {
+ VDEB(printk("NCR53c406: Sig register valid\n"));
+ k++;
+ }
+ }
+ if (k>3){
+ VDEB(printk("port_base=%x\n", port_base));
+ port_base = ports[i];
+ }
+ }
+ }
+#endif PORT_BASE
+
+ if(!port_base){ /* no ports found */
+ printk("NCR53c406: no available ports found\n");
+ return 0;
+ }
+
+ DEB(printk("NCR 53c406a detected\n"));
+
+ REG1;
+#if (USE_DMA)
+ outb(0x00, PIO_STATUS);
+#else /* USE_PIO */
+ outb(0x01, PIO_STATUS);
+#endif
+ outb(0x00, PIO_FLAG);
+
+ outb(C4_IMG, CONFIG4); /* REG0; */
+ outb(C3_IMG, CONFIG3);
+ outb(C2_IMG, CONFIG2);
+ outb(C1_IMG, CONFIG1);
+
+ outb(0x05, CLKCONV); /* clock conversion factor */
+ outb(0x9C, SRTIMOUT); /* Selection timeout */
+ outb(0x05, SYNCPRD); /* */
+ outb(0x00, SYNCOFF); /* asynchronous mode */
+
+ DEB(printk("NCR53c406: using port_base %x\n", port_base));
+ snarf_region(port_base, 0x10);
+
+ irq_level=IRQ_LEV;
+
+ if(request_irq(irq_level, NCR53c406_intr, SA_INTERRUPT, "NCR53c406a")){
+ printk("NCR53c406: unable to allocate IRQ %d\n", irq_level);
+ return 0;
+ }
+ DEB(printk("Allocated IRQ %d\n", irq_level));
+
+#if (USE_DMA)
+ dma_chan = DMA_CHAN;
+ if(request_dma(dma_chan, "NCR53c406a") != 0){
+ printk("NCR53c406: unable to allocate DMA channel %d\n", dma_chan);
+ return 0;
+ }
+
+ DEB(printk("Allocated DMA channel %d\n", dma_chan));
+#endif /* USE_DMA */
+
+ tpnt->present = 1;
+ return 1;
+}
+
+const char*
+NCR53c406_info(){
+ printk("NCR53c406_info called\n");
+ return ("This is NCR53c406 info function!\n");
+}
+
+int
+NCR53c406_command(Scsi_Cmnd *SCpnt){
+ printk("NCR53c406_command called\n");
+ return 0;
+}
+
+int
+NCR53c406_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)){
+ int i;
+ unsigned int cmd_size = COMMAND_SIZE(SCpnt->cmnd[0]);
+
+ DEB(printk("NCR53c406_queue called\n"));
+ DEB(printk("cmd=%02x cmd size=%02x target=%02x lun=%02x bufflen=%d\n",
+ SCpnt->cmnd[0],
+ cmd_size,
+ SCpnt->target,
+ SCpnt->lun,
+ SCpnt->request_bufflen));
+ VDEB(for(i=0; i<cmd_size; i++)
+ printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i]));
+ VDEB(printk("\n"));
+ in_command = 1;
+
+ current_SC = SCpnt;
+ current_SC->scsi_done = done;
+ current_SC->SCp.phase = command;
+ current_SC->SCp.Status = 0;
+ current_SC->SCp.Message = 0;
+
+ cli();
+ REG0;
+ outb(SCpnt->target, DEST_ID); /* set destination */
+ outb(FLUSH_FIFO, CMD_REG); /* reset the fifos */
+
+ for(i=0; i<cmd_size; i++){
+ outb(SCpnt->cmnd[i], SCSI_FIFO);
+ }
+ outb(SELECT_NO_ATN, CMD_REG);
+ sti();
+
+ return 0;
+}
+
+int
+NCR53c406_abort(Scsi_Cmnd *SCpnt){
+ DEB(printk("NCR53c406_abort called\n"));
+ return SCSI_ABORT_SNOOZE; /* Don't know how to abort */
+}
+
+int
+NCR53c406_reset(Scsi_Cmnd *SCpnt){
+ DEB(printk("NCR53c406_reset called\n"));
+ cli();
+ in_reset = 1;
+ outb(C4_IMG, CONFIG4); /* Select reg set 0 */
+ outb(FLUSH_FIFO, CMD_REG);
+ outb(SCSI_RESET, CMD_REG);
+ outb(SCSI_NOP | DMA_OP, CMD_REG); /* required after reset */
+ sti();
+ return SCSI_RESET_PENDING; /* should get an interrupt */
+}
+
+int
+NCR53c406_biosparm(Scsi_Disk *disk, int dev, int* info_array){
+ int size;
+
+ DEB(printk("NCR53c406_biosparm called\n"));
+
+ size = disk->capacity;
+ info_array[0] = 64; /* heads */
+ info_array[1] = 32; /* sectors */
+ info_array[2] = size>>11; /* cylinders */
+ if (info_array[2] > 1024) { /* big disk */
+ info_array[0] = 255;
+ info_array[1] = 63;
+ info_array[2] = size / (255*63);
+ }
+ return 0;
+}
+
+
+static void
+NCR53c406_intr(int unused){
+ unsigned char status, int_reg, seq_reg, fifo_size;
+#if USE_PIO
+ unsigned char pio_status;
+ struct scatterlist *sglist;
+ unsigned int sgcount;
+#endif
+
+ VDEB(int i;)
+ DEB(printk("NCR53c406_intr called\n"));
+
+ cli();
+#if USE_PIO
+ REG1;
+ pio_status = inb(PIO_STATUS);
+#endif
+ REG0;
+ status = inb(STAT_REG);
+ seq_reg = inb(SEQ_REG);
+ int_reg = inb(INT_REG);
+ fifo_size = inb(FIFO_FLAGS) & 0x1f;
+ sti();
+
+#if NCR53C406_DEBUG
+ printk("status=%02x seq_reg=%02x int_reg=%02x fifo_size=%02x",
+ status, seq_reg, int_reg, fifo_size);
+#if (USE_DMA)
+ printk("\n");
+#else
+ printk(" pio=%02x\n", pio_status);
+#endif /* USE_DMA */
+#endif /* NCR53C406_DEBUG */
+
+ if((in_command || in_reset) && (int_reg & 0x80)){ /* SCSI reset intr */
+ DEB(printk("Reset intr received\n"));
+ in_command = 0;
+ in_reset = 0;
+ current_SC->result = DID_RESET << 16;
+ current_SC->scsi_done(current_SC);
+ }
+
+ if(int_reg & 0x20){ /* Disconnect */
+ if(in_command || in_reset){ /* target disconnected while in command*/
+ DEB(printk("Disconnect intr received\n"));
+ if(current_SC->SCp.phase != message_in){
+ in_command = 0;
+ in_reset = 0;
+ current_SC->result = DID_NO_CONNECT << 16;
+ }
+ else{
+ current_SC->result = (current_SC->SCp.Status & 0xff)
+ | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16);
+ in_command = 0;
+ }
+ if(current_SC->scsi_done)
+ current_SC->scsi_done( current_SC );
+ }
+ else /* Target disconnected on idle bus? */
+ return;
+ }
+
+ switch(status & 0x07){ /* scsi phase */
+ case 0x00: /* DATA-OUT */
+ if(int_reg & 0x10){ /* Target requesting info transfer */
+ DEB(printk("Data-Out phase\n"));
+ outb(FLUSH_FIFO, CMD_REG);
+ LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */
+#if (USE_DMA)
+ NCR53c406_dma_write(current_SC->request_buffer,
+ current_SC->request_bufflen);
+#endif USE_DMA
+ outb(TRANSFER_INFO | DMA_OP, CMD_REG);
+#if USE_PIO
+ if (!current_SC->use_sg)
+ NCR53c406_pio_write(current_SC->request_buffer,
+ current_SC->request_bufflen);
+ else { /* use s/g */
+ sgcount = current_SC->use_sg;
+ sglist = current_SC->request_buffer;
+ while( sgcount-- ) {
+ NCR53c406_pio_write(sglist->address, sglist->length);
+ sglist++;
+ }
+ }
+ REG0;
+#endif USE_PIO
+ }
+ break;
+
+ case 0x01: /* DATA-IN */
+ DEB(printk("Data-In phase\n"));
+ outb(FLUSH_FIFO, CMD_REG);
+ LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */
+#if (USE_DMA)
+ NCR53c406_dma_read(current_SC->request_buffer,
+ current_SC->request_bufflen);
+#endif USE_DMA
+ outb(TRANSFER_INFO | DMA_OP, CMD_REG);
+#if USE_PIO
+ if (!current_SC->use_sg)
+ NCR53c406_pio_read(current_SC->request_buffer,
+ current_SC->request_bufflen);
+ else { /* use s/g */
+ sgcount = current_SC->use_sg;
+ sglist = current_SC->request_buffer;
+ while( sgcount-- ) {
+ NCR53c406_pio_read(sglist->address, sglist->length);
+ sglist++;
+ }
+ }
+ REG0;
+#endif USE_PIO
+ break;
+
+ case 0x02: /* COMMAND */
+ DEB(printk("Command phase\n"));
+ break;
+
+ case 0x03: /* STATUS */
+ current_SC->SCp.phase = status;
+ DEB(printk("Status phase\n"));
+#if VERBOSE_NCR53C406_DEBUG
+ printk("request_buffer=");
+ for(i=0; i<current_SC->request_bufflen && i<200; i++)
+ printk("%02x ", *((unsigned char*)current_SC->request_buffer + i));
+ printk("\n");
+ printk("dma residue = %d\n", NCR53c406_dma_residual());
+#endif
+
+ outb(FLUSH_FIFO, CMD_REG);
+ outb(INIT_CMD_COMPLETE, CMD_REG);
+ break;
+
+ case 0x04: /* Reserved */
+ case 0x05: /* Reserved */
+ DEB(printk("Reserved phase\n"));
+ break;
+
+ case 0x06: /* MESSAGE-OUT */
+ DEB(printk("Message-Out phase\n"));
+ outb(SET_ATN, CMD_REG); /* Reject the message */
+ outb(MSG_ACCEPT, CMD_REG);
+ break;
+
+ case 0x07: /* MESSAGE-IN */
+ DEB(printk("Message-In phase\n"));
+ current_SC->SCp.phase = message_in;
+
+ current_SC->SCp.Status = inb(SCSI_FIFO);
+ current_SC->SCp.Message = inb(SCSI_FIFO);
+
+ DEB(printk("SCSI FIFO size=%d\n", inb(FIFO_FLAGS) & 0x1f));
+ DEB(printk("Status = %02x Message = %02x\n",
+ current_SC->SCp.Status, current_SC->SCp.Message);)
+
+ outb(MSG_ACCEPT, CMD_REG);
+ break;
+ }
+
+}
+
+#endif _NCR53C406_C
diff -u /dev/null linux/drivers/scsi/NCR53c406.h:1.1.2.3
--- /dev/null Fri Sep 9 16:49:52 1994
+++ linux/drivers/scsi/NCR53c406.h Fri Sep 9 16:49:52 1994
@@ -0,0 +1,116 @@
+#ifndef _NCR53C406_H
+#define _NCR53C406_H
+
+/*
+ * NCR53c406.h
+ *
+ * Copyright (C) 1994 Normunds Saumanis (saumanis@cps.msu.edu)
+ *
+ */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* NOTE: scatter-gather support only works in PIO mode.
+ Use SG_NONE if DMA mode is enabled!
+*/
+#define NCR53c406 { NULL, "NCR53c406a", NCR53c406_detect, NULL, \
+ NCR53c406_info, NCR53c406_command, \
+ NCR53c406_queue, NCR53c406_abort, \
+ NCR53c406_reset, 0, NCR53c406_biosparm, \
+ 1, 7, SG_ALL /*SG_NONE*/, 1, 0, 1, DISABLE_CLUSTERING }
+
+
+/* Control Register Set 0 */
+#define TC_LSB (port_base+0x00) /* transfer counter lsb */
+#define TC_MSB (port_base+0x01) /* transfer counter msb */
+#define SCSI_FIFO (port_base+0x02) /* scsi fifo register */
+#define CMD_REG (port_base+0x03) /* command register */
+#define STAT_REG (port_base+0x04) /* status register */
+#define DEST_ID (port_base+0x04) /* selection/reselection bus id */
+#define INT_REG (port_base+0x05) /* interrupt status register */
+#define SRTIMOUT (port_base+0x05) /* select/reselect timeout reg */
+#define SEQ_REG (port_base+0x06) /* sequence step register */
+#define SYNCPRD (port_base+0x06) /* synchronous transfer period */
+#define FIFO_FLAGS (port_base+0x07) /* indicates # of bytes in fifo */
+#define SYNCOFF (port_base+0x07) /* synchronous offset register */
+#define CONFIG1 (port_base+0x08) /* configuration register */
+#define CLKCONV (port_base+0x09) /* clock conversion reg */
+#define TESTREG (port_base+0x0A) /* test mode register */
+#define CONFIG2 (port_base+0x0B) /* Configuration 2 Register */
+#define CONFIG3 (port_base+0x0C) /* Configuration 3 Register */
+#define CONFIG4 (port_base+0x0D) /* Configuration 4 Register */
+#define TC_HIGH (port_base+0x0E) /* Transfer Counter High */
+#define FIFO_BOTTOM (port_base+0x0F) /* Reserve FIFO byte register */
+
+/* Control Register Set 1 */
+#define JUMPER_SENSE (port_base+0x00) /* Jumper sense port reg (r/w) */
+#define SRAM_PTR (port_base+0x01) /* SRAM address pointer reg (r/w) */
+#define SRAM_DATA (port_base+0x02) /* SRAM data register (r/w) */
+#define PIO_FIFO (port_base+0x04) /* PIO FIFO registers (r/w) */
+#define PIO_FIFO1 (port_base+0x05)
+#define PIO_FIFO2 (port_base+0x06)
+#define PIO_FIFO3 (port_base+0x07)
+#define PIO_STATUS (port_base+0x08) /* PIO status (r/w) */
+#define ATA_CMD (port_base+0x09) /* ATA command/status reg (r/w) */
+#define ATA_ERR (port_base+0x0A) /* ATA features/error register (r/w)*/
+#define PIO_FLAG (port_base+0x0B) /* PIO flag interrupt enable (r/w) */
+#define CONFIG5 (port_base+0x0D) /* Configuration 5 register (r/w) */
+#define SIGNATURE (port_base+0x0E) /* Signature Register (r) */
+#define CONFIG6 (port_base+0x0F) /* Configuration 6 register (r) */
+
+/* Commands */
+#define DMA_OP 0x80
+
+#define SCSI_NOP 0x00
+#define FLUSH_FIFO 0x01
+#define CHIP_RESET 0x02
+#define SCSI_RESET 0x03
+#define RESELECT 0x40
+#define SELECT_NO_ATN 0x41
+#define SELECT_ATN 0x42
+#define SELECT_ATN_STOP 0x43
+#define ENABLE_SEL 0x44
+#define DISABLE_SEL 0x45
+#define SELECT_ATN3 0x46
+#define RESELECT3 0x47
+#define TRANSFER_INFO 0x10
+#define INIT_CMD_COMPLETE 0x11
+#define MSG_ACCEPT 0x12
+#define TRANSFER_PAD 0x18
+#define SET_ATN 0x1a
+#define RESET_ATN 0x1b
+#define SEND_MSG 0x20
+#define SEND_STATUS 0x21
+#define SEND_DATA 0x22
+#define DISCONN_SEQ 0x23
+#define TERMINATE_SEQ 0x24
+#define TARG_CMD_COMPLETE 0x25
+#define DISCONN 0x27
+#define RECV_MSG 0x28
+#define RECV_CMD 0x29
+#define RECV_DATA 0x2a
+#define RECV_CMD_SEQ 0x2b
+#define TARGET_ABORT_DMA 0x04
+
+int NCR53c406_detect(Scsi_Host_Template *);
+const char* NCR53c406_info(void);
+
+int NCR53c406_command(Scsi_Cmnd *);
+int NCR53c406_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int NCR53c406_abort(Scsi_Cmnd *);
+int NCR53c406_reset(Scsi_Cmnd *);
+int NCR53c406_biosparm(Disk *, int, int*);
+
+#ifdef _NCR53C406_C
+static void NCR53c406_intr(int);
+#endif
+
+#define LOAD_DMA_COUNT(count) \
+ outb(count & 0xff, TC_LSB); \
+ outb((count >> 8) & 0xff, TC_MSB); \
+ outb((count >> 16) & 0xff, TC_HIGH);
+
+#endif /* _NCR53C406_H */
+
diff -u linux/drivers/scsi/hosts.c:1.1.1.1 linux/drivers/scsi/hosts.c:1.2
--- linux/drivers/scsi/hosts.c:1.1.1.1 Fri Sep 9 16:49:53 1994
+++ linux/drivers/scsi/hosts.c Fri Sep 9 16:49:53 1994
@@ -83,8 +83,12 @@
#include "scsi_debug.h"
#endif
+#ifdef CONFIG_SCSI_NCR53C406
+#include "NCR53c406.h"
+#endif
+
/*
-static const char RCSid[] = "/cvs/linux/drivers/scsi/hosts.c,v 1.1.1.4 1994/09/07 20:00:51 root Exp";
+static const char RCSid[] = "$Header: /junk/cvs/linux/drivers/scsi/hosts.c,v 1.2 1994/09/09 04:47:15 root Exp $";
*/
/*
@@ -155,6 +159,9 @@
#endif
#ifdef CONFIG_SCSI_7000FASST
WD7000,
+#endif
+#ifdef CONFIG_SCSI_NCR53C406
+ NCR53c406,
#endif
#ifdef CONFIG_SCSI_DEBUG
SCSI_DEBUG,