patch-2.3.99-pre1 linux/drivers/scsi/ncr53c8xx.c
Next file: linux/drivers/scsi/scsi.c
Previous file: linux/drivers/scsi/hosts.h
Back to the patch index
Back to the overall index
- Lines: 3289
- Date:
Sun Mar 12 20:10:20 2000
- Orig file:
v2.3.51/linux/drivers/scsi/ncr53c8xx.c
- Orig date:
Tue Jan 11 22:31:41 2000
diff -u --recursive --new-file v2.3.51/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
@@ -73,7 +73,7 @@
*/
/*
-** January 8 2000, version 3.2e
+** March 6 2000, version 3.2g
**
** Supported SCSI-II features:
** Synchronous negotiation
@@ -104,7 +104,7 @@
/*
** Name and version of the driver
*/
-#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2e"
+#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2g"
#define SCSI_NCR_DEBUG_FLAGS (0)
@@ -184,98 +184,14 @@
*/
typedef u32 u_int32;
typedef u64 u_int64;
-
+typedef u_long vm_offset_t;
#include "ncr53c8xx.h"
-/*==========================================================
-**
-** A la VMS/CAM-3 queue management.
-** Implemented from linux list management.
-**
-**==========================================================
-*/
-
-typedef struct xpt_quehead {
- struct xpt_quehead *flink; /* Forward pointer */
- struct xpt_quehead *blink; /* Backward pointer */
-} XPT_QUEHEAD;
-
-#define xpt_que_init(ptr) do { \
- (ptr)->flink = (ptr); (ptr)->blink = (ptr); \
-} while (0)
-
-static inline void __xpt_que_add(struct xpt_quehead * new,
- struct xpt_quehead * blink,
- struct xpt_quehead * flink)
-{
- flink->blink = new;
- new->flink = flink;
- new->blink = blink;
- blink->flink = new;
-}
-
-static inline void __xpt_que_del(struct xpt_quehead * blink,
- struct xpt_quehead * flink)
-{
- flink->blink = blink;
- blink->flink = flink;
-}
-
-static inline int xpt_que_empty(struct xpt_quehead *head)
-{
- return head->flink == head;
-}
-
-static inline void xpt_que_splice(struct xpt_quehead *list,
- struct xpt_quehead *head)
-{
- struct xpt_quehead *first = list->flink;
-
- if (first != list) {
- struct xpt_quehead *last = list->blink;
- struct xpt_quehead *at = head->flink;
-
- first->blink = head;
- head->flink = first;
-
- last->flink = at;
- at->blink = last;
- }
-}
-
-#define xpt_que_entry(ptr, type, member) \
- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
-
-
-#define xpt_insque(new, pos) __xpt_que_add(new, pos, (pos)->flink)
-
-#define xpt_remque(el) __xpt_que_del((el)->blink, (el)->flink)
-
-#define xpt_insque_head(new, head) __xpt_que_add(new, head, (head)->flink)
-
-static inline struct xpt_quehead *xpt_remque_head(struct xpt_quehead *head)
-{
- struct xpt_quehead *elem = head->flink;
-
- if (elem != head)
- __xpt_que_del(head, elem->flink);
- else
- elem = 0;
- return elem;
-}
-
-#define xpt_insque_tail(new, head) __xpt_que_add(new, (head)->blink, head)
+#define NAME53C "ncr53c"
+#define NAME53C8XX "ncr53c8xx"
+#define DRIVER_SMP_LOCK ncr53c8xx_lock
-static inline struct xpt_quehead *xpt_remque_tail(struct xpt_quehead *head)
-{
- struct xpt_quehead *elem = head->blink;
-
- if (elem != head)
- __xpt_que_del(elem->blink, head);
- else
- elem = 0;
- return elem;
-}
+#include "sym53c8xx_comm.h"
/*==========================================================
**
@@ -315,33 +231,6 @@
/*==========================================================
**
-** On x86 architecture, write buffers management does
-** not reorder writes to memory. So, using compiler
-** optimization barriers is enough to guarantee some
-** ordering when the CPU is writing data accessed by
-** the NCR.
-** On Alpha architecture, explicit memory barriers have
-** to be used.
-** Other architectures are defaulted to mb() macro if
-** defined, otherwise use compiler barrier.
-**
-**==========================================================
-*/
-
-#if defined(__i386__)
-#define MEMORY_BARRIER() barrier()
-#elif defined(__alpha__)
-#define MEMORY_BARRIER() mb()
-#else
-# ifdef mb
-# define MEMORY_BARRIER() mb()
-# else
-# define MEMORY_BARRIER() barrier()
-# endif
-#endif
-
-/*==========================================================
-**
** Configuration and Debugging
**
**==========================================================
@@ -464,379 +353,11 @@
#endif
/*
-** Io mapped or memory mapped.
-*/
-
-#if defined(SCSI_NCR_IOMAPPED)
-#define NCR_IOMAPPED
-#endif
-
-/*
** other
*/
#define NCR_SNOOP_TIMEOUT (1000000)
-/*==========================================================
-**
-** Defines for Linux.
-**
-** Linux and Bsd kernel functions are quite different.
-** These defines allow a minimum change of the original
-** code.
-**
-**==========================================================
-*/
-
- /*
- ** Obvious definitions
- */
-
-#define u_char unsigned char
-#define u_short unsigned short
-#define u_int unsigned int
-#define u_long unsigned long
-
-typedef u_long vm_offset_t;
-typedef int vm_size_t;
-
-#ifndef bcopy
-#define bcopy(s, d, n) memcpy((d), (s), (n))
-#endif
-#ifndef bzero
-#define bzero(d, n) memset((d), 0, (n))
-#endif
-
-#ifndef offsetof
-#define offsetof(t, m) ((size_t) (&((t *)0)->m))
-#endif
-
-/*
-** Simple Wrapper to kernel PCI bus interface.
-**
-** This wrapper allows to get rid of old kernel PCI interface
-** and still allows to preserve linux-2.0 compatibilty.
-** In fact, it is mostly an incomplete emulation of the new
-** PCI code for pre-2.2 kernels. When kernel-2.0 support
-** will be dropped, we will just have to remove most of this
-** code.
-*/
-
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,2,0)
-
-typedef struct pci_dev *pcidev_t;
-#define PCIDEV_NULL (0)
-#define PciBusNumber(d) (d)->bus->number
-#define PciDeviceFn(d) (d)->devfn
-#define PciVendorId(d) (d)->vendor
-#define PciDeviceId(d) (d)->device
-#define PciIrqLine(d) (d)->irq
-
-#if LINUX_VERSION_CODE > LinuxVersionCode(2,3,12)
-
-static int __init
-pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
-{
- *base = pdev->resource[index].start;
- if ((pdev->resource[index].flags & 0x7) == 0x4)
- ++index;
- return ++index;
-}
-#else
-static int __init
-pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
-{
- *base = pdev->base_address[index++];
- if ((*base & 0x7) == 0x4) {
-#if BITS_PER_LONG > 32
- *base |= (((u_long)pdev->base_address[index]) << 32);
-#endif
- ++index;
- }
- return index;
-}
-#endif
-
-#else /* Incomplete emulation of current PCI code for pre-2.2 kernels */
-
-typedef unsigned int pcidev_t;
-#define PCIDEV_NULL (~0u)
-#define PciBusNumber(d) ((d)>>8)
-#define PciDeviceFn(n) ((d)&0xff)
-#define __PciDev(busn, devfn) (((busn)<<8)+(devfn))
-
-#define pci_present pcibios_present
-
-#define pci_read_config_byte(d, w, v) \
- pcibios_read_config_byte(PciBusNumber(d), PciDeviceFn(d), w, v)
-#define pci_read_config_word(d, w, v) \
- pcibios_read_config_word(PciBusNumber(d), PciDeviceFn(d), w, v)
-#define pci_read_config_dword(d, w, v) \
- pcibios_read_config_dword(PciBusNumber(d), PciDeviceFn(d), w, v)
-
-
-#define pci_write_config_byte(d, w, v) \
- pcibios_write_config_byte(PciBusNumber(d), PciDeviceFn(d), w, v)
-#define pci_write_config_word(d, w, v) \
- pcibios_write_config_word(PciBusNumber(d), PciDeviceFn(d), w, v)
-#define pci_write_config_dword(d, w, v) \
- pcibios_write_config_dword(PciBusNumber(d), PciDeviceFn(d), w, v)
-
-static pcidev_t __init
-pci_find_device(unsigned int vendor, unsigned int device, pcidev_t prev)
-{
- static unsigned short pci_index;
- int retv;
- unsigned char bus_number, device_fn;
-
- if (prev == PCIDEV_NULL)
- pci_index = 0;
- else
- ++pci_index;
- retv = pcibios_find_device (vendor, device, pci_index,
- &bus_number, &device_fn);
- return retv ? PCIDEV_NULL : __PciDev(bus_number, device_fn);
-}
-
-static u_short __init PciVendorId(pcidev_t dev)
-{
- u_short vendor_id;
- pcibios_read_config_word(dev, PCI_VENDOR_ID, &vendor_id);
- return vendor_id;
-}
-
-static u_short __init PciDeviceId(pcidev_t dev)
-{
- u_short device_id;
- pci_read_config_word(dev, PCI_DEVICE_ID, &device_id);
- return device_id;
-}
-
-static u_int __init PciIrqLine(pcidev_t dev)
-{
- u_short irq;
- pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
- return irq;
-}
-
-static int __init
-pci_get_base_address(pcidev_t dev, int offset, u_long *base)
-{
- u_int32 tmp;
-
- pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + offset, &tmp);
- *base = tmp;
- offset += sizeof(u_int32);
- if ((tmp & 0x7) == 0x4) {
-#if BITS_PER_LONG > 32
- pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + offset, &tmp);
- *base |= (((u_long)tmp) << 32);
-#endif
- offset += sizeof(u_int32);
- }
- return offset;
-}
-
-#endif /* LINUX_VERSION_CODE >= LinuxVersionCode(2,2,0) */
-
-/*
-** SMP threading.
-**
-** Assuming that SMP systems are generally high end systems and may
-** use several SCSI adapters, we are using one lock per controller
-** instead of some global one. For the moment (linux-2.1.95), driver's
-** entry points are called with the 'io_request_lock' lock held, so:
-** - We are uselessly loosing a couple of micro-seconds to lock the
-** controller data structure.
-** - But the driver is not broken by design for SMP and so can be
-** more resistant to bugs or bad changes in the IO sub-system code.
-** - A small advantage could be that the interrupt code is grained as
-** wished (e.g.: threaded by controller).
-*/
-
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)
-
-#if 0 /* not yet needed */
-static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
-#define NCR_LOCK_DRIVER(flags) spin_lock_irqsave(&driver_lock, flags)
-#define NCR_UNLOCK_DRIVER(flags) spin_unlock_irqrestore(&driver_lock, flags)
-#endif
-
-#define NCR_INIT_LOCK_NCB(np) spin_lock_init(&np->smp_lock);
-#define NCR_LOCK_NCB(np, flags) spin_lock_irqsave(&np->smp_lock, flags)
-#define NCR_UNLOCK_NCB(np, flags) spin_unlock_irqrestore(&np->smp_lock, flags)
-
-#define NCR_LOCK_SCSI_DONE(np, flags) \
- spin_lock_irqsave(&io_request_lock, flags)
-#define NCR_UNLOCK_SCSI_DONE(np, flags) \
- spin_unlock_irqrestore(&io_request_lock, flags)
-
-#else
-
-#if 0 /* not yet needed */
-#define NCR_LOCK_DRIVER(flags) do {;} while (0)
-#define NCR_UNLOCK_DRIVER(flags) do {;} while (0)
-#endif
-
-#define NCR_INIT_LOCK_NCB(np) do { } while (0)
-#define NCR_LOCK_NCB(np, flags) do { save_flags(flags); cli(); } while (0)
-#define NCR_UNLOCK_NCB(np, flags) do { restore_flags(flags); } while (0)
-
-#define NCR_LOCK_SCSI_DONE(np, flags) do {;} while (0)
-#define NCR_UNLOCK_SCSI_DONE(np, flags) do {;} while (0)
-
-#endif
-
-/*
-** Address translation
-**
-** The driver has to provide physical memory addresses to
-** the script processor. Because some architectures use
-** different physical addresses from the PCI BUS, we must
-** use virt_to_bus instead of virt_to_phys.
-*/
-
-#define vtophys(p) virt_to_bus(p)
-
-/*
-** Memory mapped IO
-**
-** Since linux-2.1, we must use ioremap() to map the io memory space.
-** iounmap() to unmap it. That allows portability.
-** Linux 1.3.X and 2.0.X allow to remap physical pages addresses greater
-** than the highest physical memory address to kernel virtual pages with
-** vremap() / vfree(). That was not portable but worked with i386
-** architecture.
-*/
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0)
-#define ioremap vremap
-#define iounmap vfree
-#endif
-
-#if defined (__sparc__)
-#include <asm/irq.h>
-#elif defined (__alpha__)
-#define bus_dvma_to_mem(p) ((p) & 0xfffffffful)
-#else
-#define bus_dvma_to_mem(p) (p)
-#endif
-
-#if defined(__i386__) || !defined(NCR_IOMAPPED)
-static vm_offset_t __init remap_pci_mem(u_long base, u_long size)
-{
- u_long page_base = ((u_long) base) & PAGE_MASK;
- u_long page_offs = ((u_long) base) - page_base;
- u_long page_remapped = (u_long) ioremap(page_base, page_offs+size);
-
- return (vm_offset_t) (page_remapped? (page_remapped + page_offs) : 0UL);
-}
-
-static void __init unmap_pci_mem(vm_offset_t vaddr, u_long size)
-{
- if (vaddr)
- iounmap((void *) (vaddr & PAGE_MASK));
-}
-#endif /* __i386__ || !NCR_IOMAPPED */
-
-/*
-** Insert a delay in micro-seconds and milli-seconds.
-** -------------------------------------------------
-** Under Linux, udelay() is restricted to delay < 1 milli-second.
-** In fact, it generally works for up to 1 second delay.
-** Since 2.1.105, the mdelay() function is provided for delays
-** in milli-seconds.
-** Under 2.0 kernels, udelay() is an inline function that is very
-** inaccurate on Pentium processors.
-*/
-
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,105)
-#define UDELAY udelay
-#define MDELAY mdelay
-#else
-static void UDELAY(long us) { udelay(us); }
-static void MDELAY(long ms) { while (ms--) UDELAY(1000); }
-#endif
-
-/*
-** Internal data structure allocation.
-**
-** Linux scsi memory poor pool is adjusted for the need of
-** middle-level scsi driver.
-** We allocate our control blocks in the kernel memory pool
-** to avoid scsi pool shortage.
-**
-** kmalloc() only ensures 8 bytes boundary alignment.
-** The NCR need better alignment for cache line bursting.
-** The global header is moved between the NCB and CCBs and needs
-** origin and destination addresses to have same lower four bits.
-**
-** We use 32 boundary alignment for NCB and CCBs and offset multiple
-** of 32 for global header fields. That's too much but at least enough.
-*/
-
-#define ALIGN_SIZE(shift) (1UL << shift)
-#define ALIGN_MASK(shift) (~(ALIGN_SIZE(shift)-1))
-
-#define CACHE_LINE_SHIFT 5
-#define CACHE_LINE_SIZE ALIGN_SIZE(CACHE_LINE_SHIFT)
-#define CACHE_LINE_MASK ALIGN_MASK(CACHE_LINE_SHIFT)
-
-static void *m_alloc(int size, int a_shift)
-{
- u_long addr;
- void *ptr;
- u_long a_size, a_mask;
-
- if (a_shift < 3)
- a_shift = 3;
-
- a_size = ALIGN_SIZE(a_shift);
- a_mask = ALIGN_MASK(a_shift);
-
- ptr = (void *) kmalloc(size + a_size, GFP_ATOMIC);
- if (ptr) {
- addr = (((u_long) ptr) + a_size) & a_mask;
- *((void **) (addr - sizeof(void *))) = ptr;
- ptr = (void *) addr;
- }
-
- return ptr;
-}
-
-#ifdef MODULE
-static void m_free(void *ptr, int size)
-{
- u_long addr;
-
- if (ptr) {
- addr = (u_long) ptr;
- ptr = *((void **) (addr - sizeof(void *)));
-
- kfree(ptr);
- }
-}
-#endif
-
-/*
-** Transfer direction
-**
-** Low-level scsi drivers under Linux do not receive the expected
-** data transfer direction from upper scsi drivers.
-** The driver will only check actual data direction for common
-** scsi opcodes. Other ones may cause problem, since they may
-** depend on device type or be vendor specific.
-** I would prefer to never trust the device for data direction,
-** but that is not possible.
-**
-** The original driver requires the expected direction to be known.
-** The Linux version of the driver has been enhanced in order to
-** be able to transfer data in the direction choosen by the target.
-*/
-
-#define XFER_IN (1)
-#define XFER_OUT (2)
-
/*
** Head of list of NCR boards
**
@@ -848,44 +369,8 @@
static struct Scsi_Host *first_host = NULL;
static Scsi_Host_Template *the_template = NULL;
-
-/*
-** /proc directory entry and proc_info function
-*/
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
-static struct proc_dir_entry proc_scsi_ncr53c8xx = {
- PROC_SCSI_NCR53C8XX, 9, "ncr53c8xx",
- S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-#endif
-#ifdef SCSI_NCR_PROC_INFO_SUPPORT
-static int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
- int length, int hostno, int func);
-#endif
-
-/*
-** Driver setup.
-**
-** This structure is initialized from linux config options.
-** It can be overridden at boot-up by the boot command line.
-*/
-static struct ncr_driver_setup
- driver_setup = SCSI_NCR_DRIVER_SETUP;
-
-#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
-static struct ncr_driver_setup
- driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP;
-# ifdef MODULE
-char *ncr53c8xx = 0; /* command line passed by insmod */
-# if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
-MODULE_PARM(ncr53c8xx, "s");
-# endif
-# endif
-#endif
-
/*
-** Other Linux definitions
+** Other definitions
*/
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) + ((scsi_code) & 0x7f))
@@ -903,307 +388,47 @@
{25,31,37,43, 50,62,75,125, 12,15,18,21, 6,7,9,10};
#endif /* SCSI_NCR_NVRAM_SUPPORT */
-/*
-** Structures used by ncr53c8xx_detect/ncr53c8xx_pci_init to
-** transmit device configuration to the ncr_attach() function.
-*/
-typedef struct {
- int bus;
- u_char device_fn;
- u_long base;
- u_long base_2;
- u_long io_port;
- int irq;
-/* port and reg fields to use INB, OUTB macros */
- u_long port;
- volatile struct ncr_reg *reg;
-} ncr_slot;
-
-typedef struct {
- int type;
-#define SCSI_NCR_SYMBIOS_NVRAM (1)
-#define SCSI_NCR_TEKRAM_NVRAM (2)
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- union {
- Symbios_nvram Symbios;
- Tekram_nvram Tekram;
- } data;
-#endif
-} ncr_nvram;
-
-/*
-** Structure used by ncr53c8xx_detect/ncr53c8xx_pci_init
-** to save data on each detected board for ncr_attach().
-*/
-typedef struct {
- ncr_slot slot;
- ncr_chip chip;
- ncr_nvram *nvram;
- u_char host_id;
- int attach_done;
-} ncr_device;
-
/*==========================================================
**
-** Debugging tags
+** Command control block states.
**
**==========================================================
*/
-#define DEBUG_ALLOC (0x0001)
-#define DEBUG_PHASE (0x0002)
-#define DEBUG_QUEUE (0x0008)
-#define DEBUG_RESULT (0x0010)
-#define DEBUG_SCATTER (0x0020)
-#define DEBUG_SCRIPT (0x0040)
-#define DEBUG_TINY (0x0080)
-#define DEBUG_TIMING (0x0100)
-#define DEBUG_NEGO (0x0200)
-#define DEBUG_TAGS (0x0400)
+#define HS_IDLE (0)
+#define HS_BUSY (1)
+#define HS_NEGOTIATE (2) /* sync/wide data transfer*/
+#define HS_DISCONNECT (3) /* Disconnected by target */
+
+#define HS_DONEMASK (0x80)
+#define HS_COMPLETE (4|HS_DONEMASK)
+#define HS_SEL_TIMEOUT (5|HS_DONEMASK) /* Selection timeout */
+#define HS_RESET (6|HS_DONEMASK) /* SCSI reset */
+#define HS_ABORTED (7|HS_DONEMASK) /* Transfer aborted */
+#define HS_TIMEOUT (8|HS_DONEMASK) /* Software timeout */
+#define HS_FAIL (9|HS_DONEMASK) /* SCSI or PCI bus errors */
+#define HS_UNEXPECTED (10|HS_DONEMASK)/* Unexpected disconnect */
/*
-** Enable/Disable debug messages.
-** Can be changed at runtime too.
+** Invalid host status values used by the SCRIPTS processor
+** when the nexus is not fully identified.
+** Shall never appear in a CCB.
*/
-#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
- #define DEBUG_FLAGS ncr_debug
-#else
- #define DEBUG_FLAGS SCSI_NCR_DEBUG_FLAGS
-#endif
-
-
+#define HS_INVALMASK (0x40)
+#define HS_SELECTING (0|HS_INVALMASK)
+#define HS_IN_RESELECT (1|HS_INVALMASK)
+#define HS_STARTING (2|HS_INVALMASK)
-/*==========================================================
-**
-** assert ()
-**
-**==========================================================
-**
-** modified copy from 386bsd:/usr/include/sys/assert.h
-**
-**----------------------------------------------------------
+/*
+** Flags set by the SCRIPT processor for commands
+** that have been skipped.
*/
-
-#define assert(expression) { \
- if (!(expression)) { \
- (void)printk(KERN_ERR \
- "assertion \"%s\" failed: file \"%s\", line %d\n", \
- #expression, \
- __FILE__, __LINE__); \
- } \
-}
+#define HS_SKIPMASK (0x20)
/*==========================================================
**
-** Big/Little endian support.
-**
-**==========================================================
-*/
-
-/*
-** If the NCR uses big endian addressing mode over the
-** PCI, actual io register addresses for byte and word
-** accesses must be changed according to lane routing.
-** Btw, ncr_offb() and ncr_offw() macros only apply to
-** constants and so donnot generate bloated code.
-*/
-
-#if defined(SCSI_NCR_BIG_ENDIAN)
-
-#define ncr_offb(o) (((o)&~3)+((~((o)&3))&3))
-#define ncr_offw(o) (((o)&~3)+((~((o)&3))&2))
-
-#else
-
-#define ncr_offb(o) (o)
-#define ncr_offw(o) (o)
-
-#endif
-
-/*
-** If the CPU and the NCR use same endian-ness addressing,
-** no byte reordering is needed for script patching.
-** Macro cpu_to_scr() is to be used for script patching.
-** Macro scr_to_cpu() is to be used for getting a DWORD
-** from the script.
-*/
-
-#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
-
-#define cpu_to_scr(dw) cpu_to_le32(dw)
-#define scr_to_cpu(dw) le32_to_cpu(dw)
-
-#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
-
-#define cpu_to_scr(dw) cpu_to_be32(dw)
-#define scr_to_cpu(dw) be32_to_cpu(dw)
-
-#else
-
-#define cpu_to_scr(dw) (dw)
-#define scr_to_cpu(dw) (dw)
-
-#endif
-
-/*==========================================================
-**
-** Access to the controller chip.
-**
-** If NCR_IOMAPPED is defined, the driver will use
-** normal IOs instead of the MEMORY MAPPED IO method
-** recommended by PCI specifications.
-** If all PCI bridges, host brigdes and architectures
-** would have been correctly designed for PCI, this
-** option would be useless.
-**
-**==========================================================
-*/
-
-/*
-** If the CPU and the NCR use same endian-ness addressing,
-** no byte reordering is needed for accessing chip io
-** registers. Functions suffixed by '_raw' are assumed
-** to access the chip over the PCI without doing byte
-** reordering. Functions suffixed by '_l2b' are
-** assumed to perform little-endian to big-endian byte
-** reordering, those suffixed by '_b2l' blah, blah,
-** blah, ...
-*/
-
-#if defined(NCR_IOMAPPED)
-
-/*
-** IO mapped only input / ouput
-*/
-
-#define INB_OFF(o) inb (np->port + ncr_offb(o))
-#define OUTB_OFF(o, val) outb ((val), np->port + ncr_offb(o))
-
-#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
-
-#define INW_OFF(o) inw_l2b (np->port + ncr_offw(o))
-#define INL_OFF(o) inl_l2b (np->port + (o))
-
-#define OUTW_OFF(o, val) outw_b2l ((val), np->port + ncr_offw(o))
-#define OUTL_OFF(o, val) outl_b2l ((val), np->port + (o))
-
-#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
-
-#define INW_OFF(o) inw_b2l (np->port + ncr_offw(o))
-#define INL_OFF(o) inl_b2l (np->port + (o))
-
-#define OUTW_OFF(o, val) outw_l2b ((val), np->port + ncr_offw(o))
-#define OUTL_OFF(o, val) outl_l2b ((val), np->port + (o))
-
-#else
-
-#define INW_OFF(o) inw_raw (np->port + ncr_offw(o))
-#define INL_OFF(o) inl_raw (np->port + (o))
-
-#define OUTW_OFF(o, val) outw_raw ((val), np->port + ncr_offw(o))
-#define OUTL_OFF(o, val) outl_raw ((val), np->port + (o))
-
-#endif /* ENDIANs */
-
-#else /* defined NCR_IOMAPPED */
-
-/*
-** MEMORY mapped IO input / output
-*/
-
-#define INB_OFF(o) readb((char *)np->reg + ncr_offb(o))
-#define OUTB_OFF(o, val) writeb((val), (char *)np->reg + ncr_offb(o))
-
-#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
-
-#define INW_OFF(o) readw_l2b((char *)np->reg + ncr_offw(o))
-#define INL_OFF(o) readl_l2b((char *)np->reg + (o))
-
-#define OUTW_OFF(o, val) writew_b2l((val), (char *)np->reg + ncr_offw(o))
-#define OUTL_OFF(o, val) writel_b2l((val), (char *)np->reg + (o))
-
-#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
-
-#define INW_OFF(o) readw_b2l((char *)np->reg + ncr_offw(o))
-#define INL_OFF(o) readl_b2l((char *)np->reg + (o))
-
-#define OUTW_OFF(o, val) writew_l2b((val), (char *)np->reg + ncr_offw(o))
-#define OUTL_OFF(o, val) writel_l2b((val), (char *)np->reg + (o))
-
-#else
-
-#define INW_OFF(o) readw_raw((char *)np->reg + ncr_offw(o))
-#define INL_OFF(o) readl_raw((char *)np->reg + (o))
-
-#define OUTW_OFF(o, val) writew_raw((val), (char *)np->reg + ncr_offw(o))
-#define OUTL_OFF(o, val) writel_raw((val), (char *)np->reg + (o))
-
-#endif
-
-#endif /* defined NCR_IOMAPPED */
-
-#define INB(r) INB_OFF (offsetof(struct ncr_reg,r))
-#define INW(r) INW_OFF (offsetof(struct ncr_reg,r))
-#define INL(r) INL_OFF (offsetof(struct ncr_reg,r))
-
-#define OUTB(r, val) OUTB_OFF (offsetof(struct ncr_reg,r), (val))
-#define OUTW(r, val) OUTW_OFF (offsetof(struct ncr_reg,r), (val))
-#define OUTL(r, val) OUTL_OFF (offsetof(struct ncr_reg,r), (val))
-
-/*
-** Set bit field ON, OFF
-*/
-
-#define OUTONB(r, m) OUTB(r, INB(r) | (m))
-#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m))
-#define OUTONW(r, m) OUTW(r, INW(r) | (m))
-#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m))
-#define OUTONL(r, m) OUTL(r, INL(r) | (m))
-#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m))
-
-
-/*==========================================================
-**
-** Command control block states.
-**
-**==========================================================
-*/
-
-#define HS_IDLE (0)
-#define HS_BUSY (1)
-#define HS_NEGOTIATE (2) /* sync/wide data transfer*/
-#define HS_DISCONNECT (3) /* Disconnected by target */
-
-#define HS_DONEMASK (0x80)
-#define HS_COMPLETE (4|HS_DONEMASK)
-#define HS_SEL_TIMEOUT (5|HS_DONEMASK) /* Selection timeout */
-#define HS_RESET (6|HS_DONEMASK) /* SCSI reset */
-#define HS_ABORTED (7|HS_DONEMASK) /* Transfer aborted */
-#define HS_TIMEOUT (8|HS_DONEMASK) /* Software timeout */
-#define HS_FAIL (9|HS_DONEMASK) /* SCSI or PCI bus errors */
-#define HS_UNEXPECTED (10|HS_DONEMASK)/* Unexpected disconnect */
-
-/*
-** Invalid host status values used by the SCRIPTS processor
-** when the nexus is not fully identified.
-** Shall never appear in a CCB.
-*/
-
-#define HS_INVALMASK (0x40)
-#define HS_SELECTING (0|HS_INVALMASK)
-#define HS_IN_RESELECT (1|HS_INVALMASK)
-#define HS_STARTING (2|HS_INVALMASK)
-
-/*
-** Flags set by the SCRIPT processor for commands
-** that have been skipped.
-*/
-#define HS_SKIPMASK (0x20)
-
-/*==========================================================
-**
-** Software Interrupt Codes
+** Software Interrupt Codes
**
**==========================================================
*/
@@ -1758,6 +983,8 @@
**----------------------------------------------------------------
*/
Scsi_Cmnd *cmd; /* SCSI command */
+ u_char cdb_buf[16]; /* Copy of CDB */
+ u_char sense_buf[64];
int data_len; /* Total data length */
/*----------------------------------------------------------------
@@ -1888,6 +1115,7 @@
** General controller parameters and configuration.
**----------------------------------------------------------------
*/
+ pcidev_t pdev;
u_short device_id; /* PCI device id */
u_char revision_id; /* PCI device revision id */
u_char bus; /* PCI BUS number */
@@ -1956,6 +1184,7 @@
u_char order; /* Tag order to use */
u_char verbose; /* Verbosity for this controller*/
int ncr_cache; /* Used for cache test at init. */
+ u_long p_ncb; /* BUS address of this NCB */
/*----------------------------------------------------------------
** Command completion handling.
@@ -1969,6 +1198,9 @@
** Fields that should be removed or changed.
**----------------------------------------------------------------
*/
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ u_long ktime; /* Copy of kernel time */
+#endif
struct ccb *ccb; /* Global CCB */
struct usrcmd user; /* Command from user */
u_char release_stage; /* Synchronisation stage on release */
@@ -2158,7 +1390,7 @@
static void ncr_script_copy_and_bind
(ncb_p np, ncrcmd *src, ncrcmd *dst, int len);
static void ncr_script_fill (struct script * scr, struct scripth * scripth);
-static int ncr_scatter (ccb_p cp, Scsi_Cmnd *cmd);
+static int ncr_scatter (ncb_p np, ccb_p cp, Scsi_Cmnd *cmd);
static void ncr_getsync (ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p);
static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer);
static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln);
@@ -2188,25 +1420,6 @@
#define requeue_waiting_list(np) process_waiting_list((np), DID_OK)
#define reset_waiting_list(np) process_waiting_list((np), DID_RESET)
-#ifdef SCSI_NCR_NVRAM_SUPPORT
-static void ncr_get_nvram (ncr_device *devp, ncr_nvram *nvp);
-static int ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram);
-static int ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram *nvram);
-#endif
-
-/*==========================================================
-**
-**
-** Global static data.
-**
-**
-**==========================================================
-*/
-
-#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
-static int ncr_debug = SCSI_NCR_DEBUG_FLAGS;
-#endif
-
static inline char *ncr_name (ncb_p np)
{
return np->inst_name;
@@ -2235,7 +1448,9 @@
#define RELOC_SOFTC 0x40000000
#define RELOC_LABEL 0x50000000
#define RELOC_REGISTER 0x60000000
+#if 0
#define RELOC_KVAR 0x70000000
+#endif
#define RELOC_LABELH 0x80000000
#define RELOC_MASK 0xf0000000
@@ -2244,19 +1459,21 @@
#define PADDRH(label) (RELOC_LABELH | offsetof(struct scripth, label))
#define RADDR(label) (RELOC_REGISTER | REG(label))
#define FADDR(label,ofs)(RELOC_REGISTER | ((REG(label))+(ofs)))
+#if 0
#define KVAR(which) (RELOC_KVAR | (which))
+#endif
+#if 0
#define SCRIPT_KVAR_JIFFIES (0)
-
#define SCRIPT_KVAR_FIRST SCRIPT_KVAR_JIFFIES
#define SCRIPT_KVAR_LAST SCRIPT_KVAR_JIFFIES
-
/*
* Kernel variables referenced in the scripts.
* THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY.
*/
static void *script_kvars[] __initdata =
{ (void *)&jiffies };
+#endif
static struct script script0 __initdata = {
/*--------------------------< START >-----------------------*/ {
@@ -2427,7 +1644,7 @@
** ... set a timestamp ...
*/
SCR_COPY (sizeof (u_long)),
- KVAR(SCRIPT_KVAR_JIFFIES),
+ NADDR (ktime),
NADDR (header.stamp.command),
#endif
/*
@@ -2540,7 +1757,7 @@
** set the timestamp.
*/
SCR_COPY (sizeof (u_long)),
- KVAR(SCRIPT_KVAR_JIFFIES),
+ NADDR (ktime),
NADDR (header.stamp.status),
#endif
/*
@@ -2776,7 +1993,7 @@
** and count the disconnects.
*/
SCR_COPY (sizeof (u_long)),
- KVAR(SCRIPT_KVAR_JIFFIES),
+ NADDR (ktime),
NADDR (header.stamp.disconnect),
SCR_COPY (4),
NADDR (disc_phys),
@@ -2932,7 +2149,7 @@
** Set a time stamp for this reselection
*/
SCR_COPY (sizeof (u_long)),
- KVAR(SCRIPT_KVAR_JIFFIES),
+ NADDR (ktime),
NADDR (header.stamp.reselect),
#endif
/*
@@ -3825,11 +3042,15 @@
*/
relocs = 2;
tmp1 = src[0];
+#ifdef RELOC_KVAR
if ((tmp1 & RELOC_MASK) == RELOC_KVAR)
tmp1 = 0;
+#endif
tmp2 = src[1];
+#ifdef RELOC_KVAR
if ((tmp2 & RELOC_MASK) == RELOC_KVAR)
tmp2 = 0;
+#endif
if ((tmp1 ^ tmp2) & 3) {
printk (KERN_ERR"%s: ERROR1 IN SCRIPT at %d.\n",
ncr_name(np), (int) (src-start-1));
@@ -3882,7 +3103,7 @@
switch (old & RELOC_MASK) {
case RELOC_REGISTER:
new = (old & ~RELOC_MASK)
- + bus_dvma_to_mem(np->paddr);
+ + pcivtobus(np->paddr);
break;
case RELOC_LABEL:
new = (old & ~RELOC_MASK) + np->p_script;
@@ -3891,8 +3112,9 @@
new = (old & ~RELOC_MASK) + np->p_scripth;
break;
case RELOC_SOFTC:
- new = (old & ~RELOC_MASK) + vtophys(np);
+ new = (old & ~RELOC_MASK) + np->p_ncb;
break;
+#ifdef RELOC_KVAR
case RELOC_KVAR:
if (((old & ~RELOC_MASK) <
SCRIPT_KVAR_FIRST) ||
@@ -3902,6 +3124,7 @@
new = vtophys(script_kvars[old &
~RELOC_MASK]);
break;
+#endif
case 0:
/* Don't relocate a 0 address. */
if (old == 0) {
@@ -3941,17 +3164,6 @@
struct host_data {
struct ncb *ncb;
-
- char ncb_align[CACHE_LINE_SIZE-1]; /* Filler for alignment */
- struct ncb _ncb_data;
-
- char ccb_align[CACHE_LINE_SIZE-1]; /* Filler for alignment */
- struct ccb _ccb_data;
-
- char scr_align[CACHE_LINE_SIZE-1]; /* Filler for alignment */
- struct script script_data;
-
- struct scripth scripth_data;
};
/*
@@ -4390,88 +3602,6 @@
return 0;
}
-
-#ifdef SCSI_NCR_DEBUG_NVRAM
-
-void __init ncr_display_Symbios_nvram(ncb_p np, Symbios_nvram *nvram)
-{
- int i;
-
- /* display Symbios nvram host data */
- printk(KERN_DEBUG "%s: HOST ID=%d%s%s%s%s%s\n",
- ncr_name(np), nvram->host_id & 0x0f,
- (nvram->flags & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"",
- (nvram->flags & SYMBIOS_PARITY_ENABLE) ? " PARITY" :"",
- (nvram->flags & SYMBIOS_VERBOSE_MSGS) ? " VERBOSE" :"",
- (nvram->flags & SYMBIOS_CHS_MAPPING) ? " CHS_ALT" :"",
- (nvram->flags1 & SYMBIOS_SCAN_HI_LO) ? " HI_LO" :"");
-
- /* display Symbios nvram drive data */
- for (i = 0 ; i < 15 ; i++) {
- struct Symbios_target *tn = &nvram->target[i];
- printk(KERN_DEBUG "%s-%d:%s%s%s%s WIDTH=%d SYNC=%d TMO=%d\n",
- ncr_name(np), i,
- (tn->flags & SYMBIOS_DISCONNECT_ENABLE) ? " DISC" : "",
- (tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME) ? " SCAN_BOOT" : "",
- (tn->flags & SYMBIOS_SCAN_LUNS) ? " SCAN_LUNS" : "",
- (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? " TCQ" : "",
- tn->bus_width,
- tn->sync_period / 4,
- tn->timeout);
- }
-}
-
-static u_char Tekram_boot_delay[7] __initdata = {3, 5, 10, 20, 30, 60, 120};
-
-void __init ncr_display_Tekram_nvram(ncb_p np, Tekram_nvram *nvram)
-{
- int i, tags, boot_delay;
- char *rem;
-
- /* display Tekram nvram host data */
- tags = 2 << nvram->max_tags_index;
- boot_delay = 0;
- if (nvram->boot_delay_index < 6)
- boot_delay = Tekram_boot_delay[nvram->boot_delay_index];
- switch((nvram->flags & TEKRAM_REMOVABLE_FLAGS) >> 6) {
- default:
- case 0: rem = ""; break;
- case 1: rem = " REMOVABLE=boot device"; break;
- case 2: rem = " REMOVABLE=all"; break;
- }
-
- printk(KERN_DEBUG
- "%s: HOST ID=%d%s%s%s%s%s%s%s%s%s BOOT DELAY=%d tags=%d\n",
- ncr_name(np), nvram->host_id & 0x0f,
- (nvram->flags1 & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"",
- (nvram->flags & TEKRAM_MORE_THAN_2_DRIVES) ? " >2DRIVES" :"",
- (nvram->flags & TEKRAM_DRIVES_SUP_1GB) ? " >1GB" :"",
- (nvram->flags & TEKRAM_RESET_ON_POWER_ON) ? " RESET" :"",
- (nvram->flags & TEKRAM_ACTIVE_NEGATION) ? " ACT_NEG" :"",
- (nvram->flags & TEKRAM_IMMEDIATE_SEEK) ? " IMM_SEEK" :"",
- (nvram->flags & TEKRAM_SCAN_LUNS) ? " SCAN_LUNS" :"",
- (nvram->flags1 & TEKRAM_F2_F6_ENABLED) ? " F2_F6" :"",
- rem, boot_delay, tags);
-
- /* display Tekram nvram drive data */
- for (i = 0; i <= 15; i++) {
- int sync, j;
- struct Tekram_target *tn = &nvram->target[i];
- j = tn->sync_index & 0xf;
- sync = Tekram_sync[j];
- printk(KERN_DEBUG "%s-%d:%s%s%s%s%s%s PERIOD=%d\n",
- ncr_name(np), i,
- (tn->flags & TEKRAM_PARITY_CHECK) ? " PARITY" : "",
- (tn->flags & TEKRAM_SYNC_NEGO) ? " SYNC" : "",
- (tn->flags & TEKRAM_DISCONNECT_ENABLE) ? " DISC" : "",
- (tn->flags & TEKRAM_START_CMD) ? " START" : "",
- (tn->flags & TEKRAM_TAGGED_COMMANDS) ? " TCQ" : "",
- (tn->flags & TEKRAM_WIDE_NEGO) ? " WIDE" : "",
- sync);
- }
-}
-#endif /* SCSI_NCR_DEBUG_NVRAM */
-
/*
** Host attach and initialisations.
**
@@ -4486,7 +3616,7 @@
ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
{
struct host_data *host_data;
- ncb_p np;
+ ncb_p np = 0;
struct Scsi_Host *instance = 0;
u_long flags = 0;
ncr_nvram *nvram = device->nvram;
@@ -4512,21 +3642,25 @@
*/
if (!(instance = scsi_register(tpnt, sizeof(*host_data))))
goto attach_error;
-
- /*
- ** Initialize structure.
- */
host_data = (struct host_data *) instance->hostdata;
- bzero (host_data, sizeof(*host_data));
/*
- ** Align np and first ccb to 32 boundary for cache line
- ** bursting when copying the global header.
+ ** Allocate the host control block.
*/
- np = (ncb_p) (((u_long) &host_data->_ncb_data) & CACHE_LINE_MASK);
+ np = __m_calloc_dma(device->pdev, sizeof(struct ncb), "NCB");
+ if (!np)
+ goto attach_error;
NCR_INIT_LOCK_NCB(np);
+ np->pdev = device->pdev;
+ np->p_ncb = vtobus(np);
host_data->ncb = np;
- np->ccb = (ccb_p) (((u_long) &host_data->_ccb_data) & CACHE_LINE_MASK);
+
+ /*
+ ** Allocate the default CCB.
+ */
+ np->ccb = (ccb_p) m_calloc_dma(sizeof(struct ccb), "CCB");
+ if (!np->ccb)
+ goto attach_error;
/*
** Store input informations in the host data structure.
@@ -4545,9 +3679,17 @@
np->maxburst = device->chip.burst_max;
np->myaddr = device->host_id;
+ /*
+ ** Allocate SCRIPTS areas.
+ */
np->script0 = (struct script *)
- (((u_long) &host_data->script_data) & CACHE_LINE_MASK);
- np->scripth0 = &host_data->scripth_data;
+ m_calloc_dma(sizeof(struct script), "SCRIPT");
+ if (!np->script0)
+ goto attach_error;
+ np->scripth0 = (struct scripth *)
+ m_calloc_dma(sizeof(struct scripth), "SCRIPTH");
+ if (!np->scripth0)
+ goto attach_error;
/*
** Initialize timer structure
@@ -4599,12 +3741,12 @@
switch(nvram->type) {
case SCSI_NCR_SYMBIOS_NVRAM:
#ifdef SCSI_NCR_DEBUG_NVRAM
- ncr_display_Symbios_nvram(np, &nvram->data.Symbios);
+ ncr_display_Symbios_nvram(&nvram->data.Symbios);
#endif
break;
case SCSI_NCR_TEKRAM_NVRAM:
#ifdef SCSI_NCR_DEBUG_NVRAM
- ncr_display_Tekram_nvram(np, &nvram->data.Tekram);
+ ncr_display_Tekram_nvram(&nvram->data.Tekram);
#endif
break;
default:
@@ -4656,13 +3798,14 @@
ncr_script_fill (&script0, &scripth0);
np->scripth = np->scripth0;
- np->p_scripth = vtophys(np->scripth);
+ np->p_scripth = vtobus(np->scripth);
- np->p_script = (np->paddr2) ? bus_dvma_to_mem(np->paddr2) : vtophys(np->script0);
+ np->p_script = (np->paddr2) ?
+ pcivtobus(np->paddr2) : vtobus(np->script0);
ncr_script_copy_and_bind (np, (ncrcmd *) &script0, (ncrcmd *) np->script0, sizeof(struct script));
ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, (ncrcmd *) np->scripth0, sizeof(struct scripth));
- np->ccb->p_ccb = vtophys (np->ccb);
+ np->ccb->p_ccb = vtobus (np->ccb);
/*
** Patch the script for LED support.
@@ -4798,6 +3941,8 @@
attach_error:
if (!instance) return -1;
printk(KERN_INFO "%s: detaching...\n", ncr_name(np));
+ if (!np)
+ goto unregister;
#ifndef NCR_IOMAPPED
if (np->vaddr) {
#ifdef DEBUG_NCR53C8XX
@@ -4823,6 +3968,15 @@
#endif
free_irq(np->irq, np);
}
+ if (np->scripth0)
+ m_free_dma(np->scripth0, sizeof(struct scripth), "SCRIPTH");
+ if (np->script0)
+ m_free_dma(np->script0, sizeof(struct script), "SCRIPT");
+ if (np->ccb)
+ m_free_dma(np->ccb, sizeof(struct ccb), "CCB");
+ m_free_dma(np, sizeof(struct ncb), "NCB");
+
+unregister:
scsi_unregister(instance);
return -1;
@@ -4850,6 +4004,7 @@
*/
static inline void ncr_queue_done_cmd(ncb_p np, Scsi_Cmnd *cmd)
{
+ unmap_scsi_data(np, cmd);
cmd->host_scribble = (char *) np->done_list;
np->done_list = cmd;
}
@@ -5105,7 +4260,7 @@
**----------------------------------------------------
*/
- segments = ncr_scatter (cp, cp->cmd);
+ segments = ncr_scatter (np, cp, cp->cmd);
if (segments < 0) {
ncr_free_ccb(np, cp);
@@ -5114,47 +4269,24 @@
/*----------------------------------------------------
**
- ** Guess xfer direction.
- ** Spare some CPU by testing here frequently opcode.
+ ** Determine xfer direction.
**
**----------------------------------------------------
*/
if (!cp->data_len)
- direction = 0;
- else {
- switch((int) cmd->cmnd[0]) {
- case 0x08: /* READ(6) 08 */
- case 0x28: /* READ(10) 28 */
- case 0xA8: /* READ(12) A8 */
- direction = XFER_IN;
- break;
- case 0x0A: /* WRITE(6) 0A */
- case 0x2A: /* WRITE(10) 2A */
- case 0xAA: /* WRITE(12) AA */
- direction = XFER_OUT;
- break;
- default:
- direction = (XFER_IN|XFER_OUT);
- break;
- }
- }
-
- /*----------------------------------------------------
- **
- ** Set the SAVED_POINTER.
- **
- **----------------------------------------------------
- */
-
- /*
- ** Default to no data transfer.
- */
- lastp = goalp = NCB_SCRIPT_PHYS (np, no_data);
+ direction = SCSI_DATA_NONE;
+ else
+ direction = scsi_data_direction(cmd);
/*
- ** Compute data out pointers, if needed.
+ ** If data direction is UNKNOWN, speculate DATA_READ
+ ** but prepare alternate pointers for WRITE in case
+ ** of our speculation will be just wrong.
+ ** SCRIPTS will swap values if needed.
*/
- if (direction & XFER_OUT) {
+ switch(direction) {
+ case SCSI_DATA_UNKNOWN:
+ case SCSI_DATA_WRITE:
goalp = NCB_SCRIPT_PHYS (np, data_out2) + 8;
if (segments <= MAX_SCATTERL)
lastp = goalp - 8 - (segments * 16);
@@ -5162,21 +4294,12 @@
lastp = NCB_SCRIPTH_PHYS (np, hdata_out2);
lastp -= (segments - MAX_SCATTERL) * 16;
}
- /*
- ** If actual data direction is unknown, save pointers
- ** in header. The SCRIPTS will swap them to current
- ** if target decision will be data out.
- */
- if (direction & XFER_IN) {
- cp->phys.header.wgoalp = cpu_to_scr(goalp);
- cp->phys.header.wlastp = cpu_to_scr(lastp);
- }
- }
-
- /*
- ** Compute data in pointers, if needed.
- */
- if (direction & XFER_IN) {
+ if (direction != SCSI_DATA_UNKNOWN)
+ break;
+ cp->phys.header.wgoalp = cpu_to_scr(goalp);
+ cp->phys.header.wlastp = cpu_to_scr(lastp);
+ /* fall through */
+ case SCSI_DATA_READ:
goalp = NCB_SCRIPT_PHYS (np, data_in2) + 8;
if (segments <= MAX_SCATTERL)
lastp = goalp - 8 - (segments * 16);
@@ -5184,6 +4307,11 @@
lastp = NCB_SCRIPTH_PHYS (np, hdata_in2);
lastp -= (segments - MAX_SCATTERL) * 16;
}
+ break;
+ default:
+ case SCSI_DATA_NONE:
+ lastp = goalp = NCB_SCRIPT_PHYS (np, no_data);
+ break;
}
/*
@@ -5193,7 +4321,7 @@
cp->phys.header.lastp = cpu_to_scr(lastp);
cp->phys.header.goalp = cpu_to_scr(goalp);
- if ((direction & (XFER_IN|XFER_OUT)) == (XFER_IN|XFER_OUT))
+ if (direction == SCSI_DATA_UNKNOWN)
cp->phys.header.savep =
cpu_to_scr(NCB_SCRIPTH_PHYS (np, data_io));
else
@@ -5236,7 +4364,8 @@
/*
** command
*/
- cp->phys.cmd.addr = cpu_to_scr(vtophys (&cmd->cmnd[0]));
+ memcpy(cp->cdb_buf, cmd->cmnd, MIN(cmd->cmd_len, sizeof(cp->cdb_buf)));
+ cp->phys.cmd.addr = cpu_to_scr(CCB_PHYS (cp, cdb_buf[0]));
cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len);
/*
@@ -5684,7 +4813,7 @@
#ifdef DEBUG_NCR53C8XX
printk("%s: freeing ccb (%lx)\n", ncr_name(np), (u_long) cp);
#endif
- m_free(cp, sizeof(*cp));
+ m_free_dma(cp, sizeof(*cp), "CCB");
}
/*
@@ -5700,12 +4829,20 @@
printk("%s: freeing lp (%lx)\n", ncr_name(np), (u_long) lp);
#endif
if (lp->jump_ccb != &lp->jump_ccb_0)
- m_free(lp->jump_ccb, 256);
- m_free(lp, sizeof(*lp));
+ m_free_dma(lp->jump_ccb,256,"JUMP_CCB");
+ m_free_dma(lp, sizeof(*lp), "LCB");
}
}
}
+ if (np->scripth0)
+ m_free_dma(np->scripth0, sizeof(struct scripth), "SCRIPTH");
+ if (np->script0)
+ m_free_dma(np->script0, sizeof(struct script), "SCRIPT");
+ if (np->ccb)
+ m_free_dma(np->ccb, sizeof(struct ccb), "CCB");
+ m_free_dma(np, sizeof(struct ncb), "NCB");
+
printk("%s: host resources successfully released\n", ncr_name(np));
return 1;
@@ -5859,6 +4996,7 @@
*/
if (cmd->cmnd[0] == 0x12 && !(cmd->cmnd[1] & 0x3) &&
cmd->cmnd[4] >= 7 && !cmd->use_sg) {
+ sync_scsi_data(np, cmd); /* SYNC the data */
ncr_setup_lcb (np, cmd->target, cmd->lun,
(char *) cmd->request_buffer);
}
@@ -5885,6 +5023,12 @@
*/
cmd->result = ScsiResult(DID_OK, S_CHECK_COND);
+ /*
+ ** Copy back sense data to caller's buffer.
+ */
+ memcpy(cmd->sense_buffer, cp->sense_buf,
+ MIN(sizeof(cmd->sense_buffer), sizeof(cp->sense_buf)));
+
if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) {
u_char * p = (u_char*) & cmd->sense_buffer;
int i;
@@ -6260,7 +5404,7 @@
if (bootverbose)
printk ("%s: Downloading SCSI SCRIPTS.\n",
ncr_name(np));
- OUTL (nc_scratcha, vtophys(np->script0));
+ OUTL (nc_scratcha, vtobus(np->script0));
OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, start_ram));
}
else
@@ -6774,7 +5918,12 @@
return;
}
+#ifdef SCSI_NCR_PROFILE_SUPPORT
+ np->ktime = thistime;
+ np->timer.expires = ktime_get(1);
+#else
np->timer.expires = ktime_get(SCSI_NCR_TIMER_INTERVAL);
+#endif
add_timer(&np->timer);
/*
@@ -7289,6 +6438,7 @@
u_int32 dsp;
u_int32 dsa;
u_int32 nxtdsp;
+ u_int32 newtmp;
u_int32 *vdsp;
u_int32 oadr, olen;
u_int32 *tblp;
@@ -7383,11 +6533,11 @@
nxtdsp = dsp;
}
else if (cp) {
- if (dsp == vtophys (&cp->patch[2])) {
+ if (dsp == CCB_PHYS (cp, patch[2])) {
vdsp = &cp->patch[0];
nxtdsp = scr_to_cpu(vdsp[3]);
}
- else if (dsp == vtophys (&cp->patch[6])) {
+ else if (dsp == CCB_PHYS (cp, patch[6])) {
vdsp = &cp->patch[4];
nxtdsp = scr_to_cpu(vdsp[3]);
}
@@ -7482,7 +6632,11 @@
*/
newcmd = cp->patch;
- if (cp->phys.header.savep == cpu_to_scr(vtophys (newcmd))) newcmd+=4;
+ newtmp = CCB_PHYS (cp, patch);
+ if (newtmp == scr_to_cpu(cp->phys.header.savep)) {
+ newcmd = &cp->patch[4];
+ newtmp = CCB_PHYS (cp, patch[4]);
+ }
/*
** fillin the commands
@@ -7509,7 +6663,7 @@
#ifdef SCSI_NCR_PROFILE_SUPPORT
np->profile.num_break++;
#endif
- OUTL (nc_temp, vtophys (newcmd));
+ OUTL (nc_temp, newtmp);
OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch));
return;
@@ -7678,15 +6832,14 @@
*/
cp->sensecmd[0] = 0x03;
cp->sensecmd[1] = cmd->lun << 5;
- cp->sensecmd[4] = sizeof(cmd->sense_buffer);
+ cp->sensecmd[4] = sizeof(cp->sense_buf);
/*
** sense data
*/
- cp->phys.sense.addr =
- cpu_to_scr(vtophys (&cmd->sense_buffer[0]));
- cp->phys.sense.size =
- cpu_to_scr(sizeof(cmd->sense_buffer));
+ bzero(cp->sense_buf, sizeof(cp->sense_buf));
+ cp->phys.sense.addr = cpu_to_scr(CCB_PHYS(cp,sense_buf[0]));
+ cp->phys.sense.size = cpu_to_scr(sizeof(cp->sense_buf));
/*
** requeue the command.
@@ -8395,7 +7548,7 @@
#define ncr_reg_bus_addr(r) \
- (bus_dvma_to_mem(np->paddr) + offsetof (struct ncr_reg, r))
+ (pcivtobus(np->paddr) + offsetof (struct ncr_reg, r))
/*------------------------------------------------------------------------
** Initialize the fixed part of a CCB structure.
@@ -8409,7 +7562,7 @@
/*
** Remember virtual and bus address of this ccb.
*/
- cp->p_ccb = vtophys(cp);
+ cp->p_ccb = vtobus(cp);
cp->phys.header.cp = cp;
/*
@@ -8424,10 +7577,10 @@
** JUMP @(sched_point)
*/
cp->start.setup_dsa[0] = cpu_to_scr(copy_4);
- cp->start.setup_dsa[1] = cpu_to_scr(vtophys(&cp->start.p_phys));
+ cp->start.setup_dsa[1] = cpu_to_scr(CCB_PHYS(cp, start.p_phys));
cp->start.setup_dsa[2] = cpu_to_scr(ncr_reg_bus_addr(nc_dsa));
cp->start.schedule.l_cmd = cpu_to_scr(SCR_JUMP);
- cp->start.p_phys = cpu_to_scr(vtophys(&cp->phys));
+ cp->start.p_phys = cpu_to_scr(CCB_PHYS(cp, phys));
bcopy(&cp->start, &cp->restart, sizeof(cp->restart));
@@ -8450,15 +7603,10 @@
/*
** Allocate memory for this CCB.
*/
- cp = m_alloc(sizeof(struct ccb), 5);
+ cp = m_calloc_dma(sizeof(struct ccb), "CCB");
if (!cp)
return;
- if (DEBUG_FLAGS & DEBUG_ALLOC) {
- PRINT_LUN(np, tn, ln);
- printk ("new ccb @%p.\n", cp);
- }
-
/*
** Count it and initialyze it.
*/
@@ -8516,7 +7664,7 @@
** COPY @(tp->sval), @(sxfer)
*/
tp->getscr[0] = cpu_to_scr(copy_1);
- tp->getscr[1] = cpu_to_scr(vtophys (&tp->sval));
+ tp->getscr[1] = cpu_to_scr(vtobus (&tp->sval));
tp->getscr[2] = cpu_to_scr(ncr_reg_bus_addr(nc_sxfer));
/*
@@ -8524,7 +7672,7 @@
** COPY @(tp->wval), @(scntl3)
*/
tp->getscr[3] = cpu_to_scr(copy_1);
- tp->getscr[4] = cpu_to_scr(vtophys (&tp->wval));
+ tp->getscr[4] = cpu_to_scr(vtobus (&tp->wval));
tp->getscr[5] = cpu_to_scr(ncr_reg_bus_addr(nc_scntl3));
/*
@@ -8549,7 +7697,7 @@
/*
** Link this target control block to the JUMP chain.
*/
- np->jump_tcb[th].l_paddr = cpu_to_scr(vtophys (&tp->jump_tcb));
+ np->jump_tcb[th].l_paddr = cpu_to_scr(vtobus (&tp->jump_tcb));
/*
** These assert's should be moved at driver initialisations.
@@ -8584,17 +7732,12 @@
/*
** Allocate the lcb.
*/
- lp = m_alloc(sizeof(struct lcb), 3);
+ lp = m_calloc_dma(sizeof(struct lcb), "LCB");
if (!lp)
goto fail;
bzero(lp, sizeof(*lp));
tp->lp[ln] = lp;
- if (DEBUG_FLAGS & DEBUG_ALLOC) {
- PRINT_LUN(np, tn, ln);
- printk ("new lcb @%p.\n", lp);
- }
-
/*
** Initialize the target control block if not yet.
*/
@@ -8615,7 +7758,7 @@
*/
lp->maxnxs = 1;
lp->jump_ccb = &lp->jump_ccb_0;
- lp->p_jump_ccb = cpu_to_scr(vtophys(lp->jump_ccb));
+ lp->p_jump_ccb = cpu_to_scr(vtobus(lp->jump_ccb));
/*
** Initilialyze the reselect script:
@@ -8633,7 +7776,7 @@
lp->jump_lcb.l_paddr = tp->jump_lcb[lh].l_paddr;
lp->load_jump_ccb[0] = cpu_to_scr(copy_4);
- lp->load_jump_ccb[1] = cpu_to_scr(vtophys (&lp->p_jump_ccb));
+ lp->load_jump_ccb[1] = cpu_to_scr(vtobus (&lp->p_jump_ccb));
lp->load_jump_ccb[2] = cpu_to_scr(ncr_reg_bus_addr(nc_temp));
lp->jump_tag.l_cmd = cpu_to_scr(SCR_JUMP);
@@ -8642,7 +7785,7 @@
/*
** Link this lun control block to the JUMP chain.
*/
- tp->jump_lcb[lh].l_paddr = cpu_to_scr(vtophys (&lp->jump_lcb));
+ tp->jump_lcb[lh].l_paddr = cpu_to_scr(vtobus (&lp->jump_lcb));
/*
** Initialize command queuing control.
@@ -8726,12 +7869,12 @@
*/
if ((inq_byte7 & INQ7_QUEUE) && lp->jump_ccb == &lp->jump_ccb_0) {
int i;
- lp->jump_ccb = m_alloc(256, 8);
+ lp->jump_ccb = m_calloc_dma(256, "JUMP_CCB");
if (!lp->jump_ccb) {
lp->jump_ccb = &lp->jump_ccb_0;
goto fail;
}
- lp->p_jump_ccb = cpu_to_scr(vtophys(lp->jump_ccb));
+ lp->p_jump_ccb = cpu_to_scr(vtobus(lp->jump_ccb));
for (i = 0 ; i < 64 ; i++)
lp->jump_ccb[i] =
cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_i_t_l_q));
@@ -8783,7 +7926,7 @@
** sizes to the data segment array.
*/
-static int ncr_scatter(ccb_p cp, Scsi_Cmnd *cmd)
+static int ncr_scatter(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd)
{
struct scr_tblmove *data;
int segment = 0;
@@ -8794,8 +7937,10 @@
if (!use_sg) {
if (cmd->request_bufflen) {
+ u_long baddr = map_scsi_single_data(np, cmd);
+
data = &data[MAX_SCATTER - 1];
- data[0].addr = cpu_to_scr(vtophys(cmd->request_buffer));
+ data[0].addr = cpu_to_scr(baddr);
data[0].size = cpu_to_scr(cmd->request_bufflen);
cp->data_len = cmd->request_bufflen;
segment = 1;
@@ -8804,13 +7949,16 @@
else if (use_sg <= MAX_SCATTER) {
struct scatterlist *scatter = (struct scatterlist *)cmd->buffer;
+ use_sg = map_scsi_sg_data(np, cmd);
data = &data[MAX_SCATTER - use_sg];
+
while (segment < use_sg) {
- data[segment].addr =
- cpu_to_scr(vtophys(scatter[segment].address));
- data[segment].size =
- cpu_to_scr(scatter[segment].length);
- cp->data_len += scatter[segment].length;
+ u_long baddr = scsi_sg_dma_address(&scatter[segment]);
+ unsigned int len = scsi_sg_dma_len(&scatter[segment]);
+
+ data[segment].addr = cpu_to_scr(baddr);
+ data[segment].size = cpu_to_scr(len);
+ cp->data_len += len;
++segment;
}
}
@@ -9198,866 +8346,43 @@
(void) ncrgetfreq (np, 11); /* throw away first result */
f1 = ncrgetfreq (np, 11);
- f2 = ncrgetfreq (np, 11);
-
- if (bootverbose)
- printk ("%s: NCR clock is %uKHz, %uKHz\n", ncr_name(np), f1, f2);
-
- if (f1 > f2) f1 = f2; /* trust lower result */
-
- if (f1 < 45000) f1 = 40000;
- else if (f1 < 55000) f1 = 50000;
- else f1 = 80000;
-
- if (f1 < 80000 && mult > 1) {
- if (bootverbose >= 2)
- printk ("%s: clock multiplier assumed\n", ncr_name(np));
- np->multiplier = mult;
- }
- } else {
- if ((scntl3 & 7) == 3) f1 = 40000;
- else if ((scntl3 & 7) == 5) f1 = 80000;
- else f1 = 160000;
-
- f1 /= np->multiplier;
- }
-
- /*
- ** Compute controller synchronous parameters.
- */
- f1 *= np->multiplier;
- np->clock_khz = f1;
-}
-
-/*===================== LINUX ENTRY POINTS SECTION ==========================*/
-
-#ifndef uchar
-#define uchar unsigned char
-#endif
-
-#ifndef ushort
-#define ushort unsigned short
-#endif
-
-#ifndef ulong
-#define ulong unsigned long
-#endif
-
-/* ---------------------------------------------------------------------
-**
-** Driver setup from the boot command line
-**
-** ---------------------------------------------------------------------
-*/
-
-#ifdef MODULE
-#define ARG_SEP ' '
-#else
-#define ARG_SEP ','
-#endif
-
-int __init ncr53c8xx_setup(char *str)
-{
-#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
- char *cur = str;
- char *pc, *pv;
- int val;
- int base;
- int c;
- int xi = 0;
-
- while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
- char *pe;
-
- val = 0;
- pv = pc;
- c = *++pv;
-
- if (c == 'n')
- val = 0;
- else if (c == 'y')
- val = 1;
- else {
- base = 0;
- val = (int) simple_strtoul(pv, &pe, base);
- }
- if (!strncmp(cur, "tags:", 5)) {
- int i;
- driver_setup.default_tags = val;
- if (pe && *pe == '/') {
- i = 0;
- while (*pe && *pe != ARG_SEP &&
- i < sizeof(driver_setup.tag_ctrl)-1) {
- driver_setup.tag_ctrl[i++] = *pe++;
- }
- driver_setup.tag_ctrl[i] = '\0';
- }
- }
- else if (!strncmp(cur, "mpar:", 5))
- driver_setup.master_parity = val;
- else if (!strncmp(cur, "spar:", 5))
- driver_setup.scsi_parity = val;
- else if (!strncmp(cur, "disc:", 5))
- driver_setup.disconnection = val;
- else if (!strncmp(cur, "specf:", 6))
- driver_setup.special_features = val;
- else if (!strncmp(cur, "ultra:", 6))
- driver_setup.ultra_scsi = val;
- else if (!strncmp(cur, "fsn:", 4))
- driver_setup.force_sync_nego = val;
- else if (!strncmp(cur, "revprob:", 8))
- driver_setup.reverse_probe = val;
- else if (!strncmp(cur, "sync:", 5))
- driver_setup.default_sync = val;
- else if (!strncmp(cur, "verb:", 5))
- driver_setup.verbose = val;
- else if (!strncmp(cur, "debug:", 6))
- driver_setup.debug = val;
- else if (!strncmp(cur, "burst:", 6))
- driver_setup.burst_max = val;
- else if (!strncmp(cur, "led:", 4))
- driver_setup.led_pin = val;
- else if (!strncmp(cur, "wide:", 5))
- driver_setup.max_wide = val? 1:0;
- else if (!strncmp(cur, "settle:", 7))
- driver_setup.settle_delay= val;
- else if (!strncmp(cur, "diff:", 5))
- driver_setup.diff_support= val;
- else if (!strncmp(cur, "irqm:", 5))
- driver_setup.irqm = val;
- else if (!strncmp(cur, "pcifix:", 7))
- driver_setup.pci_fix_up = val;
- else if (!strncmp(cur, "buschk:", 7))
- driver_setup.bus_check = val;
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- else if (!strncmp(cur, "nvram:", 6))
- driver_setup.use_nvram = val;
-#endif
-
- else if (!strncmp(cur, "safe:", 5) && val)
- memcpy(&driver_setup, &driver_safe_setup, sizeof(driver_setup));
- else if (!strncmp(cur, "excl:", 5)) {
- if (xi < SCSI_NCR_MAX_EXCLUDES)
- driver_setup.excludes[xi++] = val;
- }
- else if (!strncmp(cur, "hostid:", 7))
- driver_setup.host_id = val;
- else
- printk("ncr53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
-
- if ((cur = strchr(cur, ARG_SEP)) != NULL)
- ++cur;
- }
-#endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
- return 0;
-}
-
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13)
-#ifndef MODULE
-__setup("ncr53c8xx=", ncr53c8xx_setup);
-#endif
-#endif
-
-static int
-ncr53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, ncr_device *device);
-
-/*
-** Linux entry point for NCR53C8XX devices detection routine.
-**
-** Called by the middle-level scsi drivers at initialization time,
-** or at module installation.
-**
-** Read the PCI configuration and try to attach each
-** detected NCR board.
-**
-** If NVRAM is present, try to attach boards according to
-** the used defined boot order.
-**
-** Returns the number of boards successfully attached.
-*/
-
-static void __init ncr_print_driver_setup(void)
-{
-#define YesNo(y) y ? 'y' : 'n'
- printk ("ncr53c8xx: setup=disc:%c,specf:%d,ultra:%d,tags:%d,sync:%d,"
- "burst:%d,wide:%c,diff:%d,revprob:%c,buschk:0x%x\n",
- YesNo(driver_setup.disconnection),
- driver_setup.special_features,
- driver_setup.ultra_scsi,
- driver_setup.default_tags,
- driver_setup.default_sync,
- driver_setup.burst_max,
- YesNo(driver_setup.max_wide),
- driver_setup.diff_support,
- YesNo(driver_setup.reverse_probe),
- driver_setup.bus_check);
-
- printk ("ncr53c8xx: setup=mpar:%c,spar:%c,fsn=%c,verb:%d,debug:0x%x,"
- "led:%c,settle:%d,irqm:%d,nvram:0x%x,pcifix:0x%x\n",
- YesNo(driver_setup.master_parity),
- YesNo(driver_setup.scsi_parity),
- YesNo(driver_setup.force_sync_nego),
- driver_setup.verbose,
- driver_setup.debug,
- YesNo(driver_setup.led_pin),
- driver_setup.settle_delay,
- driver_setup.irqm,
- driver_setup.use_nvram,
- driver_setup.pci_fix_up);
-#undef YesNo
-}
-
-/*
-** NCR53C8XX devices description table and chip ids list.
-*/
-
-static ncr_chip ncr_chip_table[] __initdata = SCSI_NCR_CHIP_TABLE;
-static ushort ncr_chip_ids[] __initdata = SCSI_NCR_CHIP_IDS;
-
-
-/*===================================================================
-** Detect all 53c8xx hosts and then attach them.
-**
-** If we are using NVRAM, once all hosts are detected, we need to
-** check any NVRAM for boot order in case detect and boot order
-** differ and attach them using the order in the NVRAM.
-**
-** If no NVRAM is found or data appears invalid attach boards in
-** the the order they are detected.
-**===================================================================
-*/
-int __init ncr53c8xx_detect(Scsi_Host_Template *tpnt)
-{
- pcidev_t pcidev;
- int i, j, chips, hosts, count;
- int attach_count = 0;
- ncr_device *devtbl, *devp;
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- ncr_nvram nvram0, nvram, *nvp;
-#endif
-
- /*
- ** PCI is required.
- */
- if (!pci_present())
- return 0;
-
- /*
- ** Initialize driver general stuff.
- */
-#ifdef SCSI_NCR_PROC_INFO_SUPPORT
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
- tpnt->proc_dir = &proc_scsi_ncr53c8xx;
-#else
- tpnt->proc_name = "ncr53c8xx";
-#endif
- tpnt->proc_info = ncr53c8xx_proc_info;
-#endif
-
-#if defined(SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT) && defined(MODULE)
-if (ncr53c8xx)
- ncr53c8xx_setup(ncr53c8xx);
-#endif
-#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
- ncr_debug = driver_setup.debug;
-#endif
-
- if (initverbose >= 2)
- ncr_print_driver_setup();
-
- /*
- ** Allocate the device table since we donnot want to
- ** overflow the kernel stack.
- ** 1 x 4K PAGE is enough for more than 40 devices for i386.
- */
- devtbl = kmalloc(4000, GFP_ATOMIC);
- if (!devtbl)
- return 0;
-
- /*
- ** Detect all 53c8xx hosts.
- ** Save the first Symbios NVRAM content if any
- ** for the boot order.
- */
- chips = sizeof(ncr_chip_ids) / sizeof(ncr_chip_ids[0]);
- hosts = 4000 / sizeof(*devtbl);
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- nvp = (driver_setup.use_nvram & 0x1) ? &nvram0 : 0;
-#endif
- j = 0;
- count = 0;
- pcidev = PCIDEV_NULL;
- while (1) {
- char *msg = "";
- if (count >= hosts)
- break;
- if (j >= chips)
- break;
- i = driver_setup.reverse_probe ? chips - 1 - j : j;
- pcidev = pci_find_device(PCI_VENDOR_ID_NCR, ncr_chip_ids[i],
- pcidev);
- if (pcidev == PCIDEV_NULL) {
- ++j;
- continue;
- }
- /* Some HW as the HP LH4 may report twice PCI devices */
- for (i = 0; i < count ; i++) {
- if (devtbl[i].slot.bus == PciBusNumber(pcidev) &&
- devtbl[i].slot.device_fn == PciDeviceFn(pcidev))
- break;
- }
- if (i != count) /* Ignore this device if we already have it */
- continue;
- devp = &devtbl[count];
- devp->host_id = driver_setup.host_id;
- devp->attach_done = 0;
- if (ncr53c8xx_pci_init(tpnt, pcidev, devp)) {
- continue;
- }
- ++count;
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- if (nvp) {
- ncr_get_nvram(devp, nvp);
- switch(nvp->type) {
- case SCSI_NCR_SYMBIOS_NVRAM:
- /*
- * Switch to the other nvram buffer, so that
- * nvram0 will contain the first Symbios
- * format NVRAM content with boot order.
- */
- nvp = &nvram;
- msg = "with Symbios NVRAM";
- break;
- case SCSI_NCR_TEKRAM_NVRAM:
- msg = "with Tekram NVRAM";
- break;
- }
- }
-#endif
- printk(KERN_INFO "ncr53c8xx: 53c%s detected %s\n",
- devp->chip.name, msg);
- }
-
- /*
- ** If we have found a SYMBIOS NVRAM, use first the NVRAM boot
- ** sequence as device boot order.
- ** check devices in the boot record against devices detected.
- ** attach devices if we find a match. boot table records that
- ** do not match any detected devices will be ignored.
- ** devices that do not match any boot table will not be attached
- ** here but will attempt to be attached during the device table
- ** rescan.
- */
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- if (!nvp || nvram0.type != SCSI_NCR_SYMBIOS_NVRAM)
- goto next;
- for (i = 0; i < 4; i++) {
- Symbios_host *h = &nvram0.data.Symbios.host[i];
- for (j = 0 ; j < count ; j++) {
- devp = &devtbl[j];
- if (h->device_fn != devp->slot.device_fn ||
- h->bus_nr != devp->slot.bus ||
- h->device_id != devp->chip.device_id)
- continue;
- if (devp->attach_done)
- continue;
- ncr_get_nvram(devp, nvp);
- if (!ncr_attach (tpnt, attach_count, devp))
- attach_count++;
- devp->attach_done = 1;
- break;
- }
- }
-next:
-#endif
-
- /*
- ** Rescan device list to make sure all boards attached.
- ** Devices without boot records will not be attached yet
- ** so try to attach them here.
- */
- for (i= 0; i < count; i++) {
- devp = &devtbl[i];
- if (!devp->attach_done) {
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- ncr_get_nvram(devp, nvp);
-#endif
- if (!ncr_attach (tpnt, attach_count, devp))
- attach_count++;
- }
- }
-
- kfree(devtbl);
-
- return attach_count;
-}
-
-/*===================================================================
-** Detect and try to read SYMBIOS and TEKRAM NVRAM.
-**
-** Data can be used to order booting of boards.
-**
-** Data is saved in ncr_device structure if NVRAM found. This
-** is then used to find drive boot order for ncr_attach().
-**
-** NVRAM data is passed to Scsi_Host_Template later during
-** ncr_attach() for any device set up.
-*===================================================================
-*/
-#ifdef SCSI_NCR_NVRAM_SUPPORT
-static void __init ncr_get_nvram(ncr_device *devp, ncr_nvram *nvp)
-{
- devp->nvram = nvp;
- if (!nvp)
- return;
- /*
- ** Get access to chip IO registers
- */
-#ifdef NCR_IOMAPPED
- request_region(devp->slot.io_port, 128, "ncr53c8xx");
- devp->slot.port = devp->slot.io_port;
-#else
- devp->slot.reg = (struct ncr_reg *) remap_pci_mem(devp->slot.base, 128);
- if (!devp->slot.reg)
- return;
-#endif
-
- /*
- ** Try to read SYMBIOS nvram.
- ** Try to read TEKRAM nvram if Symbios nvram not found.
- */
- if (!ncr_get_Symbios_nvram(&devp->slot, &nvp->data.Symbios))
- nvp->type = SCSI_NCR_SYMBIOS_NVRAM;
- else if (!ncr_get_Tekram_nvram(&devp->slot, &nvp->data.Tekram))
- nvp->type = SCSI_NCR_TEKRAM_NVRAM;
- else {
- nvp->type = 0;
- devp->nvram = 0;
- }
-
- /*
- ** Release access to chip IO registers
- */
-#ifdef NCR_IOMAPPED
- release_region(devp->slot.port, 128);
-#else
- unmap_pci_mem((u_long) devp->slot.reg, 128ul);
-#endif
-
-}
-#endif /* SCSI_NCR_NVRAM_SUPPORT */
-
-/*
-** Read and check the PCI configuration for any detected NCR
-** boards and save data for attaching after all boards have
-** been detected.
-*/
-
-static int __init
-ncr53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, ncr_device *device)
-{
- ushort vendor_id, device_id, command;
- uchar cache_line_size, latency_timer;
- uchar revision;
- uint irq;
- ulong base, base_2, io_port;
- int i;
- ncr_chip *chip;
-
- /*
- ** Read info from the PCI config space.
- ** pci_read_config_xxx() functions are assumed to be used for
- ** successfully detected PCI devices.
- */
- vendor_id = PciVendorId(pdev);
- device_id = PciDeviceId(pdev);
- irq = PciIrqLine(pdev);
- i = 0;
- i = pci_get_base_address(pdev, i, &io_port);
- i = pci_get_base_address(pdev, i, &base);
- (void) pci_get_base_address(pdev, i, &base_2);
- pci_read_config_word(pdev, PCI_COMMAND, &command);
- pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
- pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);
- pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer);
-
- /*
- ** If user excludes this chip, donnot initialize it.
- */
- for (i = 0 ; i < SCSI_NCR_MAX_EXCLUDES ; i++) {
- if (driver_setup.excludes[i] ==
- (io_port & PCI_BASE_ADDRESS_IO_MASK))
- return -1;
- }
- /*
- * Check if the chip is supported
- */
- chip = 0;
- for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); i++) {
- if (device_id != ncr_chip_table[i].device_id)
- continue;
- if (revision > ncr_chip_table[i].revision_id)
- continue;
- chip = &device->chip;
- memcpy(chip, &ncr_chip_table[i], sizeof(*chip));
- chip->revision_id = revision;
- break;
- }
-
-#if defined(__i386__)
- /*
- * Ignore Symbios chips controlled by SISL RAID controller.
- */
- if (chip && (base_2 & PCI_BASE_ADDRESS_MEM_MASK)) {
- unsigned int ScriptsSize, MagicValue;
- vm_offset_t ScriptsRAM;
-
- if (chip->features & FE_RAM8K)
- ScriptsSize = 8192;
- else
- ScriptsSize = 4096;
-
- ScriptsRAM = remap_pci_mem(base_2 & PCI_BASE_ADDRESS_MEM_MASK,
- ScriptsSize);
- if (ScriptsRAM) {
- MagicValue = readl(ScriptsRAM + ScriptsSize - 16);
- unmap_pci_mem(ScriptsRAM, ScriptsSize);
- if (MagicValue == 0x52414944)
- return -1;
- }
- }
-#endif
-
- printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n",
- PciBusNumber(pdev),
- (int) (PciDeviceFn(pdev) & 0xf8) >> 3,
- (int) (PciDeviceFn(pdev) & 0x7));
-
- if (!chip) {
- printk("ncr53c8xx: not initializing, device not supported\n");
- return -1;
- }
-
-#ifdef __powerpc__
- /*
- * Several fix-up for power/pc.
- * Should not be performed by the driver.
- */
- if (!(command & PCI_COMMAND_MASTER)) {
- printk("ncr53c8xx: attempting to force PCI_COMMAND_MASTER...");
- command |= PCI_COMMAND_MASTER;
- pci_write_config_word(pdev, PCI_COMMAND, command);
- pci_read_config_word(pdev, PCI_COMMAND, &command);
- if (!(command & PCI_COMMAND_MASTER)) {
- printk("failed!\n");
- } else {
- printk("succeeded.\n");
- }
- }
-
- if (!(command & PCI_COMMAND_IO)) {
- printk("ncr53c8xx: attempting to force PCI_COMMAND_IO...");
- command |= PCI_COMMAND_IO;
- pci_write_config_word(pdev, PCI_COMMAND, command);
- pci_read_config_word(pdev, PCI_COMMAND, &command);
- if (!(command & PCI_COMMAND_IO)) {
- printk("failed!\n");
- } else {
- printk("succeeded.\n");
- }
- }
-
- if (!(command & PCI_COMMAND_MEMORY)) {
- printk("ncr53c8xx: attempting to force PCI_COMMAND_MEMORY...");
- command |= PCI_COMMAND_MEMORY;
- pci_write_config_word(pdev, PCI_COMMAND, command);
- pci_read_config_word(pdev, PCI_COMMAND, &command);
- if (!(command & PCI_COMMAND_MEMORY)) {
- printk("failed!\n");
- } else {
- printk("succeeded.\n");
- }
- }
-
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,140)
- if ( is_prep ) {
- if (io_port >= 0x10000000) {
- printk("ncr53c8xx: reallocating io_port (Wacky IBM)");
- io_port = (io_port & 0x00FFFFFF) | 0x01000000;
- pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, io_port);
- }
- if (base >= 0x10000000) {
- printk("ncr53c8xx: reallocating base (Wacky IBM)");
- base = (base & 0x00FFFFFF) | 0x01000000;
- pci_write_config_dword(pdev, PCI_BASE_ADDRESS_1, base);
- }
- if (base_2 >= 0x10000000) {
- printk("ncr53c8xx: reallocating base2 (Wacky IBM)");
- base_2 = (base_2 & 0x00FFFFFF) | 0x01000000;
- pci_write_config_dword(pdev, PCI_BASE_ADDRESS_2, base_2);
- }
- }
-#endif
-#endif /* __powerpc__ */
-
-#ifdef __sparc__
- /*
- * Severall fix-ups for sparc.
- *
- * Should not be performed by the driver, but how can OBP know
- * each and every PCI card, if they don't use Fcode?
- */
-
- base = __pa(base);
- base_2 = __pa(base_2);
-
- if (!(command & PCI_COMMAND_MASTER)) {
- if (initverbose >= 2)
- printk("ncr53c8xx: setting PCI_COMMAND_MASTER bit (fixup)\n");
- command |= PCI_COMMAND_MASTER;
- pci_write_config_word(pdev, PCI_COMMAND, command);
- pci_read_config_word(pdev, PCI_COMMAND, &command);
- }
-
- if ((chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) {
- if (initverbose >= 2)
- printk("ncr53c8xx: setting PCI_COMMAND_INVALIDATE bit (fixup)\n");
- command |= PCI_COMMAND_INVALIDATE;
- pci_write_config_word(pdev, PCI_COMMAND, command);
- pci_read_config_word(pdev, PCI_COMMAND, &command);
- }
-
- if ((chip->features & FE_CLSE) && !cache_line_size) {
- /* PCI_CACHE_LINE_SIZE value is in 32-bit words. */
- cache_line_size = 64 / sizeof(u_int32);
- if (initverbose >= 2)
- printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n", cache_line_size);
- pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, cache_line_size);
- pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);
- }
-
- if (!latency_timer) {
- latency_timer = 128;
- if (initverbose >= 2)
- printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fixup)\n", latency_timer);
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, latency_timer);
- pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer);
- }
-#endif /* __sparc__ */
-
- /*
- * Check availability of IO space, memory space and master capability.
- */
- if (command & PCI_COMMAND_IO)
- io_port &= PCI_BASE_ADDRESS_IO_MASK;
- else
- io_port = 0;
-
- if (command & PCI_COMMAND_MEMORY)
- base &= PCI_BASE_ADDRESS_MEM_MASK;
- else
- base = 0;
-
- if (!io_port && !base) {
- printk("ncr53c8xx: not initializing, both I/O and memory mappings disabled\n");
- return -1;
- }
-
- base_2 &= PCI_BASE_ADDRESS_MEM_MASK;
-
- if (io_port && check_region (io_port, 128)) {
-#ifdef __sparc__
- printk("ncr53c8xx: IO region 0x%lx to 0x%lx is in use\n",
- io_port, (io_port + 127));
-#else
- printk("ncr53c8xx: IO region 0x%x to 0x%x is in use\n",
- (int) io_port, (int) (io_port + 127));
-#endif
- return -1;
- }
-
- if (!(command & PCI_COMMAND_MASTER)) {
- printk("ncr53c8xx: not initializing, BUS MASTERING was disabled\n");
- return -1;
- }
-
- /*
- * Fix some features according to driver setup.
- */
- if (!(driver_setup.special_features & 1))
- chip->features &= ~FE_SPECIAL_SET;
- else {
- if (driver_setup.special_features & 2)
- chip->features &= ~FE_WRIE;
- }
- if (driver_setup.ultra_scsi < 2 && (chip->features & FE_ULTRA2)) {
- chip->features |= FE_ULTRA;
- chip->features &= ~FE_ULTRA2;
- }
- if (driver_setup.ultra_scsi < 1)
- chip->features &= ~FE_ULTRA;
- if (!driver_setup.max_wide)
- chip->features &= ~FE_WIDE;
-
-
-#ifdef SCSI_NCR_PCI_FIX_UP_SUPPORT
-
- /*
- * Try to fix up PCI config according to wished features.
- */
-#if defined(__i386__) && !defined(MODULE)
- if ((driver_setup.pci_fix_up & 1) &&
- (chip->features & FE_CLSE) && cache_line_size == 0) {
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,75)
- extern char x86;
- switch(x86) {
-#else
- switch(boot_cpu_data.x86) {
-#endif
- case 4: cache_line_size = 4; break;
- case 6:
- case 5: cache_line_size = 8; break;
- }
- if (cache_line_size)
- (void) pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, cache_line_size);
- if (initverbose)
- printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fix-up).\n", cache_line_size);
- }
-
- if ((driver_setup.pci_fix_up & 2) && cache_line_size &&
- (chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) {
- command |= PCI_COMMAND_INVALIDATE;
- (void) pci_write_config_word(pdev, PCI_COMMAND, command);
- if (initverbose)
- printk("ncr53c8xx: setting PCI_COMMAND_INVALIDATE bit (fix-up).\n");
- }
-#endif
- /*
- * Fix up for old chips that support READ LINE but not CACHE LINE SIZE.
- * - If CACHE LINE SIZE is unknown, set burst max to 32 bytes = 8 dwords
- * and donnot enable READ LINE.
- * - Otherwise set it to the CACHE LINE SIZE (power of 2 assumed).
- */
-
- if (!(chip->features & FE_CLSE)) {
- int burst_max = chip->burst_max;
- if (cache_line_size == 0) {
- chip->features &= ~FE_ERL;
- if (burst_max > 3)
- burst_max = 3;
- }
- else {
- while (cache_line_size < (1 << burst_max))
- --burst_max;
- }
- chip->burst_max = burst_max;
- }
-
- /*
- * Tune PCI LATENCY TIMER according to burst max length transfer.
- * (latency timer >= burst length + 6, we add 10 to be quite sure)
- * If current value is zero, the device has probably been configured
- * for no bursting due to some broken hardware.
- */
-
- if (latency_timer == 0 && chip->burst_max)
- printk("ncr53c8xx: PCI_LATENCY_TIMER=0, bursting should'nt be allowed.\n");
-
- if ((driver_setup.pci_fix_up & 4) && chip->burst_max) {
- uchar lt = (1 << chip->burst_max) + 6 + 10;
- if (latency_timer < lt) {
- latency_timer = lt;
- if (initverbose)
- printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fix-up).\n", latency_timer);
- (void) pci_write_config_byte(pdev, PCI_LATENCY_TIMER, latency_timer);
- }
- }
+ f2 = ncrgetfreq (np, 11);
- /*
- * Fix up for recent chips that support CACHE LINE SIZE.
- * If PCI config space is not OK, remove features that shall not be
- * used by the chip. No need to trigger possible chip bugs.
- */
+ if (bootverbose)
+ printk ("%s: NCR clock is %uKHz, %uKHz\n", ncr_name(np), f1, f2);
- if ((chip->features & FE_CLSE) && cache_line_size == 0) {
- chip->features &= ~FE_CACHE_SET;
- printk("ncr53c8xx: PCI_CACHE_LINE_SIZE not set, features based on CACHE LINE SIZE not used.\n");
- }
+ if (f1 > f2) f1 = f2; /* trust lower result */
- if ((chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) {
- chip->features &= ~FE_WRIE;
- printk("ncr53c8xx: PCI_COMMAND_INVALIDATE not set, WRITE AND INVALIDATE not used\n");
- }
+ if (f1 < 45000) f1 = 40000;
+ else if (f1 < 55000) f1 = 50000;
+ else f1 = 80000;
-#endif /* SCSI_NCR_PCI_FIX_UP_SUPPORT */
+ if (f1 < 80000 && mult > 1) {
+ if (bootverbose >= 2)
+ printk ("%s: clock multiplier assumed\n", ncr_name(np));
+ np->multiplier = mult;
+ }
+ } else {
+ if ((scntl3 & 7) == 3) f1 = 40000;
+ else if ((scntl3 & 7) == 5) f1 = 80000;
+ else f1 = 160000;
- /* initialise ncr_device structure with items required by ncr_attach */
- device->slot.bus = PciBusNumber(pdev);
- device->slot.device_fn = PciDeviceFn(pdev);
- device->slot.base = base;
- device->slot.base_2 = base_2;
- device->slot.io_port = io_port;
- device->slot.irq = irq;
- device->attach_done = 0;
+ f1 /= np->multiplier;
+ }
- return 0;
+ /*
+ ** Compute controller synchronous parameters.
+ */
+ f1 *= np->multiplier;
+ np->clock_khz = f1;
}
+/*===================== LINUX ENTRY POINTS SECTION ==========================*/
+
/*
** Linux select queue depths function
*/
-#define DEF_DEPTH (driver_setup.default_tags)
-#define ALL_TARGETS -2
-#define NO_TARGET -1
-#define ALL_LUNS -2
-#define NO_LUN -1
-
-static int device_queue_depth(ncb_p np, int target, int lun)
-{
- int c, h, t, u, v;
- char *p = driver_setup.tag_ctrl;
- char *ep;
-
- h = -1;
- t = NO_TARGET;
- u = NO_LUN;
- while ((c = *p++) != 0) {
- v = simple_strtoul(p, &ep, 0);
- switch(c) {
- case '/':
- ++h;
- t = ALL_TARGETS;
- u = ALL_LUNS;
- break;
- case 't':
- if (t != target)
- t = (target == v) ? v : NO_TARGET;
- u = ALL_LUNS;
- break;
- case 'u':
- if (u != lun)
- u = (lun == v) ? v : NO_LUN;
- break;
- case 'q':
- if (h == np->unit &&
- (t == ALL_TARGETS || t == target) &&
- (u == ALL_LUNS || u == lun))
- return v;
- break;
- case '-':
- t = ALL_TARGETS;
- u = ALL_LUNS;
- break;
- default:
- break;
- }
- p = ep;
- }
- return DEF_DEPTH;
-}
-
static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_device *devlist)
{
struct scsi_device *device;
@@ -10081,7 +8406,7 @@
** Use at least 2.
** Donnot use more than our maximum.
*/
- numtags = device_queue_depth(np, device->id, device->lun);
+ numtags = device_queue_depth(np->unit, device->id, device->lun);
if (numtags > tp->usrtags)
numtags = tp->usrtags;
if (!device->tagged_supported)
@@ -10111,14 +8436,6 @@
}
/*
-** Linux entry point for info() function
-*/
-const char *ncr53c8xx_info (struct Scsi_Host *host)
-{
- return SCSI_NCR_DRIVER_NAME;
-}
-
-/*
** Linux entry point of queuecommand() function
*/
@@ -10134,6 +8451,10 @@
cmd->scsi_done = done;
cmd->host_scribble = NULL;
+#ifdef SCSI_NCR_DYNAMIC_DMA_MAPPING
+ cmd->__data_mapped = 0;
+ cmd->__data_mapping = 0;
+#endif
NCR_LOCK_NCB(np, flags);
@@ -10150,8 +8471,10 @@
NCR_UNLOCK_NCB(np, flags);
- if (sts != DID_OK)
+ if (sts != DID_OK) {
+ unmap_scsi_data(np, cmd);
done(cmd);
+ }
return sts;
}
@@ -10627,50 +8950,8 @@
#endif /* SCSI_NCR_USER_COMMAND_SUPPORT */
-#ifdef SCSI_NCR_USER_INFO_SUPPORT
-
-struct info_str
-{
- char *buffer;
- int length;
- int offset;
- int pos;
-};
-
-static void copy_mem_info(struct info_str *info, char *data, int len)
-{
- if (info->pos + len > info->length)
- len = info->length - info->pos;
-
- if (info->pos + len < info->offset) {
- info->pos += len;
- return;
- }
- if (info->pos < info->offset) {
- data += (info->offset - info->pos);
- len -= (info->offset - info->pos);
- }
-
- if (len > 0) {
- memcpy(info->buffer + info->pos, data, len);
- info->pos += len;
- }
-}
-
-static int copy_info(struct info_str *info, char *fmt, ...)
-{
- va_list args;
- char buf[81];
- int len;
-
- va_start(args, fmt);
- len = vsprintf(buf, fmt, args);
- va_end(args);
-
- copy_mem_info(info, buf, len);
- return len;
-}
+#ifdef SCSI_NCR_USER_INFO_SUPPORT
/*
** Copy formatted profile information into the input buffer.
*/
@@ -10778,7 +9059,6 @@
return retv;
}
-
/*=========================================================================
** End of proc file system stuff
**=========================================================================
@@ -10786,431 +9066,104 @@
#endif
-#ifdef SCSI_NCR_NVRAM_SUPPORT
-
-/* ---------------------------------------------------------------------
+/*==========================================================
**
-** Try reading Symbios format nvram
+** /proc directory entry.
**
-** ---------------------------------------------------------------------
+**==========================================================
+*/
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
+static struct proc_dir_entry proc_scsi_ncr53c8xx = {
+ PROC_SCSI_NCR53C8XX, 9, NAME53C8XX,
+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+#endif
+
+/*==========================================================
**
-** GPOI0 - data in/data out
-** GPIO1 - clock
+** Boot command line.
**
-** return 0 if NVRAM data OK, 1 if NVRAM data not OK
-** ---------------------------------------------------------------------
-*/
-
-#define SET_BIT 0
-#define CLR_BIT 1
-#define SET_CLK 2
-#define CLR_CLK 3
-
-static u_short nvram_read_data(ncr_slot *np, u_char *data, int len, u_char *gpreg, u_char *gpcntl);
-static void nvram_start(ncr_slot *np, u_char *gpreg);
-static void nvram_write_byte(ncr_slot *np, u_char *ack_data, u_char write_data, u_char *gpreg, u_char *gpcntl);
-static void nvram_read_byte(ncr_slot *np, u_char *read_data, u_char ack_data, u_char *gpreg, u_char *gpcntl);
-static void nvram_readAck(ncr_slot *np, u_char *read_bit, u_char *gpreg, u_char *gpcntl);
-static void nvram_writeAck(ncr_slot *np, u_char write_bit, u_char *gpreg, u_char *gpcntl);
-static void nvram_doBit(ncr_slot *np, u_char *read_bit, u_char write_bit, u_char *gpreg);
-static void nvram_stop(ncr_slot *np, u_char *gpreg);
-static void nvram_setBit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode);
-
-static int __init ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram)
-{
- static u_char Symbios_trailer[6] = {0xfe, 0xfe, 0, 0, 0, 0};
- u_char gpcntl, gpreg;
- u_char old_gpcntl, old_gpreg;
- u_short csum;
- u_char ack_data;
- int retv = 1;
-
- /* save current state of GPCNTL and GPREG */
- old_gpreg = INB (nc_gpreg);
- old_gpcntl = INB (nc_gpcntl);
- gpcntl = old_gpcntl & 0xfc;
-
- /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */
- OUTB (nc_gpreg, old_gpreg);
- OUTB (nc_gpcntl, gpcntl);
-
- /* this is to set NVRAM into a known state with GPIO0/1 both low */
- gpreg = old_gpreg;
- nvram_setBit(np, 0, &gpreg, CLR_CLK);
- nvram_setBit(np, 0, &gpreg, CLR_BIT);
-
- /* now set NVRAM inactive with GPIO0/1 both high */
- nvram_stop(np, &gpreg);
-
- /* activate NVRAM */
- nvram_start(np, &gpreg);
-
- /* write device code and random address MSB */
- nvram_write_byte(np, &ack_data,
- 0xa0 | ((SYMBIOS_NVRAM_ADDRESS >> 7) & 0x0e), &gpreg, &gpcntl);
- if (ack_data & 0x01)
- goto out;
-
- /* write random address LSB */
- nvram_write_byte(np, &ack_data,
- (SYMBIOS_NVRAM_ADDRESS & 0x7f) << 1, &gpreg, &gpcntl);
- if (ack_data & 0x01)
- goto out;
-
- /* regenerate START state to set up for reading */
- nvram_start(np, &gpreg);
-
- /* rewrite device code and address MSB with read bit set (lsb = 0x01) */
- nvram_write_byte(np, &ack_data,
- 0xa1 | ((SYMBIOS_NVRAM_ADDRESS >> 7) & 0x0e), &gpreg, &gpcntl);
- if (ack_data & 0x01)
- goto out;
-
- /* now set up GPIO0 for inputting data */
- gpcntl |= 0x01;
- OUTB (nc_gpcntl, gpcntl);
-
- /* input all active data - only part of total NVRAM */
- csum = nvram_read_data(np,
- (u_char *) nvram, sizeof(*nvram), &gpreg, &gpcntl);
-
- /* finally put NVRAM back in inactive mode */
- gpcntl &= 0xfe;
- OUTB (nc_gpcntl, gpcntl);
- nvram_stop(np, &gpreg);
-
-#ifdef SCSI_NCR_DEBUG_NVRAM
-printk("ncr53c8xx: NvRAM type=%x trailer=%x %x %x %x %x %x byte_count=%d/%d checksum=%x/%x\n",
- nvram->type,
- nvram->trailer[0], nvram->trailer[1], nvram->trailer[2],
- nvram->trailer[3], nvram->trailer[4], nvram->trailer[5],
- nvram->byte_count, sizeof(*nvram) - 12,
- nvram->checksum, csum);
+**==========================================================
+*/
+#ifdef MODULE
+char *ncr53c8xx = 0; /* command line passed by insmod */
+# if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
+MODULE_PARM(ncr53c8xx, "s");
+# endif
#endif
- /* check valid NVRAM signature, verify byte count and checksum */
- if (nvram->type == 0 &&
- !memcmp(nvram->trailer, Symbios_trailer, 6) &&
- nvram->byte_count == sizeof(*nvram) - 12 &&
- csum == nvram->checksum)
- retv = 0;
-out:
- /* return GPIO0/1 to original states after having accessed NVRAM */
- OUTB (nc_gpcntl, old_gpcntl);
- OUTB (nc_gpreg, old_gpreg);
-
- return retv;
-}
-
-/*
- * Read Symbios NvRAM data and compute checksum.
- */
-static u_short __init
-nvram_read_data(ncr_slot *np, u_char *data, int len, u_char *gpreg, u_char *gpcntl)
-{
- int x;
- u_short csum;
-
- for (x = 0; x < len; x++)
- nvram_read_byte(np, &data[x], (x == (len - 1)), gpreg, gpcntl);
-
- for (x = 6, csum = 0; x < len - 6; x++)
- csum += data[x];
-
- return csum;
-}
-
-/*
- * Send START condition to NVRAM to wake it up.
- */
-static void __init nvram_start(ncr_slot *np, u_char *gpreg)
-{
- nvram_setBit(np, 1, gpreg, SET_BIT);
- nvram_setBit(np, 0, gpreg, SET_CLK);
- nvram_setBit(np, 0, gpreg, CLR_BIT);
- nvram_setBit(np, 0, gpreg, CLR_CLK);
-}
-
-/*
- * WRITE a byte to the NVRAM and then get an ACK to see it was accepted OK,
- * GPIO0 must already be set as an output
- */
-static void __init
-nvram_write_byte(ncr_slot *np, u_char *ack_data, u_char write_data, u_char *gpreg, u_char *gpcntl)
-{
- int x;
-
- for (x = 0; x < 8; x++)
- nvram_doBit(np, 0, (write_data >> (7 - x)) & 0x01, gpreg);
-
- nvram_readAck(np, ack_data, gpreg, gpcntl);
-}
-
-/*
- * READ a byte from the NVRAM and then send an ACK to say we have got it,
- * GPIO0 must already be set as an input
- */
-static void __init
-nvram_read_byte(ncr_slot *np, u_char *read_data, u_char ack_data, u_char *gpreg, u_char *gpcntl)
-{
- int x;
- u_char read_bit;
-
- *read_data = 0;
- for (x = 0; x < 8; x++) {
- nvram_doBit(np, &read_bit, 1, gpreg);
- *read_data |= ((read_bit & 0x01) << (7 - x));
- }
-
- nvram_writeAck(np, ack_data, gpreg, gpcntl);
-}
-
-/*
- * Output an ACK to the NVRAM after reading,
- * change GPIO0 to output and when done back to an input
- */
-static void __init
-nvram_writeAck(ncr_slot *np, u_char write_bit, u_char *gpreg, u_char *gpcntl)
-{
- OUTB (nc_gpcntl, *gpcntl & 0xfe);
- nvram_doBit(np, 0, write_bit, gpreg);
- OUTB (nc_gpcntl, *gpcntl);
-}
-
-/*
- * Input an ACK from NVRAM after writing,
- * change GPIO0 to input and when done back to an output
- */
-static void __init
-nvram_readAck(ncr_slot *np, u_char *read_bit, u_char *gpreg, u_char *gpcntl)
-{
- OUTB (nc_gpcntl, *gpcntl | 0x01);
- nvram_doBit(np, read_bit, 1, gpreg);
- OUTB (nc_gpcntl, *gpcntl);
-}
-
-/*
- * Read or write a bit to the NVRAM,
- * read if GPIO0 input else write if GPIO0 output
- */
-static void __init nvram_doBit(ncr_slot *np, u_char *read_bit, u_char write_bit, u_char *gpreg)
-{
- nvram_setBit(np, write_bit, gpreg, SET_BIT);
- nvram_setBit(np, 0, gpreg, SET_CLK);
- if (read_bit)
- *read_bit = INB (nc_gpreg);
- nvram_setBit(np, 0, gpreg, CLR_CLK);
- nvram_setBit(np, 0, gpreg, CLR_BIT);
-}
-
-/*
- * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZzzzz!!
- */
-static void __init nvram_stop(ncr_slot *np, u_char *gpreg)
-{
- nvram_setBit(np, 0, gpreg, SET_CLK);
- nvram_setBit(np, 1, gpreg, SET_BIT);
-}
-
-/*
- * Set/clear data/clock bit in GPIO0
- */
-static void __init
-nvram_setBit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode)
+int __init ncr53c8xx_setup(char *str)
{
- UDELAY (5);
- switch (bit_mode){
- case SET_BIT:
- *gpreg |= write_bit;
- break;
- case CLR_BIT:
- *gpreg &= 0xfe;
- break;
- case SET_CLK:
- *gpreg |= 0x02;
- break;
- case CLR_CLK:
- *gpreg &= 0xfd;
- break;
-
- }
- OUTB (nc_gpreg, *gpreg);
- UDELAY (5);
+ return sym53c8xx__setup(str);
}
-#undef SET_BIT 0
-#undef CLR_BIT 1
-#undef SET_CLK 2
-#undef CLR_CLK 3
-
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13)
+#ifndef MODULE
+__setup("ncr53c8xx=", ncr53c8xx_setup);
+#endif
+#endif
-/* ---------------------------------------------------------------------
-**
-** Try reading Tekram format nvram
-**
-** ---------------------------------------------------------------------
+/*===================================================================
**
-** GPOI0 - data in
-** GPIO1 - data out
-** GPIO2 - clock
-** GPIO4 - chip select
+** SYM53C8XX supported device list
**
-** return 0 if NVRAM data OK, 1 if NVRAM data not OK
-** ---------------------------------------------------------------------
+**===================================================================
*/
-static u_short Tnvram_read_data(ncr_slot *np, u_short *data, int len, u_char *gpreg);
-static void Tnvram_Send_Command(ncr_slot *np, u_short write_data, u_char *read_bit, u_char *gpreg);
-static void Tnvram_Read_Word(ncr_slot *np, u_short *nvram_data, u_char *gpreg);
-static void Tnvram_Read_Bit(ncr_slot *np, u_char *read_bit, u_char *gpreg);
-static void Tnvram_Write_Bit(ncr_slot *np, u_char write_bit, u_char *gpreg);
-static void Tnvram_Stop(ncr_slot *np, u_char *gpreg);
-static void Tnvram_Clk(ncr_slot *np, u_char *gpreg);
-
-static int __init ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram *nvram)
-{
- u_char gpcntl, gpreg;
- u_char old_gpcntl, old_gpreg;
- u_short csum;
-
- /* save current state of GPCNTL and GPREG */
- old_gpreg = INB (nc_gpreg);
- old_gpcntl = INB (nc_gpcntl);
-
- /* set up GPREG & GPCNTL to set GPIO0/1/2/4 in to known state, 0 in,
- 1/2/4 out */
- gpreg = old_gpreg & 0xe9;
- OUTB (nc_gpreg, gpreg);
- gpcntl = (old_gpcntl & 0xe9) | 0x09;
- OUTB (nc_gpcntl, gpcntl);
-
- /* input all of NVRAM, 64 words */
- csum = Tnvram_read_data(np, (u_short *) nvram,
- sizeof(*nvram) / sizeof(short), &gpreg);
-
- /* return GPIO0/1/2/4 to original states after having accessed NVRAM */
- OUTB (nc_gpcntl, old_gpcntl);
- OUTB (nc_gpreg, old_gpreg);
-
- /* check data valid */
- if (csum != 0x1234)
- return 1;
-
- return 0;
-}
-
-/*
- * Read Tekram NvRAM data and compute checksum.
- */
-static u_short __init
-Tnvram_read_data(ncr_slot *np, u_short *data, int len, u_char *gpreg)
-{
- u_char read_bit;
- u_short csum;
- int x;
-
- for (x = 0, csum = 0; x < len; x++) {
-
- /* output read command and address */
- Tnvram_Send_Command(np, 0x180 | x, &read_bit, gpreg);
- if (read_bit & 0x01)
- return 0; /* Force bad checksum */
-
- Tnvram_Read_Word(np, &data[x], gpreg);
- csum += data[x];
-
- Tnvram_Stop(np, gpreg);
- }
-
- return csum;
-}
-
-/*
- * Send read command and address to NVRAM
- */
-static void __init Tnvram_Send_Command(ncr_slot *np, u_short write_data, u_char *read_bit, u_char *gpreg)
-{
- int x;
-
- /* send 9 bits, start bit (1), command (2), address (6) */
- for (x = 0; x < 9; x++)
- Tnvram_Write_Bit(np, (u_char) (write_data >> (8 - x)), gpreg);
-
- *read_bit = INB (nc_gpreg);
-}
-
-/*
- * READ a byte from the NVRAM
- */
-static void __init Tnvram_Read_Word(ncr_slot *np, u_short *nvram_data, u_char *gpreg)
-{
- int x;
- u_char read_bit;
-
- *nvram_data = 0;
- for (x = 0; x < 16; x++) {
- Tnvram_Read_Bit(np, &read_bit, gpreg);
-
- if (read_bit & 0x01)
- *nvram_data |= (0x01 << (15 - x));
- else
- *nvram_data &= ~(0x01 << (15 - x));
- }
-}
-
-/*
- * Read bit from NVRAM
- */
-static void __init
-Tnvram_Read_Bit(ncr_slot *np, u_char *read_bit, u_char *gpreg)
-{
- UDELAY (2);
- Tnvram_Clk(np, gpreg);
- *read_bit = INB (nc_gpreg);
-}
+static u_short ncr_chip_ids[] __initdata = {
+ PCI_DEVICE_ID_NCR_53C810,
+ PCI_DEVICE_ID_NCR_53C815,
+ PCI_DEVICE_ID_NCR_53C820,
+ PCI_DEVICE_ID_NCR_53C825,
+ PCI_DEVICE_ID_NCR_53C860,
+ PCI_DEVICE_ID_NCR_53C875,
+ PCI_DEVICE_ID_NCR_53C875J,
+ PCI_DEVICE_ID_NCR_53C885,
+ PCI_DEVICE_ID_NCR_53C895,
+ PCI_DEVICE_ID_NCR_53C896,
+ PCI_DEVICE_ID_NCR_53C895A,
+ PCI_DEVICE_ID_NCR_53C1510D
+};
-/*
- * Write bit to GPIO0
- */
-static void __init
-Tnvram_Write_Bit(ncr_slot *np, u_char write_bit, u_char *gpreg)
+/*==========================================================
+**
+** Chip detection entry point.
+**
+**==========================================================
+*/
+int __init ncr53c8xx_detect(Scsi_Host_Template *tpnt)
{
- if (write_bit & 0x01)
- *gpreg |= 0x02;
- else
- *gpreg &= 0xfd;
-
- *gpreg |= 0x10;
-
- OUTB (nc_gpreg, *gpreg);
- UDELAY (2);
-
- Tnvram_Clk(np, gpreg);
-}
+ /*
+ ** Initialize driver general stuff.
+ */
+#ifdef SCSI_NCR_PROC_INFO_SUPPORT
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
+ tpnt->proc_dir = &proc_scsi_ncr53c8xx;
+#else
+ tpnt->proc_name = NAME53C8XX;
+#endif
+ tpnt->proc_info = ncr53c8xx_proc_info;
+#endif
-/*
- * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZZzzz!!
- */
-static void __init Tnvram_Stop(ncr_slot *np, u_char *gpreg)
-{
- *gpreg &= 0xef;
- OUTB (nc_gpreg, *gpreg);
- UDELAY (2);
+#if defined(SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT) && defined(MODULE)
+if (ncr53c8xx)
+ ncr53c8xx_setup(ncr53c8xx);
+#endif
- Tnvram_Clk(np, gpreg);
+ return sym53c8xx__detect(tpnt, ncr_chip_ids,
+ sizeof(ncr_chip_ids)/sizeof(ncr_chip_ids[0]));
}
-/*
- * Pulse clock bit in GPIO0
- */
-static void __init Tnvram_Clk(ncr_slot *np, u_char *gpreg)
+/*==========================================================
+**
+** Entry point for info() function
+**
+**==========================================================
+*/
+const char *ncr53c8xx_info (struct Scsi_Host *host)
{
- OUTB (nc_gpreg, *gpreg | 0x04);
- UDELAY (2);
- OUTB (nc_gpreg, *gpreg);
+ return SCSI_NCR_DRIVER_NAME;
}
-
-#endif /* SCSI_NCR_NVRAM_SUPPORT */
/*
** Module stuff
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)