X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fgdth.c;h=c900eddbce205a67d97240e99eff0314cd1203a4;hb=refs%2Fheads%2Fvserver;hp=71e66844c3fdd725700fe81d028102fa7c77f6dd;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 71e66844c..c900eddbc 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4,9 +4,9 @@ * Intel Corporation: Storage RAID Controllers * * * * gdth.c * - * Copyright (C) 1995-03 ICP vortex GmbH, Achim Leubner * - * Copyright (C) 2002-03 Intel Corporation * - * Copyright (C) 2003 Adaptec Inc. * + * Copyright (C) 1995-06 ICP vortex GmbH, Achim Leubner * + * Copyright (C) 2002-04 Intel Corporation * + * Copyright (C) 2003-06 Adaptec Inc. * * * * * * Additions/Fixes: * @@ -27,9 +27,47 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Tested with Linux 1.2.13, ..., 2.2.20, ..., 2.4.22 * + * Linux kernel 2.4.x, 2.6.x supported * * * * $Log: gdth.c,v $ + * Revision 1.74 2006/04/10 13:44:47 achim + * Community changes for 2.6.x + * Kernel 2.2.x no longer supported + * scsi_request interface removed, thanks to Christoph Hellwig + * + * Revision 1.73 2004/03/31 13:33:03 achim + * Special command 0xfd implemented to detect 64-bit DMA support + * + * Revision 1.72 2004/03/17 08:56:04 achim + * 64-bit DMA only enabled if FW >= x.43 + * + * Revision 1.71 2004/03/05 15:51:29 achim + * Screen service: separate message buffer, bugfixes + * + * Revision 1.70 2004/02/27 12:19:07 achim + * Bugfix: Reset bit in config (0xfe) call removed + * + * Revision 1.69 2004/02/20 09:50:24 achim + * Compatibility changes for kernels < 2.4.20 + * Bugfix screen service command size + * pci_set_dma_mask() error handling added + * + * Revision 1.68 2004/02/19 15:46:54 achim + * 64-bit DMA bugfixes + * Drive size bugfix for drives > 1TB + * + * Revision 1.67 2004/01/14 13:11:57 achim + * Tool access over /proc no longer supported + * Bugfixes IOCTLs + * + * Revision 1.66 2003/12/19 15:04:06 achim + * Bugfixes support for drives > 2TB + * + * Revision 1.65 2003/12/15 11:21:56 achim + * 64-bit DMA support added + * Support for drives > 2 TB implemented + * Kernels 2.2.x, 2.4.x, 2.6.x supported + * * Revision 1.64 2003/09/17 08:30:26 achim * EISA/ISA controller scan disabled * Command line switch probe_eisa_isa added @@ -295,14 +333,16 @@ * hdr_channel:x x - number of virtual bus for host drives * shared_access:Y disable driver reserve/release protocol to * access a shared resource from several nodes, - * appropiate controller firmware required + * appropriate controller firmware required * shared_access:N enable driver reserve/release protocol * probe_eisa_isa:Y scan for EISA/ISA controllers * probe_eisa_isa:N do not scan for EISA/ISA controllers + * force_dma32:Y use only 32 bit DMA mode + * force_dma32:N use 64 bit DMA mode, if supported * * The default values are: "gdth=disable:N,reserve_mode:1,reverse_scan:N, * max_ids:127,rescan:N,virt_ctr:N,hdr_channel:0, - * shared_access:Y,probe_eisa_isa:N". + * shared_access:Y,probe_eisa_isa:N,force_dma32:N". * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y". * * When loading the gdth driver as a module, the same options are available. @@ -313,7 +353,7 @@ * * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0 * max_ids=127 rescan=0 virt_ctr=0 hdr_channel=0 shared_access=0 - * probe_eisa_isa=0" + * probe_eisa_isa=0 force_dma32=0" * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1". */ @@ -330,9 +370,12 @@ * phase: Service/parameter/return code special command */ -/* default: activate /proc and character device IOCTL interface */ -#define GDTH_IOCTL_PROC -#define GDTH_IOCTL_CHRDEV + +/* interrupt coalescing */ +/* #define INT_COAL */ + +/* statistics */ +#define GDTH_STATISTICS #include @@ -350,38 +393,38 @@ #include #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6) +#include +#else +#define DMA_32BIT_MASK 0x00000000ffffffffULL +#define DMA_64BIT_MASK 0xffffffffffffffffULL +#endif + #ifdef GDTH_RTC #include #endif -#if LINUX_VERSION_CODE >= 0x020100 #include -#else -#include -#endif #include #include #include #include -#if LINUX_VERSION_CODE >= 0x020322 #include -#elif LINUX_VERSION_CODE >= 0x02015F -#include -#endif - +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include - -#include "scsi.h" -#include "hosts.h" -#if LINUX_VERSION_CODE < 0x020503 +#else +#include #include "sd.h" #endif +#include "scsi.h" +#include +#include "gdth_kcompat.h" #include "gdth.h" static void gdth_delay(int milliseconds); -static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs); -static irqreturn_t gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs); +static irqreturn_t gdth_interrupt(int irq, void *dev_id); static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp); static int gdth_async_event(int hanum); static void gdth_log_event(gdth_evt_data *dvr, char *buffer); @@ -419,31 +462,21 @@ static int gdth_get_cmd_index(int hanum); static void gdth_release_event(int hanum); static int gdth_wait(int hanum,int index,ulong32 time); static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, - ulong32 p2,ulong32 p3); + ulong64 p2,ulong64 p3); static int gdth_search_drives(int hanum); static int gdth_analyse_hdrive(int hanum, ushort hdrive); -static void *gdth_mmap(ulong paddr, ulong size); -static void gdth_munmap(void *addr); - static const char *gdth_ctr_name(int hanum); -#ifdef GDTH_IOCTL_CHRDEV static int gdth_open(struct inode *inode, struct file *filep); static int gdth_close(struct inode *inode, struct file *filep); static int gdth_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); -#endif -#if LINUX_VERSION_CODE >= 0x010300 static void gdth_flush(int hanum); -#if LINUX_VERSION_CODE >= 0x020100 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf); -#else -static int halt_called = FALSE; -void gdth_halt(void); -#endif -#endif +static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)); +static void gdth_scsi_done(struct scsi_cmnd *scp); #ifdef DEBUG_GDTH static unchar DebugState = DEBUG_GDTH; @@ -528,13 +561,16 @@ static int ser_printk(const char *fmt, ...) #ifdef GDTH_STATISTICS static ulong32 max_rq=0, max_index=0, max_sg=0; +#ifdef INT_COAL +static ulong32 max_int_coal=0; +#endif static ulong32 act_ints=0, act_ios=0, act_stats=0, act_rq=0; static struct timer_list gdth_timer; #endif #define PTR2USHORT(a) (ushort)(ulong)(a) -#define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b) -#define INDEX_OK(i,t) ((i)b) +#define INDEX_OK(i,t) ((i)hostdata)) #define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext) @@ -542,80 +578,12 @@ static struct timer_list gdth_timer; #define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b)) -#if LINUX_VERSION_CODE < 0x010300 -static void *gdth_mmap(ulong paddr, ulong size) -{ - if (paddr >= high_memory) - return NULL; - else - return (void *)paddr; -} -static void gdth_munmap(void *addr) -{ -} -inline ulong32 virt_to_phys(volatile void *addr) -{ - return (ulong32)addr; -} -inline void *phys_to_virt(ulong32 addr) -{ - return (void *)addr; -} -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt -#define gdth_readb(addr) (*(volatile unchar *)(addr)) -#define gdth_readw(addr) (*(volatile ushort *)(addr)) -#define gdth_readl(addr) (*(volatile ulong32 *)(addr)) -#define gdth_writeb(b,addr) (*(volatile unchar *)(addr) = (b)) -#define gdth_writew(b,addr) (*(volatile ushort *)(addr) = (b)) -#define gdth_writel(b,addr) (*(volatile ulong32 *)(addr) = (b)) -#define memset_io(a,b,c) memset((void *)(a),(b),(c)) -#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) -#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) - -#define PCI_SLOT(devfn) ((devfn >> 3) & 0x1f) - -#elif LINUX_VERSION_CODE < 0x020100 -static int remapped = FALSE; -static void *gdth_mmap(ulong paddr, ulong size) -{ - if ( paddr >= high_memory) { - remapped = TRUE; - return vremap(paddr, size); - } else { - return (void *)paddr; - } -} -static void gdth_munmap(void *addr) -{ - if (remapped) - vfree(addr); - remapped = FALSE; -} -#define gdth_readb(addr) readb((ulong)(addr)) -#define gdth_readw(addr) readw((ulong)(addr)) -#define gdth_readl(addr) (ulong32)readl((ulong)(addr)) -#define gdth_writeb(b,addr) writeb((b),(ulong)(addr)) -#define gdth_writew(b,addr) writew((b),(ulong)(addr)) -#define gdth_writel(b,addr) writel((ulong32)(b),(ulong)(addr)) - -#else -static void *gdth_mmap(ulong paddr, ulong size) -{ - return ioremap(paddr, size); -} -static void gdth_munmap(void *addr) -{ - return iounmap(addr); -} -#define gdth_readb(addr) readb((ulong)(addr)) -#define gdth_readw(addr) readw((ulong)(addr)) -#define gdth_readl(addr) (ulong32)readl((ulong)(addr)) -#define gdth_writeb(b,addr) writeb((b),(ulong)(addr)) -#define gdth_writew(b,addr) writew((b),(ulong)(addr)) -#define gdth_writel(b,addr) writel((ulong32)(b),(ulong)(addr)) -#endif - +#define gdth_readb(addr) readb(addr) +#define gdth_readw(addr) readw(addr) +#define gdth_readl(addr) readl(addr) +#define gdth_writeb(b,addr) writeb((b),(addr)) +#define gdth_writew(b,addr) writew((b),(addr)) +#define gdth_writel(b,addr) writel((b),(addr)) static unchar gdth_drq_tab[4] = {5,6,7,7}; /* DRQ table */ static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */ @@ -631,9 +599,7 @@ static unchar gdth_write_through = FALSE; /* write through */ static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */ static int elastidx; static int eoldidx; -#ifdef GDTH_IOCTL_CHRDEV static int major; -#endif #define DIN 1 /* IN data direction */ #define DOU 2 /* OUT data direction */ @@ -648,8 +614,8 @@ static unchar gdth_direction_tab[0x100] = { DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, - DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, - DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, + DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN,DOU,DUN,DUN,DUN,DUN,DUN, + DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN, DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DOU,DUN,DNO,DUN,DOU,DOU, DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, @@ -658,50 +624,6 @@ static unchar gdth_direction_tab[0x100] = { DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN }; -/* __initfunc, __initdata macros */ -#if LINUX_VERSION_CODE >= 0x020322 -#define GDTH_INITFUNC(type, func) type __init func -#include -#elif LINUX_VERSION_CODE >= 0x020126 -#define GDTH_INITFUNC(type, func) __initfunc(type func) -#include -#else -#define GDTH_INITFUNC(type, func) type func -#define __initdata -#define __init -#endif - -#if LINUX_VERSION_CODE >= 0x020503 -#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock) -#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags) -#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags) - -#define GDTH_LOCK_SCSI_DONE(dev, flags) spin_lock_irqsave(dev->host_lock,flags) -#define GDTH_UNLOCK_SCSI_DONE(dev, flags) spin_unlock_irqrestore(dev->host_lock,flags) -#define GDTH_LOCK_SCSI_DOCMD(dev) spin_lock_irq(dev->host_lock) -#define GDTH_UNLOCK_SCSI_DOCMD(dev) spin_unlock_irq(dev->host_lock) - -#elif LINUX_VERSION_CODE >= 0x02015F -#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock) -#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags) -#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags) - -#define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags) -#define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags) -#define GDTH_LOCK_SCSI_DOCMD() spin_lock_irq(&io_request_lock) -#define GDTH_UNLOCK_SCSI_DOCMD() spin_unlock_irq(&io_request_lock) - -#else -#define GDTH_INIT_LOCK_HA(ha) do {} while (0) -#define GDTH_LOCK_HA(ha,flags) do {save_flags(flags); cli();} while (0) -#define GDTH_UNLOCK_HA(ha,flags) do {restore_flags(flags);} while (0) - -#define GDTH_LOCK_SCSI_DONE(flags) do {} while (0) -#define GDTH_UNLOCK_SCSI_DONE(flags) do {} while (0) -#define GDTH_LOCK_SCSI_DOCMD() do {} while (0) -#define GDTH_UNLOCK_SCSI_DOCMD() do {} while (0) -#endif - /* LILO and modprobe/insmod parameters */ /* IRQ list for GDT3000/3020 EISA controllers */ static int irq[MAXHA] __initdata = @@ -730,10 +652,24 @@ static int virt_ctr = 0; static int shared_access = 1; /* enable support for EISA and ISA controllers */ static int probe_eisa_isa = 0; +/* 64 bit DMA mode, support for drives > 2 TB, if force_dma32 = 0 */ +static int force_dma32 = 0; -#ifdef MODULE -#if LINUX_VERSION_CODE >= 0x02011A /* parameters for modprobe/insmod */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) +module_param_array(irq, int, NULL, 0); +module_param(disable, int, 0); +module_param(reserve_mode, int, 0); +module_param_array(reserve_list, int, NULL, 0); +module_param(reverse_scan, int, 0); +module_param(hdr_channel, int, 0); +module_param(max_ids, int, 0); +module_param(rescan, int, 0); +module_param(virt_ctr, int, 0); +module_param(shared_access, int, 0); +module_param(probe_eisa_isa, int, 0); +module_param(force_dma32, int, 0); +#else MODULE_PARM(irq, "i"); MODULE_PARM(disable, "i"); MODULE_PARM(reserve_mode, "i"); @@ -745,59 +681,123 @@ MODULE_PARM(rescan, "i"); MODULE_PARM(virt_ctr, "i"); MODULE_PARM(shared_access, "i"); MODULE_PARM(probe_eisa_isa, "i"); -MODULE_AUTHOR("Achim Leubner"); +MODULE_PARM(force_dma32, "i"); #endif -#if LINUX_VERSION_CODE >= 0x02040B +MODULE_AUTHOR("Achim Leubner"); MODULE_LICENSE("GPL"); -#endif -#endif +MODULE_VERSION(GDTH_VERSION_STR); -#ifdef GDTH_IOCTL_CHRDEV /* ioctl interface */ static struct file_operations gdth_fops = { - .ioctl = gdth_ioctl, - .open = gdth_open, - .release = gdth_close, + .ioctl = gdth_ioctl, + .open = gdth_open, + .release = gdth_close, }; -#endif -/* /proc support */ -#if LINUX_VERSION_CODE >= 0x010300 -#include -#if LINUX_VERSION_CODE < 0x020322 -struct proc_dir_entry proc_scsi_gdth = { - PROC_SCSI_GDTH, 4, "gdth", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; -#endif #include "gdth_proc.h" #include "gdth_proc.c" -#endif -#if LINUX_VERSION_CODE >= 0x020100 /* notifier block to get a notify on system shutdown/halt/reboot */ static struct notifier_block gdth_notifier = { gdth_halt, NULL, 0 }; -#endif - +static int notifier_disabled = 0; static void gdth_delay(int milliseconds) { if (milliseconds == 0) { udelay(1); } else { -#if LINUX_VERSION_CODE >= 0x020168 mdelay(milliseconds); + } +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static void gdth_scsi_done(struct scsi_cmnd *scp) +{ + TRACE2(("gdth_scsi_done()\n")); + + if (scp->request) + complete((struct completion *)scp->request); +} + +int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, + int timeout, u32 *info) +{ + Scsi_Cmnd *scp; + DECLARE_COMPLETION_ONSTACK(wait); + int rval; + + scp = kmalloc(sizeof(*scp), GFP_KERNEL); + if (!scp) + return -ENOMEM; + memset(scp, 0, sizeof(*scp)); + scp->device = sdev; + /* use request field to save the ptr. to completion struct. */ + scp->request = (struct request *)&wait; + scp->timeout_per_command = timeout*HZ; + scp->request_buffer = gdtcmd; + scp->cmd_len = 12; + memcpy(scp->cmnd, cmnd, 12); + scp->SCp.this_residual = IOCTL_PRI; /* priority */ + scp->done = gdth_scsi_done; /* some fn. test this */ + gdth_queuecommand(scp, gdth_scsi_done); + wait_for_completion(&wait); + + rval = scp->SCp.Status; + if (info) + *info = scp->SCp.Message; + kfree(scp); + return rval; +} #else - int i; - for (i = 0; i < milliseconds; ++i) - udelay(1000); +static void gdth_scsi_done(Scsi_Cmnd *scp) +{ + TRACE2(("gdth_scsi_done()\n")); + + scp->request.rq_status = RQ_SCSI_DONE; + if (scp->request.waiting) + complete(scp->request.waiting); +} + +int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, + int timeout, u32 *info) +{ + Scsi_Cmnd *scp = scsi_allocate_device(sdev, 1, FALSE); + unsigned bufflen = gdtcmd ? sizeof(gdth_cmd_str) : 0; + DECLARE_COMPLETION_ONSTACK(wait); + int rval; + + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; + scp->SCp.this_residual = IOCTL_PRI; /* priority */ + scp->request.rq_status = RQ_SCSI_BUSY; + scp->request.waiting = &wait; + scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); + wait_for_completion(&wait); + + rval = scp->SCp.Status; + if (info) + *info = scp->SCp.Message; + + scsi_release_command(scp); + return rval; +} #endif - } + +int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd, + int timeout, u32 *info) +{ + struct scsi_device *sdev = scsi_get_host_dev(shost); + int rval = __gdth_execute(sdev, gdtcmd, cmnd, timeout, info); + + scsi_free_host_dev(sdev); + return rval; } -static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs) +static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs) { *cyls = size /HEADS/SECS; if (*cyls <= MAXCYLS) { @@ -818,7 +818,7 @@ static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs) /* controller search and initialization functions */ -GDTH_INITFUNC(static int, gdth_search_eisa(ushort eisa_adr)) +static int __init gdth_search_eisa(ushort eisa_adr) { ulong32 id; @@ -836,15 +836,15 @@ GDTH_INITFUNC(static int, gdth_search_eisa(ushort eisa_adr)) } -GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr)) +static int __init gdth_search_isa(ulong32 bios_adr) { - void *addr; + void __iomem *addr; ulong32 id; TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr)); - if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) { + if ((addr = ioremap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) { id = gdth_readl(addr); - gdth_munmap(addr); + iounmap(addr); if (id == GDT2_ID) /* GDT2000 */ return 1; } @@ -852,7 +852,7 @@ GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr)) } -GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr)) +static int __init gdth_search_pci(gdth_pci_str *pcistr) { ushort device, cnt; @@ -866,6 +866,8 @@ GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr)) gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device); gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, PCI_DEVICE_ID_VORTEX_GDTNEWRX); + gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, + PCI_DEVICE_ID_VORTEX_GDTNEWRX2); gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SRC); gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, @@ -873,34 +875,26 @@ GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr)) return cnt; } -#if LINUX_VERSION_CODE >= 0x20363 /* Vortex only makes RAID controllers. * We do not really want to specify all 550 ids here, so wildcard match. */ -static struct pci_device_id gdthtable[] = { +static struct pci_device_id gdthtable[] __attribute_used__ = { {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, {0} }; MODULE_DEVICE_TABLE(pci,gdthtable); -#endif -GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, - ushort vendor, ushort device)) +static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, + ushort vendor, ushort device) { ulong base0, base1, base2; -#if LINUX_VERSION_CODE >= 0x2015C struct pci_dev *pdev; -#else - int error; - ushort idx; -#endif TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n", *cnt, vendor, device)); -#if LINUX_VERSION_CODE >= 0x20363 pdev = NULL; while ((pdev = pci_find_device(vendor, device, pdev)) != NULL) { @@ -938,112 +932,10 @@ GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, pcistr[*cnt].irq, pcistr[*cnt].dpmem)); (*cnt)++; } -#elif LINUX_VERSION_CODE >= 0x2015C - pdev = NULL; - while ((pdev = pci_find_device(vendor, device, pdev)) - != NULL) { - if (*cnt >= MAXHA) - return; - /* GDT PCI controller found, resources are already in pdev */ - pcistr[*cnt].pdev = pdev; - pcistr[*cnt].vendor_id = vendor; - pcistr[*cnt].device_id = device; - pcistr[*cnt].bus = pdev->bus->number; - pcistr[*cnt].device_fn = pdev->devfn; - pcibios_read_config_word(pcistr[*cnt].bus, pcistr[*cnt].device_fn, - PCI_SUBSYSTEM_ID, &pcistr[*cnt].subdevice_id); - pcistr[*cnt].irq = pdev->irq; - base0 = pdev->base_address[0]; - base1 = pdev->base_address[1]; - base2 = pdev->base_address[2]; - if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ - device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY) - continue; - pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; - } else { /* GDT6110, GDT6120, .. */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base2 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base1 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_IO) - continue; - pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[*cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; - } - TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", - pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn), - pcistr[*cnt].irq, pcistr[*cnt].dpmem)); - (*cnt)++; - } -#else - idx = 0; - while (!pcibios_find_device(vendor, device, idx++, - &pcistr[*cnt].bus,&pcistr[*cnt].device_fn)) { - if (*cnt >= MAXHA) - return; - /* GDT PCI ctr. found, now read resources from config space */ -#if LINUX_VERSION_CODE >= 0x010300 -#define GDTH_BASEP (int *) -#else -#define GDTH_BASEP -#endif - if ((error = pcibios_read_config_dword(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_BASE_ADDRESS_0, - GDTH_BASEP&base0)) || - (error = pcibios_read_config_dword(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_BASE_ADDRESS_1, - GDTH_BASEP&base1)) || - (error = pcibios_read_config_dword(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_BASE_ADDRESS_2, - GDTH_BASEP&base2)) || - (error = pcibios_read_config_word(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_SUBSYSTEM_ID, - &pcistr[*cnt].subdevice_id)) || - (error = pcibios_read_config_byte(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_INTERRUPT_LINE, - &pcistr[*cnt].irq))) { - printk("GDT-PCI: error %d reading configuration space", error); - continue; - } - pcistr[*cnt].vendor_id = vendor; - pcistr[*cnt].device_id = device; - if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ - device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY) - continue; - pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; - } else { /* GDT6110, GDT6120, .. */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base2 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base1 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_IO) - continue; - pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[*cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; - } - TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", - pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn), - pcistr[*cnt].irq, pcistr[*cnt].dpmem)); - (*cnt)++; - } -#endif } -GDTH_INITFUNC(static void, gdth_sort_pci(gdth_pci_str *pcistr, int cnt)) +static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt) { gdth_pci_str temp; int i, changed; @@ -1081,7 +973,7 @@ GDTH_INITFUNC(static void, gdth_sort_pci(gdth_pci_str *pcistr, int cnt)) } -GDTH_INITFUNC(static int, gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)) +static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha) { ulong32 retries,id; unchar prot_ver,eisacf,i,irq_found; @@ -1168,31 +1060,33 @@ GDTH_INITFUNC(static int, gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)) ha->type = GDT_EISA; ha->stype = id; } + + ha->dma64_support = 0; return 1; } -GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)) +static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) { - register gdt2_dpram_str *dp2_ptr; + register gdt2_dpram_str __iomem *dp2_ptr; int i; unchar irq_drq,prot_ver; ulong32 retries; TRACE(("gdth_init_isa() bios adr. %x\n",bios_adr)); - ha->brd = gdth_mmap(bios_adr, sizeof(gdt2_dpram_str)); + ha->brd = ioremap(bios_adr, sizeof(gdt2_dpram_str)); if (ha->brd == NULL) { printk("GDT-ISA: Initialization error (DPMEM remap error)\n"); return 0; } - dp2_ptr = (gdt2_dpram_str *)ha->brd; + dp2_ptr = ha->brd; gdth_writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */ /* reset interface area */ - memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u)); + memset_io(&dp2_ptr->u, 0, sizeof(dp2_ptr->u)); if (gdth_readl(&dp2_ptr->u) != 0) { - printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); + printk("GDT-ISA: Initialization error (DPMEM write error)\n"); + iounmap(ha->brd); return 0; } @@ -1227,7 +1121,7 @@ GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)) while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-ISA: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1237,7 +1131,7 @@ GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)) gdth_writeb(0xff, &dp2_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-ISA: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1259,29 +1153,28 @@ GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)) while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-ISA: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); } gdth_writeb(0, &dp2_ptr->u.ic.Status); gdth_writeb(0xff, &dp2_ptr->io.irqdel); + + ha->dma64_support = 0; return 1; } -GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) +static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) { - register gdt6_dpram_str *dp6_ptr; - register gdt6c_dpram_str *dp6c_ptr; - register gdt6m_dpram_str *dp6m_ptr; + register gdt6_dpram_str __iomem *dp6_ptr; + register gdt6c_dpram_str __iomem *dp6c_ptr; + register gdt6m_dpram_str __iomem *dp6m_ptr; ulong32 retries; unchar prot_ver; ushort command; int i, found = FALSE; -#if LINUX_VERSION_CODE < 0x2015C - int rom_addr; -#endif TRACE(("gdth_init_pci()\n")); @@ -1293,27 +1186,25 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) ha->stype = (ulong32)pcistr->device_id; ha->subdevice_id = pcistr->subdevice_id; ha->irq = pcistr->irq; -#if LINUX_VERSION_CODE >= 0x20400 ha->pdev = pcistr->pdev; -#endif if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str)); + ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } /* check and reset interface area */ - dp6_ptr = (gdt6_dpram_str *)ha->brd; + dp6_ptr = ha->brd; gdth_writel(DPMEM_MAGIC, &dp6_ptr->u); if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", pcistr->dpmem); found = FALSE; for (i = 0xC8000; i < 0xE8000; i += 0x4000) { - gdth_munmap(ha->brd); - ha->brd = gdth_mmap(i, sizeof(ushort)); + iounmap(ha->brd); + ha->brd = ioremap(i, sizeof(ushort)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1322,20 +1213,15 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) TRACE2(("init_pci_old() address 0x%x busy\n", i)); continue; } - gdth_munmap(ha->brd); -#if LINUX_VERSION_CODE >= 0x2015C + iounmap(ha->brd); pci_write_config_dword(pcistr->pdev, PCI_BASE_ADDRESS_0, i); -#else - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_BASE_ADDRESS_0, i); -#endif - ha->brd = gdth_mmap(i, sizeof(gdt6_dpram_str)); + ha->brd = ioremap(i, sizeof(gdt6_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } - dp6_ptr = (gdt6_dpram_str *)ha->brd; + dp6_ptr = ha->brd; gdth_writel(DPMEM_MAGIC, &dp6_ptr->u); if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); @@ -1345,14 +1231,14 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) } if (!found) { printk("GDT-PCI: No free address found!\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } } - memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u)); + memset_io(&dp6_ptr->u, 0, sizeof(dp6_ptr->u)); if (gdth_readl(&dp6_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1370,7 +1256,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1380,7 +1266,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) gdth_writeb(0xff, &dp6_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1390,7 +1276,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) /* special command to controller BIOS */ gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]); gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]); - gdth_writel(0x01, &dp6_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[2]); gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]); gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); gdth_writeb(0, &dp6_ptr->io.event); @@ -1399,7 +1285,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1407,26 +1293,28 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) gdth_writeb(0, &dp6_ptr->u.ic.S_Status); gdth_writeb(0xff, &dp6_ptr->io.irqdel); + ha->dma64_support = 0; + } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */ ha->plx = (gdt6c_plx_regs *)pcistr->io; TRACE2(("init_pci_new() dpmem %lx irq %d\n", pcistr->dpmem,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str)); + ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6c_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } /* check and reset interface area */ - dp6c_ptr = (gdt6c_dpram_str *)ha->brd; + dp6c_ptr = ha->brd; gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u); if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", pcistr->dpmem); found = FALSE; for (i = 0xC8000; i < 0xE8000; i += 0x4000) { - gdth_munmap(ha->brd); - ha->brd = gdth_mmap(i, sizeof(ushort)); + iounmap(ha->brd); + ha->brd = ioremap(i, sizeof(ushort)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1435,20 +1323,15 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) TRACE2(("init_pci_plx() address 0x%x busy\n", i)); continue; } - gdth_munmap(ha->brd); -#if LINUX_VERSION_CODE >= 0x2015C + iounmap(ha->brd); pci_write_config_dword(pcistr->pdev, PCI_BASE_ADDRESS_2, i); -#else - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_BASE_ADDRESS_2, i); -#endif - ha->brd = gdth_mmap(i, sizeof(gdt6c_dpram_str)); + ha->brd = ioremap(i, sizeof(gdt6c_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } - dp6c_ptr = (gdt6c_dpram_str *)ha->brd; + dp6c_ptr = ha->brd; gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u); if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); @@ -1458,14 +1341,14 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) } if (!found) { printk("GDT-PCI: No free address found!\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } } - memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u)); + memset_io(&dp6c_ptr->u, 0, sizeof(dp6c_ptr->u)); if (gdth_readl(&dp6c_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1486,7 +1369,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1495,7 +1378,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) gdth_writeb(0, &dp6c_ptr->u.ic.Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1505,7 +1388,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) /* special command to controller BIOS */ gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); - gdth_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[2]); gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); @@ -1516,23 +1399,24 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); } gdth_writeb(0, &dp6c_ptr->u.ic.S_Status); + ha->dma64_support = 0; + } else { /* MPR */ TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str)); + ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6m_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } /* manipulate config. space to enable DPMEM, start RP controller */ -#if LINUX_VERSION_CODE >= 0x20363 pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command); command |= 6; pci_write_config_word(pcistr->pdev, PCI_COMMAND, command); @@ -1543,50 +1427,23 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) gdth_delay(1); pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, pci_resource_start(pcistr->pdev, 8)); -#elif LINUX_VERSION_CODE >= 0x2015C - pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command); - command |= 6; - pci_write_config_word(pcistr->pdev, PCI_COMMAND, command); - if (pcistr->pdev->rom_address == 1UL) - pcistr->pdev->rom_address = 0UL; - i = 0xFEFF0001UL; - pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i); - gdth_delay(1); - pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, - pcistr->pdev->rom_address); -#else - pcibios_read_config_word(pcistr->bus, pcistr->device_fn, - PCI_COMMAND, &command); - command |= 6; - pcibios_write_config_word(pcistr->bus, pcistr->device_fn, - PCI_COMMAND, command); - pcibios_read_config_dword(pcistr->bus, pcistr->device_fn, - PCI_ROM_ADDRESS, &rom_addr); - if (rom_addr == 1UL) - rom_addr = 0UL; - i = 0xFEFF0001UL; - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_ROM_ADDRESS, i); - gdth_delay(1); - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_ROM_ADDRESS, rom_addr); -#endif + dp6m_ptr = ha->brd; + /* Ensure that it is safe to access the non HW portions of DPMEM. * Aditional check needed for Xscale based RAID controllers */ - while( ((int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg) ) & 3 ) + while( ((int)gdth_readb(&dp6m_ptr->i960r.sema0_reg) ) & 3 ) gdth_delay(1); /* check and reset interface area */ - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", pcistr->dpmem); found = FALSE; for (i = 0xC8000; i < 0xE8000; i += 0x4000) { - gdth_munmap(ha->brd); - ha->brd = gdth_mmap(i, sizeof(ushort)); + iounmap(ha->brd); + ha->brd = ioremap(i, sizeof(ushort)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1595,20 +1452,15 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) TRACE2(("init_pci_mpr() address 0x%x busy\n", i)); continue; } - gdth_munmap(ha->brd); -#if LINUX_VERSION_CODE >= 0x2015C + iounmap(ha->brd); pci_write_config_dword(pcistr->pdev, PCI_BASE_ADDRESS_0, i); -#else - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_BASE_ADDRESS_0, i); -#endif - ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str)); + ha->brd = ioremap(i, sizeof(gdt6m_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; + dp6m_ptr = ha->brd; gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); @@ -1618,11 +1470,11 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) } if (!found) { printk("GDT-PCI: No free address found!\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } } - memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u)); + memset_io(&dp6m_ptr->u, 0, sizeof(dp6m_ptr->u)); /* disable board interrupts, deinit services */ gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4, @@ -1639,7 +1491,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1648,7 +1500,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1658,7 +1510,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) /* special command to controller BIOS */ gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[0]); gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[1]); - gdth_writel(0x01, &dp6m_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[2]); gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[3]); gdth_writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx); gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); @@ -1667,12 +1519,32 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); + return 0; + } + gdth_delay(1); + } + gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); + + /* read FW version to detect 64-bit DMA support */ + gdth_writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx); + gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); + retries = INIT_RETRIES; + gdth_delay(20); + while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) { + if (--retries == 0) { + printk("GDT-PCI: Initialization error (DEINIT failed)\n"); + iounmap(ha->brd); return 0; } gdth_delay(1); } + prot_ver = (unchar)(gdth_readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16); gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); + if (prot_ver < 0x2b) /* FW < x.43: no 64-bit DMA support */ + ha->dma64_support = 0; + else + ha->dma64_support = 1; } return 1; @@ -1681,29 +1553,29 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) /* controller protocol functions */ -GDTH_INITFUNC(static void, gdth_enable_int(int hanum)) +static void __init gdth_enable_int(int hanum) { gdth_ha_str *ha; ulong flags; - gdt2_dpram_str *dp2_ptr; - gdt6_dpram_str *dp6_ptr; - gdt6m_dpram_str *dp6m_ptr; + gdt2_dpram_str __iomem *dp2_ptr; + gdt6_dpram_str __iomem *dp6_ptr; + gdt6m_dpram_str __iomem *dp6m_ptr; TRACE(("gdth_enable_int() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); - GDTH_LOCK_HA(ha, flags); + spin_lock_irqsave(&ha->smp_lock, flags); if (ha->type == GDT_EISA) { outb(0xff, ha->bmic + EDOORREG); outb(0xff, ha->bmic + EDENABREG); outb(0x01, ha->bmic + EINTENABREG); } else if (ha->type == GDT_ISA) { - dp2_ptr = (gdt2_dpram_str *)ha->brd; + dp2_ptr = ha->brd; gdth_writeb(1, &dp2_ptr->io.irqdel); gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index); gdth_writeb(1, &dp2_ptr->io.irqen); } else if (ha->type == GDT_PCI) { - dp6_ptr = (gdt6_dpram_str *)ha->brd; + dp6_ptr = ha->brd; gdth_writeb(1, &dp6_ptr->io.irqdel); gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index); gdth_writeb(1, &dp6_ptr->io.irqen); @@ -1711,12 +1583,12 @@ GDTH_INITFUNC(static void, gdth_enable_int(int hanum)) outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); outb(0x03, PTR2USHORT(&ha->plx->control1)); } else if (ha->type == GDT_PCIMPR) { - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; + dp6m_ptr = ha->brd; gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4, &dp6m_ptr->i960r.edoor_en_reg); } - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); } @@ -1737,15 +1609,15 @@ static int gdth_get_status(unchar *pIStatus,int irq) *pIStatus = inb((ushort)ha->bmic + EDOORREG); else if (ha->type == GDT_ISA) *pIStatus = - gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index); + gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); else if (ha->type == GDT_PCI) *pIStatus = - gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index); + gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); else if (ha->type == GDT_PCINEW) *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg)); else if (ha->type == GDT_PCIMPR) *pIStatus = - gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg); + gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg); if (*pIStatus) return i; /* board found */ @@ -1765,14 +1637,14 @@ static int gdth_test_busy(int hanum) if (ha->type == GDT_EISA) gdtsema0 = (int)inb(ha->bmic + SEMA0REG); else if (ha->type == GDT_ISA) - gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0); + gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); else if (ha->type == GDT_PCI) - gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0); + gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0); else if (ha->type == GDT_PCINEW) gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg)); else if (ha->type == GDT_PCIMPR) gdtsema0 = - (int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg); + (int)gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); return (gdtsema0 & 1); } @@ -1808,13 +1680,13 @@ static void gdth_set_sema0(int hanum) if (ha->type == GDT_EISA) { outb(1, ha->bmic + SEMA0REG); } else if (ha->type == GDT_ISA) { - gdth_writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0); + gdth_writeb(1, &((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); } else if (ha->type == GDT_PCI) { - gdth_writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0); + gdth_writeb(1, &((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0); } else if (ha->type == GDT_PCINEW) { outb(1, PTR2USHORT(&ha->plx->sema0_reg)); } else if (ha->type == GDT_PCIMPR) { - gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg); + gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); } } @@ -1823,10 +1695,10 @@ static void gdth_copy_command(int hanum) { register gdth_ha_str *ha; register gdth_cmd_str *cmd_ptr; - register gdt6m_dpram_str *dp6m_ptr; - register gdt6c_dpram_str *dp6c_ptr; - gdt6_dpram_str *dp6_ptr; - gdt2_dpram_str *dp2_ptr; + register gdt6m_dpram_str __iomem *dp6m_ptr; + register gdt6c_dpram_str __iomem *dp6c_ptr; + gdt6_dpram_str __iomem *dp6_ptr; + gdt2_dpram_str __iomem *dp2_ptr; ushort cp_count,dp_offset,cmd_no; TRACE(("gdth_copy_command() hanum %d\n",hanum)); @@ -1849,28 +1721,28 @@ static void gdth_copy_command(int hanum) /* set offset and service, copy command to DPMEM */ if (ha->type == GDT_ISA) { - dp2_ptr = (gdt2_dpram_str *)ha->brd; + dp2_ptr = ha->brd; gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp2_ptr->u.ic.comm_queue[cmd_no].offset); gdth_writew((ushort)cmd_ptr->Service, &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCI) { - dp6_ptr = (gdt6_dpram_str *)ha->brd; + dp6_ptr = ha->brd; gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6_ptr->u.ic.comm_queue[cmd_no].offset); gdth_writew((ushort)cmd_ptr->Service, &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCINEW) { - dp6c_ptr = (gdt6c_dpram_str *)ha->brd; + dp6c_ptr = ha->brd; gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6c_ptr->u.ic.comm_queue[cmd_no].offset); gdth_writew((ushort)cmd_ptr->Service, &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCIMPR) { - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; + dp6m_ptr = ha->brd; gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6m_ptr->u.ic.comm_queue[cmd_no].offset); gdth_writew((ushort)cmd_ptr->Service, @@ -1909,13 +1781,13 @@ static void gdth_release_event(int hanum) outl(ha->ccb_phys, ha->bmic + MAILBOXREG); outb(ha->pccb->Service, ha->bmic + LDOORREG); } else if (ha->type == GDT_ISA) { - gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event); + gdth_writeb(0, &((gdt2_dpram_str __iomem *)ha->brd)->io.event); } else if (ha->type == GDT_PCI) { - gdth_writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event); + gdth_writeb(0, &((gdt6_dpram_str __iomem *)ha->brd)->io.event); } else if (ha->type == GDT_PCINEW) { outb(1, PTR2USHORT(&ha->plx->ldoor_reg)); } else if (ha->type == GDT_PCIMPR) { - gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg); + gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.ldoor_reg); } } @@ -1933,7 +1805,7 @@ static int gdth_wait(int hanum,int index,ulong32 time) gdth_from_wait = TRUE; do { - gdth_interrupt((int)ha->irq,ha,NULL); + gdth_interrupt((int)ha->irq,ha); if (wait_hanum==hanum && wait_index==index) { answer_found = TRUE; break; @@ -1950,7 +1822,7 @@ static int gdth_wait(int hanum,int index,ulong32 time) static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, - ulong32 p2,ulong32 p3) + ulong64 p2,ulong64 p3) { register gdth_ha_str *ha; register gdth_cmd_str *cmd_ptr; @@ -1976,23 +1848,35 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, if (service == CACHESERVICE) { if (opcode == GDT_IOCTL) { cmd_ptr->u.ioctl.subfunc = p1; - cmd_ptr->u.ioctl.channel = p2; + cmd_ptr->u.ioctl.channel = (ulong32)p2; cmd_ptr->u.ioctl.param_size = (ushort)p3; cmd_ptr->u.ioctl.p_param = ha->scratch_phys; } else { - cmd_ptr->u.cache.DeviceNo = (ushort)p1; - cmd_ptr->u.cache.BlockNo = p2; + if (ha->cache_feat & GDT_64BIT) { + cmd_ptr->u.cache64.DeviceNo = (ushort)p1; + cmd_ptr->u.cache64.BlockNo = p2; + } else { + cmd_ptr->u.cache.DeviceNo = (ushort)p1; + cmd_ptr->u.cache.BlockNo = (ulong32)p2; + } } } else if (service == SCSIRAWSERVICE) { - cmd_ptr->u.raw.direction = p1; - cmd_ptr->u.raw.bus = (unchar)p2; - cmd_ptr->u.raw.target = (unchar)p3; - cmd_ptr->u.raw.lun = (unchar)(p3 >> 8); + if (ha->raw_feat & GDT_64BIT) { + cmd_ptr->u.raw64.direction = p1; + cmd_ptr->u.raw64.bus = (unchar)p2; + cmd_ptr->u.raw64.target = (unchar)p3; + cmd_ptr->u.raw64.lun = (unchar)(p3 >> 8); + } else { + cmd_ptr->u.raw.direction = p1; + cmd_ptr->u.raw.bus = (unchar)p2; + cmd_ptr->u.raw.target = (unchar)p3; + cmd_ptr->u.raw.lun = (unchar)(p3 >> 8); + } } else if (service == SCREENSERVICE) { if (opcode == GDT_REALTIME) { *(ulong32 *)&cmd_ptr->u.screen.su.data[0] = p1; - *(ulong32 *)&cmd_ptr->u.screen.su.data[4] = p2; - *(ulong32 *)&cmd_ptr->u.screen.su.data[8] = p3; + *(ulong32 *)&cmd_ptr->u.screen.su.data[4] = (ulong32)p2; + *(ulong32 *)&cmd_ptr->u.screen.su.data[8] = (ulong32)p3; } } ha->cmd_len = sizeof(gdth_cmd_str); @@ -2016,10 +1900,11 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, /* search for devices */ -GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) +static int __init gdth_search_drives(int hanum) { register gdth_ha_str *ha; ushort cdev_cnt, i; + int ok; ulong32 bus_no, drv_cnt, drv_no, j; gdth_getch_str *chn; gdth_drlist_str *drl; @@ -2028,6 +1913,9 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) gdth_arcdl_str *alst; gdth_alist_str *alst2; gdth_oem_str_ioctl *oemstr; +#ifdef INT_COAL + gdth_perf_modes *pmod; +#endif #ifdef GDTH_RTC unchar rtc[12]; @@ -2036,11 +1924,20 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) TRACE(("gdth_search_drives() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); + ok = 0; /* initialize controller services, at first: screen service */ - if (!gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0)) { - printk("GDT: Initialization error screen service (code %d)\n", - ha->status); + ha->screen_feat = 0; + if (!force_dma32) { + ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_X_INIT_SCR,0,0,0); + if (ok) + ha->screen_feat = GDT_64BIT; + } + if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) + ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0); + if (!ok) { + printk("GDT-HA %d: Initialization error screen service (code %d)\n", + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n")); @@ -2060,7 +1957,7 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) for (j = 0; j < 12; ++j) rtc[j] = CMOS_READ(j); } while (rtc[0] != CMOS_READ(0)); - spin_unlock_irqrestore(&rtc_lock, flags); + spin_lock_irqrestore(&rtc_lock, flags); TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0], *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8])); /* 3. send to controller firmware */ @@ -2072,15 +1969,52 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) gdth_internal_cmd(hanum,CACHESERVICE,GDT_UNFREEZE_IO,0,0,0); /* initialize cache service */ - if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) { - printk("GDT: Initialization error cache service (code %d)\n", - ha->status); + ha->cache_feat = 0; + if (!force_dma32) { + ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INIT_HOST,LINUX_OS,0,0); + if (ok) + ha->cache_feat = GDT_64BIT; + } + if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) + ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0); + if (!ok) { + printk("GDT-HA %d: Initialization error cache service (code %d)\n", + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n")); cdev_cnt = (ushort)ha->info; ha->fw_vers = ha->service; +#ifdef INT_COAL + if (ha->type == GDT_PCIMPR) { + /* set perf. modes */ + pmod = (gdth_perf_modes *)ha->pscratch; + pmod->version = 1; + pmod->st_mode = 1; /* enable one status buffer */ + *((ulong64 *)&pmod->st_buff_addr1) = ha->coal_stat_phys; + pmod->st_buff_indx1 = COALINDEX; + pmod->st_buff_addr2 = 0; + pmod->st_buff_u_addr2 = 0; + pmod->st_buff_indx2 = 0; + pmod->st_buff_size = sizeof(gdth_coal_status) * MAXOFFSETS; + pmod->cmd_mode = 0; // disable all cmd buffers + pmod->cmd_buff_addr1 = 0; + pmod->cmd_buff_u_addr1 = 0; + pmod->cmd_buff_indx1 = 0; + pmod->cmd_buff_addr2 = 0; + pmod->cmd_buff_u_addr2 = 0; + pmod->cmd_buff_indx2 = 0; + pmod->cmd_buff_size = 0; + pmod->reserved1 = 0; + pmod->reserved2 = 0; + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,SET_PERF_MODES, + INVALID_CHANNEL,sizeof(gdth_perf_modes))) { + printk("GDT-HA %d: Interrupt coalescing activated\n", hanum); + } + } +#endif + /* detect number of buses - try new IOCTL */ iocr = (gdth_raw_iochan_str *)ha->pscratch; iocr->hdr.version = 0xffffffff; @@ -2108,8 +2042,8 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) IO_CHANNEL | INVALID_CHANNEL, sizeof(gdth_getch_str))) { if (bus_no == 0) { - printk("GDT: Error detecting channel count (0x%x)\n", - ha->status); + printk("GDT-HA %d: Error detecting channel count (0x%x)\n", + hanum, ha->status); return 0; } break; @@ -2126,8 +2060,8 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) /* read cache configuration */ if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO, INVALID_CHANNEL,sizeof(gdth_cinfo_str))) { - printk("GDT: Initialization error cache service (code %d)\n", - ha->status); + printk("GDT-HA %d: Initialization error cache service (code %d)\n", + hanum, ha->status); return 0; } ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar; @@ -2246,9 +2180,17 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) } /* initialize raw service */ - if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) { - printk("GDT: Initialization error raw service (code %d)\n", - ha->status); + ha->raw_feat = 0; + if (!force_dma32) { + ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_X_INIT_RAW,0,0,0); + if (ok) + ha->raw_feat = GDT_64BIT; + } + if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) + ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0); + if (!ok) { + printk("GDT-HA %d: Initialization error raw service (code %d)\n", + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n")); @@ -2260,7 +2202,7 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) { TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n", ha->info)); - ha->raw_feat = (ushort)ha->info; + ha->raw_feat |= (ushort)ha->info; } } @@ -2271,7 +2213,7 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) { TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n", ha->info)); - ha->cache_feat = (ushort)ha->info; + ha->cache_feat |= (ushort)ha->info; } } @@ -2291,8 +2233,8 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0, reserve_list[i+1], reserve_list[i+2] | (reserve_list[i+3] << 8))) { - printk("GDT: Error raw service (RESERVE, code %d)\n", - ha->status); + printk("GDT-HA %d: Error raw service (RESERVE, code %d)\n", + hanum, ha->status); } } } @@ -2305,17 +2247,32 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL, sizeof(gdth_oem_str_ioctl))) { TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n")); - printk("GDT CTR%d Vendor: %s\n",hanum,oemstr->text.oem_company_name); + printk("GDT-HA %d: Vendor: %s Name: %s\n", + hanum,oemstr->text.oem_company_name,ha->binfo.type_string); /* Save the Host Drive inquiry data */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) strlcpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id, - sizeof(ha->oem_name)); + sizeof(ha->oem_name)); +#else + strncpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,7); + ha->oem_name[7] = '\0'; +#endif } else { /* Old method, based on PCI ID */ TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n")); + printk("GDT-HA %d: Name: %s\n", + hanum,ha->binfo.type_string); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) if (ha->oem_id == OEM_ID_INTEL) strlcpy(ha->oem_name,"Intel ", sizeof(ha->oem_name)); else strlcpy(ha->oem_name,"ICP ", sizeof(ha->oem_name)); +#else + if (ha->oem_id == OEM_ID_INTEL) + strcpy(ha->oem_name,"Intel "); + else + strcpy(ha->oem_name,"ICP "); +#endif } /* scanning for host drives */ @@ -2329,7 +2286,8 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) static int gdth_analyse_hdrive(int hanum,ushort hdrive) { register gdth_ha_str *ha; - int drv_cyls, drv_hds, drv_secs; + ulong32 drv_cyls; + int drv_hds, drv_secs; TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n",hanum,hdrive)); if (hdrive >= MAX_HDRIVES) @@ -2340,7 +2298,7 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive) return 0; ha->hdr[hdrive].present = TRUE; ha->hdr[hdrive].size = ha->info; - + /* evaluate mapping (sectors per head, heads per cylinder) */ ha->hdr[hdrive].size &= ~SECS32; if (ha->info2 == 0) { @@ -2348,15 +2306,22 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive) } else { drv_hds = ha->info2 & 0xff; drv_secs = (ha->info2 >> 8) & 0xff; - drv_cyls = ha->hdr[hdrive].size /drv_hds/drv_secs; + drv_cyls = (ulong32)ha->hdr[hdrive].size / drv_hds / drv_secs; } ha->hdr[hdrive].heads = (unchar)drv_hds; ha->hdr[hdrive].secs = (unchar)drv_secs; /* round size */ ha->hdr[hdrive].size = drv_cyls * drv_hds * drv_secs; + + if (ha->cache_feat & GDT_64BIT) { + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INFO,hdrive,0,0) + && ha->info2 != 0) { + ha->hdr[hdrive].size = ((ulong64)ha->info2 << 32) | ha->info; + } + } TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n", hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs)); - + /* get informations about device */ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,hdrive,0,0)) { TRACE2(("gdth_search_dr() cache drive %d devtype %d\n", @@ -2395,25 +2360,20 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority) TRACE(("gdth_putq() priority %d\n",priority)); ha = HADATA(gdth_ctr_tab[hanum]); - GDTH_LOCK_HA(ha, flags); + spin_lock_irqsave(&ha->smp_lock, flags); - scp->SCp.this_residual = (int)priority; -#if LINUX_VERSION_CODE >= 0x02053C - b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; - t = scp->device->id; -#else - b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel; - t = scp->target; -#endif -#if LINUX_VERSION_CODE >= 0x010300 - if (priority >= DEFAULT_PRI) { - if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || - (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) { - TRACE2(("gdth_putq(): locked IO -> update_timeout()\n")); - scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + if (scp->done != gdth_scsi_done) { + scp->SCp.this_residual = (int)priority; + b = virt_ctr ? NUMDATA(scp->device->host)->busnum:scp->device->channel; + t = scp->device->id; + if (priority >= DEFAULT_PRI) { + if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || + (b==ha->virt_bus && thdr[t].lock)) { + TRACE2(("gdth_putq(): locked IO ->update_timeout()\n")); + scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + } } } -#endif if (ha->req_first==NULL) { ha->req_first = scp; /* queue was empty */ @@ -2429,7 +2389,7 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority) pscp->SCp.ptr = (char *)scp; scp->SCp.ptr = (char *)nscp; } - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); #ifdef GDTH_STATISTICS flags = 0; @@ -2455,7 +2415,7 @@ static void gdth_next(int hanum) TRACE(("gdth_next() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); if (!gdth_polling) - GDTH_LOCK_HA(ha, flags); + spin_lock_irqsave(&ha->smp_lock, flags); ha->cmd_cnt = ha->cmd_offs_dpmem = 0; this_cmd = firsttime = TRUE; @@ -2465,26 +2425,24 @@ static void gdth_next(int hanum) for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) { if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr) pscp = (Scsi_Cmnd *)pscp->SCp.ptr; -#if LINUX_VERSION_CODE >= 0x02053C - b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel; - t = nscp->device->id; - l = nscp->device->lun; -#else - b = virt_ctr ? NUMDATA(nscp->host)->busnum : nscp->channel; - t = nscp->target; - l = nscp->lun; -#endif - if (nscp->SCp.this_residual >= DEFAULT_PRI) { - if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || - (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) - continue; - } + if (nscp->done != gdth_scsi_done) { + b = virt_ctr ? + NUMDATA(nscp->device->host)->busnum : nscp->device->channel; + t = nscp->device->id; + l = nscp->device->lun; + if (nscp->SCp.this_residual >= DEFAULT_PRI) { + if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || + (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) + continue; + } + } else + b = t = l = 0; if (firsttime) { if (gdth_test_busy(hanum)) { /* controller busy ? */ TRACE(("gdth_next() controller %d busy !\n",hanum)); if (!gdth_polling) { - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); return; } while (gdth_test_busy(hanum)) @@ -2493,10 +2451,7 @@ static void gdth_next(int hanum) firsttime = FALSE; } -#if LINUX_VERSION_CODE >= 0x010300 - if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) -#endif - { + if (nscp->done != gdth_scsi_done) { if (nscp->SCp.phase == -1) { nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */ if (nscp->cmnd[0] == TEST_UNIT_READY) { @@ -2556,25 +2511,14 @@ static void gdth_next(int hanum) nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; - else { - if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); - /* io_request_lock already active ! */ + else nscp->scsi_done(nscp); - if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); - } } - } else - -#if LINUX_VERSION_CODE >= 0x010300 - if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) { + } else if (nscp->done == gdth_scsi_done) { if (!(cmd_index=gdth_special_cmd(hanum,nscp))) this_cmd = FALSE; next_cmd = FALSE; - } else -#endif - if (b != ha->virt_bus) { + } else if (b != ha->virt_bus) { if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW || !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) this_cmd = FALSE; @@ -2586,14 +2530,8 @@ static void gdth_next(int hanum) nscp->result = DID_BAD_TARGET << 16; if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; - else { - if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); - /* io_request_lock already active ! */ + else nscp->scsi_done(nscp); - if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); - } } else { switch (nscp->cmnd[0]) { case TEST_UNIT_READY: @@ -2603,6 +2541,7 @@ static void gdth_next(int hanum) case VERIFY: case START_STOP: case MODE_SENSE: + case SERVICE_ACTION_IN: TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); @@ -2617,22 +2556,10 @@ static void gdth_next(int hanum) nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; - else { - if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); - /* io_request_lock already active ! */ + else nscp->scsi_done(nscp); - if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); - } - } else if (gdth_internal_cache_cmd(hanum,nscp)) { - if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); - /* io_request_lock already active ! */ + } else if (gdth_internal_cache_cmd(hanum,nscp)) nscp->scsi_done(nscp); - if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); - } break; case ALLOW_MEDIUM_REMOVAL: @@ -2645,14 +2572,8 @@ static void gdth_next(int hanum) nscp->sense_buffer[0] = 0; if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; - else { - if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); - /* io_request_lock already active ! */ + else nscp->scsi_done(nscp); - if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); - } } else { nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0; TRACE(("Prevent/allow r. %d rem. drive %d\n", @@ -2674,6 +2595,8 @@ static void gdth_next(int hanum) case WRITE_6: case READ_10: case WRITE_10: + case READ_16: + case WRITE_16: if (ha->hdr[t].media_changed) { /* return UNIT_ATTENTION */ TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n", @@ -2685,14 +2608,8 @@ static void gdth_next(int hanum) nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; - else { - if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); - /* io_request_lock already active ! */ + else nscp->scsi_done(nscp); - if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); - } } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) this_cmd = FALSE; break; @@ -2701,19 +2618,13 @@ static void gdth_next(int hanum) TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp->cmnd[0], nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); - printk("GDT: Unknown SCSI command 0x%x to cache service !\n", - nscp->cmnd[0]); + printk("GDT-HA %d: Unknown SCSI command 0x%x to cache service !\n", + hanum, nscp->cmnd[0]); nscp->result = DID_ABORT << 16; if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; - else { - if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); - /* io_request_lock already active ! */ + else nscp->scsi_done(nscp); - if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); - } break; } } @@ -2733,15 +2644,15 @@ static void gdth_next(int hanum) } if (!gdth_polling) - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); if (gdth_polling && ha->cmd_cnt > 0) { if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT)) - printk("GDT: Controller %d: Command %d timed out !\n", + printk("GDT-HA %d: Command %d timed out !\n", hanum,cmd_index); } } - + static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, char *buffer,ushort count) { @@ -2749,47 +2660,43 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, ushort cpsum,cpnow; struct scatterlist *sl; gdth_ha_str *ha; - int sgcnt; char *address; - cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen; + cpcount = count<=(ushort)scp->request_bufflen ? count:(ushort)scp->request_bufflen; ha = HADATA(gdth_ctr_tab[hanum]); if (scp->use_sg) { sl = (struct scatterlist *)scp->request_buffer; -#if LINUX_VERSION_CODE >= 0x020400 - sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE); - for (i=0,cpsum=0; iuse_sg; ++i,++sl) { + unsigned long flags; + cpnow = (ushort)sl->length; TRACE(("copy_internal() now %d sum %d count %d %d\n", cpnow,cpsum,cpcount,(ushort)scp->bufflen)); if (cpsum+cpnow > cpcount) cpnow = cpcount - cpsum; cpsum += cpnow; - address = (char *)phys_to_virt(sg_dma_address(sl)); + if (!sl->page) { + printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n", + hanum); + return; + } + local_irq_save(flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset; + memcpy(address,buffer,cpnow); + flush_dcache_page(sl->page); + kunmap_atomic(address, KM_BIO_SRC_IRQ); +#else + address = kmap_atomic(sl->page, KM_BH_IRQ) + sl->offset; memcpy(address,buffer,cpnow); + flush_dcache_page(sl->page); + kunmap_atomic(address, KM_BH_IRQ); +#endif + local_irq_restore(flags); if (cpsum == cpcount) break; buffer += cpnow; } - pci_unmap_sg(ha->pdev,scp->request_buffer, - scp->use_sg,PCI_DMA_FROMDEVICE); -#else - sgcnt = scp->use_sg; - for (i=0,cpsum=0; ilength; - TRACE(("copy_internal() now %d sum %d count %d %d\n", - cpnow,cpsum,cpcount,(ushort)scp->bufflen)); - if (cpsum+cpnow > cpcount) - cpnow = cpcount - cpsum; - cpsum += cpnow; - address = (char *)sl->address; - memcpy(address,buffer,cpnow); - if (cpsum == cpcount) - break; - buffer += cpnow; - } -#endif } else { TRACE(("copy_internal() count %d\n",cpcount)); memcpy((char*)scp->request_buffer,buffer,cpcount); @@ -2806,14 +2713,13 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp) gdth_modep_data mpd; ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x02053C t = scp->device->id; -#else - t = scp->target; -#endif TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n", scp->cmnd[0],t)); + scp->result = DID_OK << 16; + scp->sense_buffer[0] = 0; + switch (scp->cmnd[0]) { case TEST_UNIT_READY: case VERIFY: @@ -2864,19 +2770,33 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp) case READ_CAPACITY: TRACE2(("Read capacity hdrive %d\n",t)); - rdc.last_block_no = ntohl(ha->hdr[t].size-1); - rdc.block_length = ntohl(SECTOR_SIZE); + if (ha->hdr[t].size > (ulong64)0xffffffff) + rdc.last_block_no = 0xffffffff; + else + rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1); + rdc.block_length = cpu_to_be32(SECTOR_SIZE); gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data)); break; + case SERVICE_ACTION_IN: + if ((scp->cmnd[1] & 0x1f) == SAI_READ_CAPACITY_16 && + (ha->cache_feat & GDT_64BIT)) { + gdth_rdcap16_data rdc16; + + TRACE2(("Read capacity (16) hdrive %d\n",t)); + rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1); + rdc16.block_length = cpu_to_be32(SECTOR_SIZE); + gdth_copy_internal_data(hanum,scp,(char*)&rdc16,sizeof(gdth_rdcap16_data)); + } else { + scp->result = DID_ABORT << 16; + } + break; + default: TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0])); break; } - scp->result = DID_OK << 16; - scp->sense_buffer[0] = 0; - if (!scp->SCp.have_data_in) scp->SCp.have_data_in++; else @@ -2890,9 +2810,12 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) register gdth_ha_str *ha; register gdth_cmd_str *cmdp; struct scatterlist *sl; - ushort i, cnt; - ulong32 no, phys_addr; - int cmd_index, read_write, sgcnt; + ulong32 cnt, blockcnt; + ulong64 no, blockno; + dma_addr_t phys_addr; + int i, cmd_index, read_write, sgcnt, mode64; + struct page *page; + ulong offset; ha = HADATA(gdth_ctr_tab[hanum]); cmdp = ha->pccb; @@ -2902,6 +2825,11 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) if (ha->type==GDT_EISA && ha->cmd_cnt>0) return 0; + mode64 = (ha->cache_feat & GDT_64BIT) ? TRUE : FALSE; + /* test for READ_16, WRITE_16 if !mode64 ? --- + not required, should not occur due to error return on + READ_CAPACITY_16 */ + cmdp->Service = CACHESERVICE; cmdp->RequestBuffer = scp; /* search free command index */ @@ -2929,7 +2857,8 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) else cmdp->OpCode = GDT_FLUSH; } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 || - scp->cmnd[0] == WRITE_12) { + scp->cmnd[0] == WRITE_12 || scp->cmnd[0] == WRITE_16 + ) { read_write = 1; if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) && (ha->cache_feat & GDT_WR_THROUGH))) @@ -2940,86 +2869,135 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) read_write = 2; cmdp->OpCode = GDT_READ; } - - cmdp->BoardNode = LOCALBOARD; - cmdp->u.cache.DeviceNo = hdrive; - cmdp->u.cache.BlockNo = 1; - cmdp->u.cache.sg_canz = 0; + + cmdp->BoardNode = LOCALBOARD; + if (mode64) { + cmdp->u.cache64.DeviceNo = hdrive; + cmdp->u.cache64.BlockNo = 1; + cmdp->u.cache64.sg_canz = 0; + } else { + cmdp->u.cache.DeviceNo = hdrive; + cmdp->u.cache.BlockNo = 1; + cmdp->u.cache.sg_canz = 0; + } if (read_write) { - if (scp->cmd_len != 6) { + if (scp->cmd_len == 16) { + memcpy(&no, &scp->cmnd[2], sizeof(ulong64)); + blockno = be64_to_cpu(no); + memcpy(&cnt, &scp->cmnd[10], sizeof(ulong32)); + blockcnt = be32_to_cpu(cnt); + } else if (scp->cmd_len == 10) { memcpy(&no, &scp->cmnd[2], sizeof(ulong32)); - cmdp->u.cache.BlockNo = ntohl(no); + blockno = be32_to_cpu(no); memcpy(&cnt, &scp->cmnd[7], sizeof(ushort)); - cmdp->u.cache.BlockCnt = (ulong32)ntohs(cnt); + blockcnt = be16_to_cpu(cnt); } else { memcpy(&no, &scp->cmnd[0], sizeof(ulong32)); - cmdp->u.cache.BlockNo = ntohl(no) & 0x001fffffUL; - cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4]; + blockno = be32_to_cpu(no) & 0x001fffffUL; + blockcnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4]; + } + if (mode64) { + cmdp->u.cache64.BlockNo = blockno; + cmdp->u.cache64.BlockCnt = blockcnt; + } else { + cmdp->u.cache.BlockNo = (ulong32)blockno; + cmdp->u.cache.BlockCnt = blockcnt; } if (scp->use_sg) { - cmdp->u.cache.DestAddr= 0xffffffff; sl = (struct scatterlist *)scp->request_buffer; sgcnt = scp->use_sg; -#if LINUX_VERSION_CODE >= 0x020400 scp->SCp.Status = GDTH_MAP_SG; scp->SCp.Message = (read_write == 1 ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); - for (i=0; iu.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); - cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl); - } -#else - for (i=0; iu.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address); - cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length; - } + if (mode64) { + cmdp->u.cache64.DestAddr= (ulong64)-1; + cmdp->u.cache64.sg_canz = sgcnt; + for (i=0; iu.cache64.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + if (cmdp->u.cache64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) + ha->dma64_cnt++; + else + ha->dma32_cnt++; #endif - cmdp->u.cache.sg_canz = (ulong32)i; + cmdp->u.cache64.sg_lst[i].sg_len = sg_dma_len(sl); + } + } else { + cmdp->u.cache.DestAddr= 0xffffffff; + cmdp->u.cache.sg_canz = sgcnt; + for (i=0; iu.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + ha->dma32_cnt++; +#endif + cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl); + } + } #ifdef GDTH_STATISTICS - if (max_sg < (ulong32)i) { - max_sg = (ulong32)i; - TRACE3(("GDT: max_sg = %d\n",i)); + if (max_sg < (ulong32)sgcnt) { + max_sg = (ulong32)sgcnt; + TRACE3(("GDT: max_sg = %d\n",max_sg)); } #endif - if (iu.cache.sg_lst[i].sg_len = 0; - } else { -#if LINUX_VERSION_CODE >= 0x020400 + + } else if (scp->request_bufflen) { scp->SCp.Status = GDTH_MAP_SINGLE; scp->SCp.Message = (read_write == 1 ? - PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - phys_addr = pci_map_single(ha->pdev,scp->request_buffer, - scp->request_bufflen,scp->SCp.Message); + PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); + page = virt_to_page(scp->request_buffer); + offset = (ulong)scp->request_buffer & ~PAGE_MASK; + phys_addr = pci_map_page(ha->pdev,page,offset, + scp->request_bufflen,scp->SCp.Message); scp->SCp.dma_handle = phys_addr; -#else - phys_addr = virt_to_bus(scp->request_buffer); -#endif - if (ha->cache_feat & SCATTER_GATHER) { - cmdp->u.cache.DestAddr = 0xffffffff; - cmdp->u.cache.sg_canz = 1; - cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr; - cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen; - cmdp->u.cache.sg_lst[1].sg_len = 0; + if (mode64) { + if (ha->cache_feat & SCATTER_GATHER) { + cmdp->u.cache64.DestAddr = (ulong64)-1; + cmdp->u.cache64.sg_canz = 1; + cmdp->u.cache64.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.cache64.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.cache64.sg_lst[1].sg_len = 0; + } else { + cmdp->u.cache64.DestAddr = phys_addr; + cmdp->u.cache64.sg_canz= 0; + } } else { - cmdp->u.cache.DestAddr = phys_addr; - cmdp->u.cache.sg_canz= 0; + if (ha->cache_feat & SCATTER_GATHER) { + cmdp->u.cache.DestAddr = 0xffffffff; + cmdp->u.cache.sg_canz = 1; + cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.cache.sg_lst[1].sg_len = 0; + } else { + cmdp->u.cache.DestAddr = phys_addr; + cmdp->u.cache.sg_canz= 0; + } } } } - TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", - cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz, - cmdp->u.cache.sg_lst[0].sg_ptr, - cmdp->u.cache.sg_lst[0].sg_len)); - TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n", - cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt)); - /* evaluate command size, check space */ - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + - (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str); + if (mode64) { + TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.cache64.DestAddr,cmdp->u.cache64.sg_canz, + cmdp->u.cache64.sg_lst[0].sg_ptr, + cmdp->u.cache64.sg_lst[0].sg_len)); + TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n", + cmdp->OpCode,cmdp->u.cache64.BlockNo,cmdp->u.cache64.BlockCnt)); + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) + + (ushort)cmdp->u.cache64.sg_canz * sizeof(gdth_sg64_str); + } else { + TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz, + cmdp->u.cache.sg_lst[0].sg_ptr, + cmdp->u.cache.sg_lst[0].sg_len)); + TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n", + cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt)); + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + + (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str); + } if (ha->cmd_len & 3) ha->cmd_len += (4 - (ha->cmd_len & 3)); @@ -3043,18 +3021,15 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) register gdth_cmd_str *cmdp; struct scatterlist *sl; ushort i; - ulong32 phys_addr, sense_paddr; - int cmd_index, sgcnt; + dma_addr_t phys_addr, sense_paddr; + int cmd_index, sgcnt, mode64; unchar t,l; + struct page *page; + ulong offset; ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x02053C t = scp->device->id; l = scp->device->lun; -#else - t = scp->target; - l = scp->lun; -#endif cmdp = ha->pccb; TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n", scp->cmnd[0],b,t,l)); @@ -3062,6 +3037,8 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) if (ha->type==GDT_EISA && ha->cmd_cnt>0) return 0; + mode64 = (ha->raw_feat & GDT_64BIT) ? TRUE : FALSE; + cmdp->Service = SCSIRAWSERVICE; cmdp->RequestBuffer = scp; /* search free command index */ @@ -3077,95 +3054,153 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) if (scp->SCp.sent_command != -1) { cmdp->OpCode = scp->SCp.sent_command; /* special raw cmd. */ cmdp->BoardNode = LOCALBOARD; - cmdp->u.raw.direction = (scp->SCp.phase >> 8); - TRACE2(("special raw cmd 0x%x param 0x%x\n", - cmdp->OpCode, cmdp->u.raw.direction)); + if (mode64) { + cmdp->u.raw64.direction = (scp->SCp.phase >> 8); + TRACE2(("special raw cmd 0x%x param 0x%x\n", + cmdp->OpCode, cmdp->u.raw64.direction)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst); + } else { + cmdp->u.raw.direction = (scp->SCp.phase >> 8); + TRACE2(("special raw cmd 0x%x param 0x%x\n", + cmdp->OpCode, cmdp->u.raw.direction)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst); + } - /* evaluate command size */ - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst); } else { -#if LINUX_VERSION_CODE >= 0x020400 - sense_paddr = pci_map_single(ha->pdev,scp->sense_buffer, - 16,PCI_DMA_FROMDEVICE); - scp->SCp.buffer = (struct scatterlist *)sense_paddr; -#else - sense_paddr = virt_to_bus(scp->sense_buffer); -#endif + page = virt_to_page(scp->sense_buffer); + offset = (ulong)scp->sense_buffer & ~PAGE_MASK; + sense_paddr = pci_map_page(ha->pdev,page,offset, + 16,PCI_DMA_FROMDEVICE); + *(ulong32 *)&scp->SCp.buffer = (ulong32)sense_paddr; + /* high part, if 64bit */ + *(ulong32 *)&scp->host_scribble = (ulong32)((ulong64)sense_paddr >> 32); cmdp->OpCode = GDT_WRITE; /* always */ cmdp->BoardNode = LOCALBOARD; - cmdp->u.raw.reserved = 0; - cmdp->u.raw.mdisc_time = 0; - cmdp->u.raw.mcon_time = 0; - cmdp->u.raw.clen = scp->cmd_len; - cmdp->u.raw.target = t; - cmdp->u.raw.lun = l; - cmdp->u.raw.bus = b; - cmdp->u.raw.priority = 0; - cmdp->u.raw.link_p = 0; - cmdp->u.raw.sdlen = scp->request_bufflen; - cmdp->u.raw.sense_len = 16; - cmdp->u.raw.sense_data = sense_paddr; - cmdp->u.raw.direction = - gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; - memcpy(cmdp->u.raw.cmd,scp->cmnd,12); + if (mode64) { + cmdp->u.raw64.reserved = 0; + cmdp->u.raw64.mdisc_time = 0; + cmdp->u.raw64.mcon_time = 0; + cmdp->u.raw64.clen = scp->cmd_len; + cmdp->u.raw64.target = t; + cmdp->u.raw64.lun = l; + cmdp->u.raw64.bus = b; + cmdp->u.raw64.priority = 0; + cmdp->u.raw64.sdlen = scp->request_bufflen; + cmdp->u.raw64.sense_len = 16; + cmdp->u.raw64.sense_data = sense_paddr; + cmdp->u.raw64.direction = + gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; + memcpy(cmdp->u.raw64.cmd,scp->cmnd,16); + cmdp->u.raw64.sg_ranz = 0; + } else { + cmdp->u.raw.reserved = 0; + cmdp->u.raw.mdisc_time = 0; + cmdp->u.raw.mcon_time = 0; + cmdp->u.raw.clen = scp->cmd_len; + cmdp->u.raw.target = t; + cmdp->u.raw.lun = l; + cmdp->u.raw.bus = b; + cmdp->u.raw.priority = 0; + cmdp->u.raw.link_p = 0; + cmdp->u.raw.sdlen = scp->request_bufflen; + cmdp->u.raw.sense_len = 16; + cmdp->u.raw.sense_data = sense_paddr; + cmdp->u.raw.direction = + gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; + memcpy(cmdp->u.raw.cmd,scp->cmnd,12); + cmdp->u.raw.sg_ranz = 0; + } if (scp->use_sg) { - cmdp->u.raw.sdata = 0xffffffff; sl = (struct scatterlist *)scp->request_buffer; sgcnt = scp->use_sg; -#if LINUX_VERSION_CODE >= 0x020400 scp->SCp.Status = GDTH_MAP_SG; scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); - for (i=0; iu.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); - cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl); - } -#else - for (i=0; iu.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address); - cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length; - } + if (mode64) { + cmdp->u.raw64.sdata = (ulong64)-1; + cmdp->u.raw64.sg_ranz = sgcnt; + for (i=0; iu.raw64.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + if (cmdp->u.raw64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) + ha->dma64_cnt++; + else + ha->dma32_cnt++; #endif - cmdp->u.raw.sg_ranz = (ulong32)i; + cmdp->u.raw64.sg_lst[i].sg_len = sg_dma_len(sl); + } + } else { + cmdp->u.raw.sdata = 0xffffffff; + cmdp->u.raw.sg_ranz = sgcnt; + for (i=0; iu.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + ha->dma32_cnt++; +#endif + cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl); + } + } #ifdef GDTH_STATISTICS - if (max_sg < (ulong32)i) { - max_sg = (ulong32)i; - TRACE3(("GDT: max_sg = %d\n",i)); + if (max_sg < sgcnt) { + max_sg = sgcnt; + TRACE3(("GDT: max_sg = %d\n",sgcnt)); } #endif - if (iu.raw.sg_lst[i].sg_len = 0; - } else { -#if LINUX_VERSION_CODE >= 0x020400 + + } else if (scp->request_bufflen) { scp->SCp.Status = GDTH_MAP_SINGLE; scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; - phys_addr = pci_map_single(ha->pdev,scp->request_buffer, - scp->request_bufflen,scp->SCp.Message); + page = virt_to_page(scp->request_buffer); + offset = (ulong)scp->request_buffer & ~PAGE_MASK; + phys_addr = pci_map_page(ha->pdev,page,offset, + scp->request_bufflen,scp->SCp.Message); scp->SCp.dma_handle = phys_addr; -#else - phys_addr = virt_to_bus(scp->request_buffer); -#endif - if (ha->raw_feat & SCATTER_GATHER) { - cmdp->u.raw.sdata = 0xffffffff; - cmdp->u.raw.sg_ranz= 1; - cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr; - cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; - cmdp->u.raw.sg_lst[1].sg_len = 0; + + if (mode64) { + if (ha->raw_feat & SCATTER_GATHER) { + cmdp->u.raw64.sdata = (ulong64)-1; + cmdp->u.raw64.sg_ranz= 1; + cmdp->u.raw64.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.raw64.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.raw64.sg_lst[1].sg_len = 0; + } else { + cmdp->u.raw64.sdata = phys_addr; + cmdp->u.raw64.sg_ranz= 0; + } } else { - cmdp->u.raw.sdata = phys_addr; - cmdp->u.raw.sg_ranz= 0; + if (ha->raw_feat & SCATTER_GATHER) { + cmdp->u.raw.sdata = 0xffffffff; + cmdp->u.raw.sg_ranz= 1; + cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.raw.sg_lst[1].sg_len = 0; + } else { + cmdp->u.raw.sdata = phys_addr; + cmdp->u.raw.sg_ranz= 0; + } } } - TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", - cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz, - cmdp->u.raw.sg_lst[0].sg_ptr, - cmdp->u.raw.sg_lst[0].sg_len)); - - /* evaluate command size */ - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + - (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str); + if (mode64) { + TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.raw64.sdata,cmdp->u.raw64.sg_ranz, + cmdp->u.raw64.sg_lst[0].sg_ptr, + cmdp->u.raw64.sg_lst[0].sg_len)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) + + (ushort)cmdp->u.raw64.sg_ranz * sizeof(gdth_sg64_str); + } else { + TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz, + cmdp->u.raw.sg_lst[0].sg_ptr, + cmdp->u.raw.sg_lst[0].sg_len)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + + (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str); + } } /* check space */ if (ha->cmd_len & 3) @@ -3215,15 +3250,23 @@ static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp) if (cmdp->OpCode == GDT_IOCTL) { TRACE2(("IOCTL\n")); ha->cmd_len = - GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong32); + GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong64); } else if (cmdp->Service == CACHESERVICE) { TRACE2(("cache command %d\n",cmdp->OpCode)); - ha->cmd_len = - GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str); + if (ha->cache_feat & GDT_64BIT) + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) + sizeof(gdth_sg64_str); + else + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str); } else if (cmdp->Service == SCSIRAWSERVICE) { - TRACE2(("raw command %d/%d\n",cmdp->OpCode,cmdp->u.raw.cmd[0])); - ha->cmd_len = - GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str); + TRACE2(("raw command %d\n",cmdp->OpCode)); + if (ha->raw_feat & GDT_64BIT) + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) + sizeof(gdth_sg64_str); + else + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str); } if (ha->cmd_len & 3) @@ -3254,7 +3297,7 @@ static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source, /* no GDTH_LOCK_HA() ! */ TRACE2(("gdth_store_event() source %d idx %d\n", source, idx)); if (source == 0) /* no source -> no event */ - return 0; + return NULL; if (ebuffer[elastidx].event_source == source && ebuffer[elastidx].event_idx == idx && @@ -3298,7 +3341,7 @@ static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr) ulong flags; TRACE2(("gdth_read_event() handle %d\n", handle)); - GDTH_LOCK_HA(ha, flags); + spin_lock_irqsave(&ha->smp_lock, flags); if (handle == -1) eindex = eoldidx; else @@ -3306,7 +3349,7 @@ static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr) estr->event_source = 0; if (eindex >= MAX_EVENTS) { - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); return eindex; } e = &ebuffer[eindex]; @@ -3319,7 +3362,7 @@ static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr) } memcpy(estr, e, sizeof(gdth_evt_str)); } - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); return eindex; } @@ -3332,7 +3375,7 @@ static void gdth_readapp_event(gdth_ha_str *ha, unchar found = FALSE; TRACE2(("gdth_readapp_event() app. %d\n", application)); - GDTH_LOCK_HA(ha, flags); + spin_lock_irqsave(&ha->smp_lock, flags); eindex = eoldidx; for (;;) { e = &ebuffer[eindex]; @@ -3352,10 +3395,10 @@ static void gdth_readapp_event(gdth_ha_str *ha, memcpy(estr, e, sizeof(gdth_evt_str)); else estr->event_source = 0; - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); } -static void gdth_clear_events() +static void gdth_clear_events(void) { TRACE(("gdth_clear_events()")); @@ -3366,17 +3409,24 @@ static void gdth_clear_events() /* SCSI interface functions */ -static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) +static irqreturn_t gdth_interrupt(int irq,void *dev_id) { + gdth_ha_str *ha2 = (gdth_ha_str *)dev_id; register gdth_ha_str *ha; - gdt6m_dpram_str *dp6m_ptr; - gdt6_dpram_str *dp6_ptr; - gdt2_dpram_str *dp2_ptr; + gdt6m_dpram_str __iomem *dp6m_ptr = NULL; + gdt6_dpram_str __iomem *dp6_ptr; + gdt2_dpram_str __iomem *dp2_ptr; Scsi_Cmnd *scp; int hanum, rval, i; unchar IStatus; ushort Service; ulong flags = 0; +#ifdef INT_COAL + int coalesced = FALSE; + int next = FALSE; + gdth_coal_status *pcs = NULL; + int act_int_coal = 0; +#endif TRACE(("gdth_interrupt() IRQ %d\n",irq)); @@ -3388,180 +3438,233 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) } if (!gdth_polling) - GDTH_LOCK_HA((gdth_ha_str *)dev_id,flags); + spin_lock_irqsave(&ha2->smp_lock, flags); wait_index = 0; /* search controller */ if ((hanum = gdth_get_status(&IStatus,irq)) == -1) { /* spurious interrupt */ if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; + spin_unlock_irqrestore(&ha2->smp_lock, flags); + return IRQ_HANDLED; } + ha = HADATA(gdth_ctr_tab[hanum]); #ifdef GDTH_STATISTICS ++act_ints; #endif - - ha = HADATA(gdth_ctr_tab[hanum]); - if (ha->type == GDT_EISA) { - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = inw(ha->bmic + MAILBOXREG+8); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = inl(ha->bmic + MAILBOXREG+12); - ha->service = inw(ha->bmic + MAILBOXREG+10); - ha->info2 = inl(ha->bmic + MAILBOXREG+4); - - outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */ - outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */ - } else if (ha->type == GDT_ISA) { - dp2_ptr = (gdt2_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = gdth_readw(&dp2_ptr->u.ic.Status); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]); - ha->service = gdth_readw(&dp2_ptr->u.ic.Service); - ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]); - - gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */ - gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index); /* reset command index */ - gdth_writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */ - } else if (ha->type == GDT_PCI) { - dp6_ptr = (gdt6_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = gdth_readw(&dp6_ptr->u.ic.Status); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]); - ha->service = gdth_readw(&dp6_ptr->u.ic.Service); - ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]); - - gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */ - gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index); /* reset command index */ - gdth_writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */ - } else if (ha->type == GDT_PCINEW) { - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = inw(PTR2USHORT(&ha->plx->status)); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else - ha->status = S_OK; - ha->info = inl(PTR2USHORT(&ha->plx->info[0])); - ha->service = inw(PTR2USHORT(&ha->plx->service)); - ha->info2 = inl(PTR2USHORT(&ha->plx->info[1])); - outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); - outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); - } else if (ha->type == GDT_PCIMPR) { - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = gdth_readw(&dp6m_ptr->i960r.status); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]); - ha->service = gdth_readw(&dp6m_ptr->i960r.service); - ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]); - - /* event string */ - if (IStatus == ASYNCINDEX) { - if (ha->service != SCREENSERVICE && - (ha->fw_vers & 0xff) >= 0x1a) { - ha->dvr.severity = - gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.severity); - for (i = 0; i < 256; ++i) { - ha->dvr.event_string[i] = gdth_readb - (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]); - if (ha->dvr.event_string[i] == 0) - break; +#ifdef INT_COAL + /* See if the fw is returning coalesced status */ + if (IStatus == COALINDEX) { + /* Coalesced status. Setup the initial status + buffer pointer and flags */ + pcs = ha->coal_stat; + coalesced = TRUE; + next = TRUE; + } + + do { + if (coalesced) { + /* For coalesced requests all status + information is found in the status buffer */ + IStatus = (unchar)(pcs->status & 0xff); + } +#endif + + if (ha->type == GDT_EISA) { + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = inw(ha->bmic + MAILBOXREG+8); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; + ha->info = inl(ha->bmic + MAILBOXREG+12); + ha->service = inw(ha->bmic + MAILBOXREG+10); + ha->info2 = inl(ha->bmic + MAILBOXREG+4); + + outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */ + outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */ + } else if (ha->type == GDT_ISA) { + dp2_ptr = ha->brd; + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = gdth_readw(&dp2_ptr->u.ic.Status); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; + ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]); + ha->service = gdth_readw(&dp2_ptr->u.ic.Service); + ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]); + + gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */ + gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);/* reset command index */ + gdth_writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */ + } else if (ha->type == GDT_PCI) { + dp6_ptr = ha->brd; + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = gdth_readw(&dp6_ptr->u.ic.Status); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; + ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]); + ha->service = gdth_readw(&dp6_ptr->u.ic.Service); + ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]); + + gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */ + gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);/* reset command index */ + gdth_writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */ + } else if (ha->type == GDT_PCINEW) { + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = inw(PTR2USHORT(&ha->plx->status)); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else + ha->status = S_OK; + ha->info = inl(PTR2USHORT(&ha->plx->info[0])); + ha->service = inw(PTR2USHORT(&ha->plx->service)); + ha->info2 = inl(PTR2USHORT(&ha->plx->info[1])); + + outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); + outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); + } else if (ha->type == GDT_PCIMPR) { + dp6m_ptr = ha->brd; + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; +#ifdef INT_COAL + if (coalesced) + ha->status = pcs->ext_status & 0xffff; + else +#endif + ha->status = gdth_readw(&dp6m_ptr->i960r.status); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; +#ifdef INT_COAL + /* get information */ + if (coalesced) { + ha->info = pcs->info0; + ha->info2 = pcs->info1; + ha->service = (pcs->ext_status >> 16) & 0xffff; + } else +#endif + { + ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]); + ha->service = gdth_readw(&dp6m_ptr->i960r.service); + ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]); + } + /* event string */ + if (IStatus == ASYNCINDEX) { + if (ha->service != SCREENSERVICE && + (ha->fw_vers & 0xff) >= 0x1a) { + ha->dvr.severity = gdth_readb + (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.severity); + for (i = 0; i < 256; ++i) { + ha->dvr.event_string[i] = gdth_readb + (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.evt_str[i]); + if (ha->dvr.event_string[i] == 0) + break; + } } } +#ifdef INT_COAL + /* Make sure that non coalesced interrupts get cleared + before being handled by gdth_async_event/gdth_sync_event */ + if (!coalesced) +#endif + { + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); + } + } else { + TRACE2(("gdth_interrupt() unknown controller type\n")); + if (!gdth_polling) + spin_unlock_irqrestore(&ha2->smp_lock, flags); + return IRQ_HANDLED; } - gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); - } else { - TRACE2(("gdth_interrupt() unknown controller type\n")); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } - TRACE(("gdth_interrupt() index %d stat %d info %d\n", - IStatus,ha->status,ha->info)); + TRACE(("gdth_interrupt() index %d stat %d info %d\n", + IStatus,ha->status,ha->info)); - if (gdth_from_wait) { - wait_hanum = hanum; - wait_index = (int)IStatus; - } + if (gdth_from_wait) { + wait_hanum = hanum; + wait_index = (int)IStatus; + } - if (IStatus == ASYNCINDEX) { - TRACE2(("gdth_interrupt() async. event\n")); - gdth_async_event(hanum); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - gdth_next(hanum); - return IRQ_HANDLED; - } + if (IStatus == ASYNCINDEX) { + TRACE2(("gdth_interrupt() async. event\n")); + gdth_async_event(hanum); + if (!gdth_polling) + spin_unlock_irqrestore(&ha2->smp_lock, flags); + gdth_next(hanum); + return IRQ_HANDLED; + } - if (IStatus == SPEZINDEX) { - TRACE2(("Service unknown or not initialized !\n")); - ha->dvr.size = sizeof(ha->dvr.eu.driver); - ha->dvr.eu.driver.ionode = hanum; - gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } - scp = ha->cmd_tab[IStatus-2].cmnd; - Service = ha->cmd_tab[IStatus-2].service; - ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND; - if (scp == UNUSED_CMND) { - TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus)); - ha->dvr.size = sizeof(ha->dvr.eu.driver); - ha->dvr.eu.driver.ionode = hanum; - ha->dvr.eu.driver.index = IStatus; - gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } - if (scp == INTERNAL_CMND) { - TRACE(("gdth_interrupt() answer to internal command\n")); + if (IStatus == SPEZINDEX) { + TRACE2(("Service unknown or not initialized !\n")); + ha->dvr.size = sizeof(ha->dvr.eu.driver); + ha->dvr.eu.driver.ionode = hanum; + gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr); + if (!gdth_polling) + spin_unlock_irqrestore(&ha2->smp_lock, flags); + return IRQ_HANDLED; + } + scp = ha->cmd_tab[IStatus-2].cmnd; + Service = ha->cmd_tab[IStatus-2].service; + ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND; + if (scp == UNUSED_CMND) { + TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus)); + ha->dvr.size = sizeof(ha->dvr.eu.driver); + ha->dvr.eu.driver.ionode = hanum; + ha->dvr.eu.driver.index = IStatus; + gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr); + if (!gdth_polling) + spin_unlock_irqrestore(&ha2->smp_lock, flags); + return IRQ_HANDLED; + } + if (scp == INTERNAL_CMND) { + TRACE(("gdth_interrupt() answer to internal command\n")); + if (!gdth_polling) + spin_unlock_irqrestore(&ha2->smp_lock, flags); + return IRQ_HANDLED; + } + + TRACE(("gdth_interrupt() sync. status\n")); + rval = gdth_sync_event(hanum,Service,IStatus,scp); if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } + spin_unlock_irqrestore(&ha2->smp_lock, flags); + if (rval == 2) { + gdth_putq(hanum,scp,scp->SCp.this_residual); + } else if (rval == 1) { + scp->scsi_done(scp); + } - TRACE(("gdth_interrupt() sync. status\n")); - rval = gdth_sync_event(hanum,Service,IStatus,scp); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - if (rval == 2) { - gdth_putq(hanum,scp,scp->SCp.this_residual); - } else if (rval == 1) { -#if LINUX_VERSION_CODE >= 0x02053C - GDTH_LOCK_SCSI_DONE(scp->device->host, flags); - scp->scsi_done(scp); - GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags); -#elif LINUX_VERSION_CODE >= 0x020503 - GDTH_LOCK_SCSI_DONE(scp->host, flags); - scp->scsi_done(scp); - GDTH_UNLOCK_SCSI_DONE(scp->host, flags); -#else - GDTH_LOCK_SCSI_DONE(flags); - scp->scsi_done(scp); - GDTH_UNLOCK_SCSI_DONE(flags); -#endif +#ifdef INT_COAL + if (coalesced) { + /* go to the next status in the status buffer */ + ++pcs; +#ifdef GDTH_STATISTICS + ++act_int_coal; + if (act_int_coal > max_int_coal) { + max_int_coal = act_int_coal; + printk("GDT: max_int_coal = %d\n",(ushort)max_int_coal); + } +#endif + /* see if there is another status */ + if (pcs->status == 0) + /* Stop the coalesce loop */ + next = FALSE; + } + } while (next); + + /* coalescing only for new GDT_PCIMPR controllers available */ + if (ha->type == GDT_PCIMPR && coalesced) { + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); } +#endif + gdth_next(hanum); return IRQ_HANDLED; } @@ -3579,10 +3682,11 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) service,ha->status)); if (service == SCREENSERVICE) { - msg = (gdth_msg_str *)ha->pscratch; - ha->scratch_busy = FALSE; + msg = ha->pmsg; TRACE(("len: %d, answer: %d, ext: %d, alen: %d\n", msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen)); + if (msg->msg_len > MSGLEN+1) + msg->msg_len = MSGLEN+1; if (msg->msg_len) if (!(msg->msg_answer && msg->msg_ext)) { msg->msg_text[msg->msg_len] = '\0'; @@ -3600,11 +3704,10 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= msg->msg_handle; - cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; - ha->scratch_busy = TRUE; + cmdp->u.screen.su.msg.msg_addr = ha->msg_phys; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) - + sizeof(ulong32); + + sizeof(ulong64); ha->cmd_cnt = 0; gdth_copy_command(hanum); gdth_release_event(hanum); @@ -3635,11 +3738,10 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= msg->msg_handle; - cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; - ha->scratch_busy = TRUE; + cmdp->u.screen.su.msg.msg_addr = ha->msg_phys; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) - + sizeof(ulong32); + + sizeof(ulong64); ha->cmd_cnt = 0; gdth_copy_command(hanum); gdth_release_event(hanum); @@ -3648,13 +3750,8 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) printk("\n"); } else { -#if LINUX_VERSION_CODE >= 0x02053C b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; -#else - b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel; - t = scp->target; -#endif if (scp->SCp.sent_command == -1 && b != ha->virt_bus) { ha->raw[BUS_L2P(ha,b)].io_cnt[t]--; } @@ -3666,17 +3763,21 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) /* retry */ return 2; } -#if LINUX_VERSION_CODE >= 0x020400 if (scp->SCp.Status == GDTH_MAP_SG) pci_unmap_sg(ha->pdev,scp->request_buffer, scp->use_sg,scp->SCp.Message); else if (scp->SCp.Status == GDTH_MAP_SINGLE) - pci_unmap_single(ha->pdev,scp->SCp.dma_handle, - scp->request_bufflen,scp->SCp.Message); - if (scp->SCp.buffer) - pci_unmap_single(ha->pdev,(dma_addr_t)scp->SCp.buffer, - 16,PCI_DMA_FROMDEVICE); -#endif + pci_unmap_page(ha->pdev,scp->SCp.dma_handle, + scp->request_bufflen,scp->SCp.Message); + if (scp->SCp.buffer) { + dma_addr_t addr; + addr = (dma_addr_t)*(ulong32 *)&scp->SCp.buffer; + if (scp->host_scribble) + addr += (dma_addr_t) + ((ulong64)(*(ulong32 *)&scp->host_scribble) << 32); + pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE); + } + if (ha->status == S_OK) { scp->SCp.Status = S_OK; scp->SCp.Message = ha->info; @@ -3754,10 +3855,7 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) scp->sense_buffer[2] = NOT_READY; scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); } -#if LINUX_VERSION_CODE >= 0x010300 - if (scp->done != gdth_scsi_done) -#endif - { + if (scp->done != gdth_scsi_done) { ha->dvr.size = sizeof(ha->dvr.eu.sync); ha->dvr.eu.sync.ionode = hanum; ha->dvr.eu.sync.service = service; @@ -3946,13 +4044,11 @@ static char *async_cache_tab[] = { static int gdth_async_event(int hanum) { gdth_ha_str *ha; - gdth_msg_str *msg; gdth_cmd_str *cmdp; int cmd_index; ha = HADATA(gdth_ctr_tab[hanum]); cmdp= ha->pccb; - msg = (gdth_msg_str *)ha->pscratch; TRACE2(("gdth_async_event() ha %d serv %d\n", hanum,ha->service)); @@ -3968,11 +4064,10 @@ static int gdth_async_event(int hanum) cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= MSG_INV_HANDLE; - cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; - ha->scratch_busy = TRUE; + cmdp->u.screen.su.msg.msg_addr = ha->msg_phys; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) - + sizeof(ulong32); + + sizeof(ulong64); ha->cmd_cnt = 0; gdth_copy_command(hanum); if (ha->type == GDT_EISA) @@ -4070,7 +4165,7 @@ static void gdth_log_event(gdth_evt_data *dvr, char *buffer) } #ifdef GDTH_STATISTICS -void gdth_timeout(ulong data) +static void gdth_timeout(ulong data) { ulong32 i; Scsi_Cmnd *nscp; @@ -4079,7 +4174,7 @@ void gdth_timeout(ulong data) int hanum = 0; ha = HADATA(gdth_ctr_tab[hanum]); - GDTH_LOCK_HA(ha, flags); + spin_lock_irqsave(&ha->smp_lock, flags); for (act_stats=0,i=0; icmd_tab[i].cmnd != UNUSED_CMND) @@ -4094,11 +4189,11 @@ void gdth_timeout(ulong data) gdth_timer.expires = jiffies + 30 * HZ; add_timer(&gdth_timer); - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); } #endif -GDTH_INITFUNC(void, internal_setup(char *str,int *ints)) +static void __init internal_setup(char *str,int *ints) { int i, argc; char *cur_str, *argv; @@ -4171,7 +4266,7 @@ GDTH_INITFUNC(void, internal_setup(char *str,int *ints)) } } -GDTH_INITFUNC(int, option_setup(char *str)) +int __init option_setup(char *str) { int ints[MAXHA]; char *cur = str; @@ -4189,13 +4284,18 @@ GDTH_INITFUNC(int, option_setup(char *str)) return 1; } -GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static int __init gdth_detect(struct scsi_host_template *shtp) +#else +static int __init gdth_detect(Scsi_Host_Template *shtp) +#endif { struct Scsi_Host *shp; + gdth_pci_str pcistr[MAXHA]; gdth_ha_str *ha; ulong32 isa_bios; ushort eisa_slot; - int i,hanum,cnt,ctr; + int i,hanum,cnt,ctr,err; unchar b; @@ -4218,11 +4318,11 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) TRACE(("gdth_detect()\n")); if (disable) { - printk("GDT: Controller driver disabled from command line !\n"); + printk("GDT-HA: Controller driver disabled from command line !\n"); return 0; } - printk("GDT: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR); + printk("GDT-HA: Storage RAID Controller Driver. Version: %s\n",GDTH_VERSION_STR); /* initializations */ gdth_polling = TRUE; b = 0; gdth_clear_events(); @@ -4232,6 +4332,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) /* scanning for controllers, at first: ISA controller */ for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) { dma_addr_t scratch_dma_handle; + scratch_dma_handle = 0; if (gdth_ctr_count >= MAXHA) break; @@ -4252,23 +4353,14 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n", isa_bios,ha->irq,ha->drq); -#if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) -#else - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) -#endif - { + if (request_irq(ha->irq,gdth_interrupt,IRQF_DISABLED,"gdth",ha)) { printk("GDT-ISA: Unable to allocate IRQ\n"); scsi_unregister(shp); continue; } if (request_dma(ha->drq,"gdth")) { printk("GDT-ISA: Unable to allocate DMA channel\n"); -#if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,ha); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -4286,16 +4378,20 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) ha->pccb = CMDDATA(shp); ha->ccb_phys = 0L; -#if LINUX_VERSION_CODE >= 0x020400 ha->pdev = NULL; ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, &scratch_dma_handle); - ha->scratch_phys = (ulong32)scratch_dma_handle; -#else - ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); - if (ha->pscratch) - ha->scratch_phys = virt_to_bus(ha->pscratch); + ha->scratch_phys = scratch_dma_handle; + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + ha->msg_phys = scratch_dma_handle; +#ifdef INT_COAL + ha->coal_stat = (gdth_coal_status *) + pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, &scratch_dma_handle); + ha->coal_stat_phys = scratch_dma_handle; #endif + ha->scratch_busy = FALSE; ha->req_first = NULL; ha->tid_cnt = MAX_HDRIVES; @@ -4305,23 +4401,26 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) ha->cmd_tab[i].cmnd = UNUSED_CMND; ha->scan_mode = rescan ? 0x10 : 0; - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { + if (ha->pscratch == NULL || ha->pmsg == NULL || + !gdth_search_drives(hanum)) { printk("GDT-ISA: Error during device scan\n"); --gdth_ctr_count; --gdth_ctr_vcount; - if (ha->pscratch != NULL) { -#if LINUX_VERSION_CODE >= 0x020400 + +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, + ha->coal_stat_phys); +#endif + if (ha->pscratch) pci_free_consistent(ha->pdev, GDTH_SCRATCH, ha->pscratch, ha->scratch_phys); -#else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); -#endif - } -#if LINUX_VERSION_CODE >= 0x010346 + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); + free_irq(ha->irq,ha); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -4329,13 +4428,17 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + shp->highmem_io = 0; +#endif + if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) + shp->max_cmd_len = 16; + shp->max_id = ha->tid_cnt; shp->max_lun = MAXLUN; shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) -#endif - { + if (virt_ctr) { virt_ctr = 1; /* register addit. SCSI channels as virtual controllers */ for (b = 1; b < ha->bus_cnt + 1; ++b) { @@ -4349,7 +4452,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) } } - GDTH_INIT_LOCK_HA(ha); + spin_lock_init(&ha->smp_lock); gdth_enable_int(hanum); #endif /* !__ia64__ */ } @@ -4358,6 +4461,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) /* scanning for EISA controllers */ for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) { dma_addr_t scratch_dma_handle; + scratch_dma_handle = 0; if (gdth_ctr_count >= MAXHA) break; @@ -4373,14 +4477,9 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) } /* controller found and initialized */ printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n", - eisa_slot>>12,ha->irq); + eisa_slot>>12,ha->irq); -#if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) -#else - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) -#endif - { + if (request_irq(ha->irq,gdth_interrupt,IRQF_DISABLED,"gdth",ha)) { printk("GDT-EISA: Unable to allocate IRQ\n"); scsi_unregister(shp); continue; @@ -4399,48 +4498,53 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) ha->pccb = CMDDATA(shp); ha->ccb_phys = 0L; -#if LINUX_VERSION_CODE >= 0x020400 + ha->pdev = NULL; ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, &scratch_dma_handle); - ha->scratch_phys = (ulong32) scratch_dma_handle; + ha->scratch_phys = scratch_dma_handle; + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + ha->msg_phys = scratch_dma_handle; +#ifdef INT_COAL + ha->coal_stat = (gdth_coal_status *) + pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, &scratch_dma_handle); + ha->coal_stat_phys = scratch_dma_handle; +#endif ha->ccb_phys = pci_map_single(ha->pdev,ha->pccb, sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); -#else - ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); - if (ha->pscratch) - ha->scratch_phys = virt_to_bus(ha->pscratch); - ha->ccb_phys = virt_to_bus(ha->pccb); -#endif ha->scratch_busy = FALSE; ha->req_first = NULL; ha->tid_cnt = MAX_HDRIVES; if (max_ids > 0 && max_ids < ha->tid_cnt) ha->tid_cnt = max_ids; for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; + ha->cmd_tab[i].cmnd = UNUSED_CMND; ha->scan_mode = rescan ? 0x10 : 0; - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { + if (ha->pscratch == NULL || ha->pmsg == NULL || + !gdth_search_drives(hanum)) { printk("GDT-EISA: Error during device scan\n"); --gdth_ctr_count; --gdth_ctr_vcount; - if (ha->pscratch != NULL) { -#if LINUX_VERSION_CODE >= 0x020400 +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, + ha->coal_stat_phys); +#endif + if (ha->pscratch) pci_free_consistent(ha->pdev, GDTH_SCRATCH, ha->pscratch, ha->scratch_phys); + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); + if (ha->ccb_phys) pci_unmap_single(ha->pdev,ha->ccb_phys, - sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); -#else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); -#endif - } -#if LINUX_VERSION_CODE >= 0x010346 + sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); free_irq(ha->irq,ha); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -4448,13 +4552,17 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + shp->highmem_io = 0; +#endif + if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) + shp->max_cmd_len = 16; + shp->max_id = ha->tid_cnt; shp->max_lun = MAXLUN; shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) -#endif - { + if (virt_ctr) { virt_ctr = 1; /* register addit. SCSI channels as virtual controllers */ for (b = 1; b < ha->bus_cnt + 1; ++b) { @@ -4468,131 +4576,149 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) } } - GDTH_INIT_LOCK_HA(ha); + spin_lock_init(&ha->smp_lock); gdth_enable_int(hanum); } } } /* scanning for PCI controllers */ -#if LINUX_VERSION_CODE < 0x2015C - if (pcibios_present()) -#endif - { - gdth_pci_str pcistr[MAXHA]; - - cnt = gdth_search_pci(pcistr); - printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt); - gdth_sort_pci(pcistr,cnt); - for (ctr = 0; ctr < cnt; ++ctr) { - dma_addr_t scratch_dma_handle; - - if (gdth_ctr_count >= MAXHA) - break; - shp = scsi_register(shtp,sizeof(gdth_ext_str)); - if (shp == NULL) - continue; + cnt = gdth_search_pci(pcistr); + printk("GDT-HA: Found %d PCI Storage RAID Controllers\n",cnt); + gdth_sort_pci(pcistr,cnt); + for (ctr = 0; ctr < cnt; ++ctr) { + dma_addr_t scratch_dma_handle; + scratch_dma_handle = 0; + + if (gdth_ctr_count >= MAXHA) + break; + shp = scsi_register(shtp,sizeof(gdth_ext_str)); + if (shp == NULL) + continue; - ha = HADATA(shp); - if (!gdth_init_pci(&pcistr[ctr],ha)) { - scsi_unregister(shp); - continue; - } - /* controller found and initialized */ - printk("GDT CTR%d: Configuring GDT-PCI HA at %d/%d IRQ %u\n", - ctr,pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); + ha = HADATA(shp); + if (!gdth_init_pci(&pcistr[ctr],ha)) { + scsi_unregister(shp); + continue; + } + /* controller found and initialized */ + printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n", + pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); -#if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq, gdth_interrupt, - SA_INTERRUPT|SA_SHIRQ, "gdth", ha)) -#else - if (request_irq(ha->irq, gdth_interrupt, - SA_INTERRUPT|SA_SHIRQ, "gdth")) -#endif - { - printk("GDT-PCI: Unable to allocate IRQ\n"); - scsi_unregister(shp); - continue; - } - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - hanum = gdth_ctr_count; - gdth_ctr_tab[gdth_ctr_count++] = shp; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum= 0; - - ha->pccb = CMDDATA(shp); - ha->ccb_phys = 0L; -#if LINUX_VERSION_CODE >= 0x020400 - ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, - &scratch_dma_handle); - ha->scratch_phys = (ulong32)scratch_dma_handle; -#else - ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); - if (ha->pscratch) - ha->scratch_phys = virt_to_bus(ha->pscratch); -#endif - ha->scratch_busy = FALSE; - ha->req_first = NULL; - ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES; - if (max_ids > 0 && max_ids < ha->tid_cnt) - ha->tid_cnt = max_ids; - for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; - ha->scan_mode = rescan ? 0x10 : 0; - - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { - printk("GDT-PCI: Error during device scan\n"); - --gdth_ctr_count; - --gdth_ctr_vcount; - if (ha->pscratch != NULL) { -#if LINUX_VERSION_CODE >= 0x020400 - pci_free_consistent(ha->pdev, GDTH_SCRATCH, - ha->pscratch, ha->scratch_phys); -#else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); -#endif - } -#if LINUX_VERSION_CODE >= 0x010346 - free_irq(ha->irq,ha); -#else - free_irq(ha->irq); + if (request_irq(ha->irq, gdth_interrupt, + IRQF_DISABLED|IRQF_SHARED, "gdth", ha)) + { + printk("GDT-PCI: Unable to allocate IRQ\n"); + scsi_unregister(shp); + continue; + } + shp->unchecked_isa_dma = 0; + shp->irq = ha->irq; + shp->dma_channel = 0xff; + hanum = gdth_ctr_count; + gdth_ctr_tab[gdth_ctr_count++] = shp; + gdth_ctr_vtab[gdth_ctr_vcount++] = shp; + + NUMDATA(shp)->hanum = (ushort)hanum; + NUMDATA(shp)->busnum= 0; + + ha->pccb = CMDDATA(shp); + ha->ccb_phys = 0L; + + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, + &scratch_dma_handle); + ha->scratch_phys = scratch_dma_handle; + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + ha->msg_phys = scratch_dma_handle; +#ifdef INT_COAL + ha->coal_stat = (gdth_coal_status *) + pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, &scratch_dma_handle); + ha->coal_stat_phys = scratch_dma_handle; #endif - scsi_unregister(shp); - continue; - } + ha->scratch_busy = FALSE; + ha->req_first = NULL; + ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES; + if (max_ids > 0 && max_ids < ha->tid_cnt) + ha->tid_cnt = max_ids; + for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; + ha->scan_mode = rescan ? 0x10 : 0; + + err = FALSE; + if (ha->pscratch == NULL || ha->pmsg == NULL || + !gdth_search_drives(hanum)) { + err = TRUE; + } else { if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 - shp->max_id = ha->tid_cnt; - shp->max_lun = MAXLUN; - shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + scsi_set_pci_device(shp, pcistr[ctr].pdev); #endif - { - virt_ctr = 1; - /* register addit. SCSI channels as virtual controllers */ - for (b = 1; b < ha->bus_cnt + 1; ++b) { - shp = scsi_register(shtp,sizeof(gdth_num_str)); - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum = b; + if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)|| + /* 64-bit DMA only supported from FW >= x.43 */ + (!ha->dma64_support)) { + if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { + printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum); + err = TRUE; + } + } else { + shp->max_cmd_len = 16; + if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) { + printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum); + } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { + printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum); + err = TRUE; } - } + } + } - GDTH_INIT_LOCK_HA(ha); - gdth_enable_int(hanum); + if (err) { + printk("GDT-PCI %d: Error during device scan\n", hanum); + --gdth_ctr_count; + --gdth_ctr_vcount; +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, + ha->coal_stat_phys); +#endif + if (ha->pscratch) + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); + free_irq(ha->irq,ha); + scsi_unregister(shp); + continue; } - } + shp->max_id = ha->tid_cnt; + shp->max_lun = MAXLUN; + shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; + if (virt_ctr) { + virt_ctr = 1; + /* register addit. SCSI channels as virtual controllers */ + for (b = 1; b < ha->bus_cnt + 1; ++b) { + shp = scsi_register(shtp,sizeof(gdth_num_str)); + shp->unchecked_isa_dma = 0; + shp->irq = ha->irq; + shp->dma_channel = 0xff; + gdth_ctr_vtab[gdth_ctr_vcount++] = shp; + NUMDATA(shp)->hanum = (ushort)hanum; + NUMDATA(shp)->busnum = b; + } + } + + spin_lock_init(&ha->smp_lock); + gdth_enable_int(hanum); + } + TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count)); if (gdth_ctr_count > 0) { #ifdef GDTH_STATISTICS @@ -4603,19 +4729,15 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) gdth_timer.function = gdth_timeout; add_timer(&gdth_timer); #endif -#ifdef GDTH_IOCTL_CHRDEV major = register_chrdev(0,"gdth",&gdth_fops); -#endif -#if LINUX_VERSION_CODE >= 0x020100 + notifier_disabled = 0; register_reboot_notifier(&gdth_notifier); -#endif } gdth_polling = FALSE; return gdth_ctr_vcount; } - -int gdth_release(struct Scsi_Host *shp) +static int gdth_release(struct Scsi_Host *shp) { int hanum; gdth_ha_str *ha; @@ -4624,31 +4746,34 @@ int gdth_release(struct Scsi_Host *shp) if (NUMDATA(shp)->busnum == 0) { hanum = NUMDATA(shp)->hanum; ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x010300 + if (ha->sdev) { + scsi_free_host_dev(ha->sdev); + ha->sdev = NULL; + } gdth_flush(hanum); -#endif if (shp->irq) { -#if LINUX_VERSION_CODE >= 0x010346 free_irq(shp->irq,ha); -#else - free_irq(shp->irq); -#endif } #ifndef __ia64__ if (shp->dma_channel != 0xff) { free_dma(shp->dma_channel); } #endif -#if LINUX_VERSION_CODE >= 0x020400 - pci_free_consistent(ha->pdev, GDTH_SCRATCH, - ha->pscratch, ha->scratch_phys); +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, ha->coal_stat_phys); +#endif + if (ha->pscratch) + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); if (ha->ccb_phys) pci_unmap_single(ha->pdev,ha->ccb_phys, sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); -#else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); -#endif gdth_ctr_released++; TRACE2(("gdth_release(): HA %d of %d\n", gdth_ctr_released, gdth_ctr_count)); @@ -4657,12 +4782,8 @@ int gdth_release(struct Scsi_Host *shp) #ifdef GDTH_STATISTICS del_timer(&gdth_timer); #endif -#ifdef GDTH_IOCTL_CHRDEV unregister_chrdev(major,"gdth"); -#endif -#if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); -#endif } } @@ -4703,7 +4824,7 @@ static const char *gdth_ctr_name(int hanum) return(""); } -const char *gdth_info(struct Scsi_Host *shp) +static const char *gdth_info(struct Scsi_Host *shp) { int hanum; gdth_ha_str *ha; @@ -4715,38 +4836,7 @@ const char *gdth_info(struct Scsi_Host *shp) return ((const char *)ha->binfo.type_string); } -/* old error handling */ -int gdth_abort(Scsi_Cmnd *scp) -{ - TRACE2(("gdth_abort() reason %d\n",scp->abort_reason)); - return SCSI_ABORT_SNOOZE; -} - -#if LINUX_VERSION_CODE >= 0x010346 -int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags) -#else -int gdth_reset(Scsi_Cmnd *scp) -#endif -{ - TRACE2(("gdth_reset()\n")); - return SCSI_RESET_PUNT; -} - -#if LINUX_VERSION_CODE >= 0x02015F -/* new error handling */ -int gdth_eh_abort(Scsi_Cmnd *scp) -{ - TRACE2(("gdth_eh_abort()\n")); - return FAILED; -} - -int gdth_eh_device_reset(Scsi_Cmnd *scp) -{ - TRACE2(("gdth_eh_device_reset()\n")); - return FAILED; -} - -int gdth_eh_bus_reset(Scsi_Cmnd *scp) +static int gdth_eh_bus_reset(Scsi_Cmnd *scp) { int i, hanum; gdth_ha_str *ha; @@ -4755,33 +4845,25 @@ int gdth_eh_bus_reset(Scsi_Cmnd *scp) unchar b; TRACE2(("gdth_eh_bus_reset()\n")); -#if LINUX_VERSION_CODE >= 0x02053C + hanum = NUMDATA(scp->device->host)->hanum; b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; -#else - hanum = NUMDATA(scp->host)->hanum; - b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel; -#endif ha = HADATA(gdth_ctr_tab[hanum]); /* clear command tab */ - GDTH_LOCK_HA(ha, flags); + spin_lock_irqsave(&ha->smp_lock, flags); for (i = 0; i < GDTH_MAXCMDS; ++i) { cmnd = ha->cmd_tab[i].cmnd; -#if LINUX_VERSION_CODE >= 0x02053C if (!SPECIAL_SCP(cmnd) && cmnd->device->channel == b) -#else - if (!SPECIAL_SCP(cmnd) && cmnd->channel == b) -#endif ha->cmd_tab[i].cmnd = UNUSED_CMND; } - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); if (b == ha->virt_bus) { /* host drives */ for (i = 0; i < MAX_HDRIVES; ++i) { if (ha->hdr[i].present) { - GDTH_LOCK_HA(ha, flags); + spin_lock_irqsave(&ha->smp_lock, flags); gdth_polling = TRUE; while (gdth_test_busy(hanum)) gdth_delay(0); @@ -4789,12 +4871,12 @@ int gdth_eh_bus_reset(Scsi_Cmnd *scp) GDT_CLUST_RESET, i, 0, 0)) ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED; gdth_polling = FALSE; - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); } } } else { /* raw devices */ - GDTH_LOCK_HA(ha, flags); + spin_lock_irqsave(&ha->smp_lock, flags); for (i = 0; i < MAXID; ++i) ha->raw[BUS_L2P(ha,b)].io_cnt[i] = 0; gdth_polling = TRUE; @@ -4803,25 +4885,15 @@ int gdth_eh_bus_reset(Scsi_Cmnd *scp) gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS, BUS_L2P(ha,b), 0, 0); gdth_polling = FALSE; - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); } return SUCCESS; } -int gdth_eh_host_reset(Scsi_Cmnd *scp) -{ - TRACE2(("gdth_eh_host_reset()\n")); - return FAILED; -} -#endif - - -#if LINUX_VERSION_CODE >= 0x020503 -int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip) -#elif LINUX_VERSION_CODE >= 0x010300 -int gdth_bios_param(Disk *disk,kdev_t dev,int *ip) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip) #else -int gdth_bios_param(Disk *disk,int dev,int *ip) +static int gdth_bios_param(Disk *disk,kdev_t dev,int *ip) #endif { unchar b, t; @@ -4830,7 +4902,7 @@ int gdth_bios_param(Disk *disk,int dev,int *ip) struct scsi_device *sd; unsigned capacity; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) sd = sdev; capacity = cap; #else @@ -4859,7 +4931,7 @@ int gdth_bios_param(Disk *disk,int dev,int *ip) } -int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)) +static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)) { int hanum; int priority; @@ -4872,29 +4944,35 @@ int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)) scp->SCp.sent_command = -1; scp->SCp.Status = GDTH_MAP_NONE; scp->SCp.buffer = (struct scatterlist *)NULL; -#if LINUX_VERSION_CODE >= 0x02053C + hanum = NUMDATA(scp->device->host)->hanum; -#else - hanum = NUMDATA(scp->host)->hanum; -#endif #ifdef GDTH_STATISTICS ++act_ios; #endif priority = DEFAULT_PRI; -#if LINUX_VERSION_CODE >= 0x010300 if (scp->done == gdth_scsi_done) priority = scp->SCp.this_residual; -#endif - gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6); + else + gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6); + gdth_putq( hanum, scp, priority ); gdth_next( hanum ); return 0; } -#ifdef GDTH_IOCTL_CHRDEV + static int gdth_open(struct inode *inode, struct file *filep) { + gdth_ha_str *ha; + int i; + + for (i = 0; i < gdth_ctr_count; i++) { + ha = HADATA(gdth_ctr_tab[i]); + if (!ha->sdev) + ha->sdev = scsi_get_host_dev(gdth_ctr_tab[i]); + } + TRACE(("gdth_open()\n")); return 0; } @@ -4905,542 +4983,422 @@ static int gdth_close(struct inode *inode, struct file *filep) return 0; } -static int ioc_event(unsigned long arg) +static int ioc_event(void __user *arg) { - gdth_ioctl_event evt; - gdth_ha_str *ha; - ulong flags; + gdth_ioctl_event evt; + gdth_ha_str *ha; + ulong flags; - if (copy_from_user(&evt, (char *)arg, sizeof(gdth_ioctl_event)) || - evt.ionode >= gdth_ctr_count) - return -EFAULT; - ha = HADATA(gdth_ctr_tab[evt.ionode]); - - if (evt.erase == 0xff) { - if (evt.event.event_source == ES_TEST) - evt.event.event_data.size=sizeof(evt.event.event_data.eu.test); - else if (evt.event.event_source == ES_DRIVER) - evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver); - else if (evt.event.event_source == ES_SYNC) - evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync); - else - evt.event.event_data.size=sizeof(evt.event.event_data.eu.async); - GDTH_LOCK_HA(ha, flags); - gdth_store_event(ha, evt.event.event_source, evt.event.event_idx, - &evt.event.event_data); - GDTH_UNLOCK_HA(ha, flags); - } else if (evt.erase == 0xfe) { - gdth_clear_events(); - } else if (evt.erase == 0) { - evt.handle = gdth_read_event(ha, evt.handle, &evt.event); - } else { - gdth_readapp_event(ha, evt.erase, &evt.event); - } - if (copy_to_user((char *)arg, &evt, sizeof(gdth_ioctl_event))) - return -EFAULT; - return 0; + if (copy_from_user(&evt, arg, sizeof(gdth_ioctl_event)) || + evt.ionode >= gdth_ctr_count) + return -EFAULT; + ha = HADATA(gdth_ctr_tab[evt.ionode]); + + if (evt.erase == 0xff) { + if (evt.event.event_source == ES_TEST) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.test); + else if (evt.event.event_source == ES_DRIVER) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver); + else if (evt.event.event_source == ES_SYNC) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync); + else + evt.event.event_data.size=sizeof(evt.event.event_data.eu.async); + spin_lock_irqsave(&ha->smp_lock, flags); + gdth_store_event(ha, evt.event.event_source, evt.event.event_idx, + &evt.event.event_data); + spin_unlock_irqrestore(&ha->smp_lock, flags); + } else if (evt.erase == 0xfe) { + gdth_clear_events(); + } else if (evt.erase == 0) { + evt.handle = gdth_read_event(ha, evt.handle, &evt.event); + } else { + gdth_readapp_event(ha, evt.erase, &evt.event); + } + if (copy_to_user(arg, &evt, sizeof(gdth_ioctl_event))) + return -EFAULT; + return 0; } -static int ioc_lockdrv(unsigned long arg) +static int ioc_lockdrv(void __user *arg) { - gdth_ioctl_lockdrv ldrv; - unchar i, j; - ulong flags; - gdth_ha_str *ha; + gdth_ioctl_lockdrv ldrv; + unchar i, j; + ulong flags; + gdth_ha_str *ha; - if (copy_from_user(&ldrv, (char *)arg, sizeof(gdth_ioctl_lockdrv)) || - ldrv.ionode >= gdth_ctr_count) - return -EFAULT; - ha = HADATA(gdth_ctr_tab[ldrv.ionode]); + if (copy_from_user(&ldrv, arg, sizeof(gdth_ioctl_lockdrv)) || + ldrv.ionode >= gdth_ctr_count) + return -EFAULT; + ha = HADATA(gdth_ctr_tab[ldrv.ionode]); - for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) { - j = ldrv.drives[i]; - if (j >= MAX_HDRIVES || !ha->hdr[j].present) - continue; - if (ldrv.lock) { - GDTH_LOCK_HA(ha, flags); - ha->hdr[j].lock = 1; - GDTH_UNLOCK_HA(ha, flags); - gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j); - gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j); - } else { - GDTH_LOCK_HA(ha, flags); - ha->hdr[j].lock = 0; - GDTH_UNLOCK_HA(ha, flags); - gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j); - gdth_next(ldrv.ionode); - } - } - return 0; + for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) { + j = ldrv.drives[i]; + if (j >= MAX_HDRIVES || !ha->hdr[j].present) + continue; + if (ldrv.lock) { + spin_lock_irqsave(&ha->smp_lock, flags); + ha->hdr[j].lock = 1; + spin_unlock_irqrestore(&ha->smp_lock, flags); + gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j); + gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j); + } else { + spin_lock_irqsave(&ha->smp_lock, flags); + ha->hdr[j].lock = 0; + spin_unlock_irqrestore(&ha->smp_lock, flags); + gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j); + gdth_next(ldrv.ionode); + } + } + return 0; } -static int ioc_resetdrv(unsigned long arg, char *cmnd) +static int ioc_resetdrv(void __user *arg, char *cmnd) { - gdth_ioctl_reset res; - gdth_cmd_str cmd; - int hanum; - gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; -#else - Scsi_Cmnd scp; - Scsi_Device sdev; -#endif + gdth_ioctl_reset res; + gdth_cmd_str cmd; + int hanum; + gdth_ha_str *ha; + int rval; - if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) || - res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES) - return -EFAULT; - hanum = res.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); + if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) || + res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES) + return -EFAULT; + hanum = res.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); - if (!ha->hdr[res.number].present) - return 0; - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_CLUST_RESET; - cmd.u.cache.DeviceNo = res.number; -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &cmd, cmnd, 30); - res.status = (ushort)srp->sr_command->SCp.Status; - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &cmd, cmnd, 30); - res.status = (ushort)scp->SCp.Status; - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#else - memset(&sdev,0,sizeof(Scsi_Device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; - gdth_do_cmd(&scp, &cmd, cmnd, 30); - res.status = (ushort)scp.SCp.Status; -#endif - if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset))) - return -EFAULT; + if (!ha->hdr[res.number].present) return 0; + memset(&cmd, 0, sizeof(gdth_cmd_str)); + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_CLUST_RESET; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = res.number; + else + cmd.u.cache.DeviceNo = res.number; + + rval = __gdth_execute(ha->sdev, &cmd, cmnd, 30, NULL); + if (rval < 0) + return rval; + res.status = rval; + + if (copy_to_user(arg, &res, sizeof(gdth_ioctl_reset))) + return -EFAULT; + return 0; } -static int ioc_general(unsigned long arg, char *cmnd) +static int ioc_general(void __user *arg, char *cmnd) { - gdth_ioctl_general gen; - char *buf = NULL; - ulong32 paddr; - int hanum; - gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; -#else - Scsi_Cmnd scp; - Scsi_Device sdev; -#endif + gdth_ioctl_general gen; + char *buf = NULL; + ulong64 paddr; + int hanum; + gdth_ha_str *ha; + int rval; - if (copy_from_user(&gen, (char *)arg, sizeof(gdth_ioctl_general)) || - gen.ionode >= gdth_ctr_count) + if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)) || + gen.ionode >= gdth_ctr_count) + return -EFAULT; + hanum = gen.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); + if (gen.data_len + gen.sense_len != 0) { + if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len, + FALSE, &paddr))) return -EFAULT; - hanum = gen.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); - if (gen.data_len + gen.sense_len != 0) { - if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len, - FALSE, &paddr))) - return -EFAULT; - if (copy_from_user(buf, (char *)arg + sizeof(gdth_ioctl_general), - gen.data_len + gen.sense_len)) { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); - return -EFAULT; - } + if (copy_from_user(buf, arg + sizeof(gdth_ioctl_general), + gen.data_len + gen.sense_len)) { + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + return -EFAULT; + } - if (gen.command.OpCode == GDT_IOCTL) { - gen.command.u.ioctl.p_param = paddr; - } else if (gen.command.Service == CACHESERVICE) { + if (gen.command.OpCode == GDT_IOCTL) { + gen.command.u.ioctl.p_param = paddr; + } else if (gen.command.Service == CACHESERVICE) { + if (ha->cache_feat & GDT_64BIT) { + /* copy elements from 32-bit IOCTL structure */ + gen.command.u.cache64.BlockCnt = gen.command.u.cache.BlockCnt; + gen.command.u.cache64.BlockNo = gen.command.u.cache.BlockNo; + gen.command.u.cache64.DeviceNo = gen.command.u.cache.DeviceNo; + /* addresses */ + if (ha->cache_feat & SCATTER_GATHER) { + gen.command.u.cache64.DestAddr = (ulong64)-1; + gen.command.u.cache64.sg_canz = 1; + gen.command.u.cache64.sg_lst[0].sg_ptr = paddr; + gen.command.u.cache64.sg_lst[0].sg_len = gen.data_len; + gen.command.u.cache64.sg_lst[1].sg_len = 0; + } else { + gen.command.u.cache64.DestAddr = paddr; + gen.command.u.cache64.sg_canz = 0; + } + } else { if (ha->cache_feat & SCATTER_GATHER) { gen.command.u.cache.DestAddr = 0xffffffff; gen.command.u.cache.sg_canz = 1; - gen.command.u.cache.sg_lst[0].sg_ptr = paddr; + gen.command.u.cache.sg_lst[0].sg_ptr = (ulong32)paddr; gen.command.u.cache.sg_lst[0].sg_len = gen.data_len; gen.command.u.cache.sg_lst[1].sg_len = 0; } else { gen.command.u.cache.DestAddr = paddr; gen.command.u.cache.sg_canz = 0; } - } else if (gen.command.Service == SCSIRAWSERVICE) { + } + } else if (gen.command.Service == SCSIRAWSERVICE) { + if (ha->raw_feat & GDT_64BIT) { + /* copy elements from 32-bit IOCTL structure */ + char cmd[16]; + gen.command.u.raw64.sense_len = gen.command.u.raw.sense_len; + gen.command.u.raw64.bus = gen.command.u.raw.bus; + gen.command.u.raw64.lun = gen.command.u.raw.lun; + gen.command.u.raw64.target = gen.command.u.raw.target; + memcpy(cmd, gen.command.u.raw.cmd, 16); + memcpy(gen.command.u.raw64.cmd, cmd, 16); + gen.command.u.raw64.clen = gen.command.u.raw.clen; + gen.command.u.raw64.sdlen = gen.command.u.raw.sdlen; + gen.command.u.raw64.direction = gen.command.u.raw.direction; + /* addresses */ + if (ha->raw_feat & SCATTER_GATHER) { + gen.command.u.raw64.sdata = (ulong64)-1; + gen.command.u.raw64.sg_ranz = 1; + gen.command.u.raw64.sg_lst[0].sg_ptr = paddr; + gen.command.u.raw64.sg_lst[0].sg_len = gen.data_len; + gen.command.u.raw64.sg_lst[1].sg_len = 0; + } else { + gen.command.u.raw64.sdata = paddr; + gen.command.u.raw64.sg_ranz = 0; + } + gen.command.u.raw64.sense_data = paddr + gen.data_len; + } else { if (ha->raw_feat & SCATTER_GATHER) { gen.command.u.raw.sdata = 0xffffffff; gen.command.u.raw.sg_ranz = 1; - gen.command.u.raw.sg_lst[0].sg_ptr = paddr; + gen.command.u.raw.sg_lst[0].sg_ptr = (ulong32)paddr; gen.command.u.raw.sg_lst[0].sg_len = gen.data_len; gen.command.u.raw.sg_lst[1].sg_len = 0; } else { gen.command.u.raw.sdata = paddr; gen.command.u.raw.sg_ranz = 0; } - gen.command.u.raw.sense_data = paddr + gen.data_len; - - } else { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); - return -EFAULT; + gen.command.u.raw.sense_data = (ulong32)paddr + gen.data_len; } - } - -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &gen.command, cmnd, gen.timeout); - gen.status = srp->sr_command->SCp.Status; - gen.info = srp->sr_command->SCp.Message; - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout); - gen.status = scp->SCp.Status; - gen.info = scp->SCp.Message; - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#else - memset(&sdev,0,sizeof(Scsi_Device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; - gdth_do_cmd(&scp, &gen.command, cmnd, gen.timeout); - gen.status = scp.SCp.Status; - gen.info = scp.SCp.Message; -#endif - - if (copy_to_user((char *)arg + sizeof(gdth_ioctl_general), buf, - gen.data_len + gen.sense_len)) { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); - return -EFAULT; - } - if (copy_to_user((char *)arg, &gen, - sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) { + } else { gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); return -EFAULT; } + } + + rval = __gdth_execute(ha->sdev, &gen.command, cmnd, gen.timeout, &gen.info); + if (rval < 0) + return rval; + gen.status = rval; + + if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf, + gen.data_len + gen.sense_len)) { gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); - return 0; + return -EFAULT; + } + if (copy_to_user(arg, &gen, + sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) { + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + return -EFAULT; + } + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + return 0; } -static int ioc_hdrlist(unsigned long arg, char *cmnd) +static int ioc_hdrlist(void __user *arg, char *cmnd) { - gdth_ioctl_rescan rsc; - gdth_cmd_str cmd; - gdth_ha_str *ha; - unchar i; - int hanum; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; -#else - Scsi_Cmnd scp; - Scsi_Device sdev; -#endif - - if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) || - rsc.ionode >= gdth_ctr_count) - return -EFAULT; - hanum = rsc.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); + gdth_ioctl_rescan *rsc; + gdth_cmd_str *cmd; + gdth_ha_str *ha; + unchar i; + int hanum, rc = -ENOMEM; + u32 cluster_type = 0; + + rsc = kmalloc(sizeof(*rsc), GFP_KERNEL); + cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); + if (!rsc || !cmd) + goto free_fail; + + if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) || + rsc->ionode >= gdth_ctr_count) { + rc = -EFAULT; + goto free_fail; + } + hanum = rsc->ionode; + ha = HADATA(gdth_ctr_tab[hanum]); + memset(cmd, 0, sizeof(gdth_cmd_str)); -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; -#else - memset(&sdev,0,sizeof(Scsi_Device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; -#endif - - for (i = 0; i < MAX_HDRIVES; ++i) { - if (!ha->hdr[i].present) { - rsc.hdr_list[i].bus = 0xff; - continue; - } - rsc.hdr_list[i].bus = ha->virt_bus; - rsc.hdr_list[i].target = i; - rsc.hdr_list[i].lun = 0; - rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type; - if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) { - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_CLUST_INFO; - cmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - if (srp->sr_command->SCp.Status == S_OK) - rsc.hdr_list[i].cluster_type = srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - if (scp->SCp.Status == S_OK) - rsc.hdr_list[i].cluster_type = scp->SCp.Message; -#else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - if (scp.SCp.Status == S_OK) - rsc.hdr_list[i].cluster_type = scp.SCp.Message; -#endif - } + for (i = 0; i < MAX_HDRIVES; ++i) { + if (!ha->hdr[i].present) { + rsc->hdr_list[i].bus = 0xff; + continue; } -#if LINUX_VERSION_CODE >= 0x020503 - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#endif - - if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) - return -EFAULT; - return 0; + rsc->hdr_list[i].bus = ha->virt_bus; + rsc->hdr_list[i].target = i; + rsc->hdr_list[i].lun = 0; + rsc->hdr_list[i].cluster_type = ha->hdr[i].cluster_type; + if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) { + cmd->Service = CACHESERVICE; + cmd->OpCode = GDT_CLUST_INFO; + if (ha->cache_feat & GDT_64BIT) + cmd->u.cache64.DeviceNo = i; + else + cmd->u.cache.DeviceNo = i; + if (__gdth_execute(ha->sdev, cmd, cmnd, 30, &cluster_type) == S_OK) + rsc->hdr_list[i].cluster_type = cluster_type; + } + } + + if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan))) + rc = -EFAULT; + else + rc = 0; + +free_fail: + kfree(rsc); + kfree(cmd); + return rc; } -static int ioc_rescan(unsigned long arg, char *cmnd) +static int ioc_rescan(void __user *arg, char *cmnd) { - gdth_ioctl_rescan rsc; - gdth_cmd_str cmd; - ushort i, status, hdr_cnt; - ulong32 info; - int hanum, cyls, hds, secs; - ulong flags; - gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; -#else - Scsi_Cmnd scp; - Scsi_Device sdev; -#endif - - if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) || - rsc.ionode >= gdth_ctr_count) - return -EFAULT; - hanum = rsc.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); + gdth_ioctl_rescan *rsc; + gdth_cmd_str *cmd; + ushort i, status, hdr_cnt; + ulong32 info; + int hanum, cyls, hds, secs; + int rc = -ENOMEM; + ulong flags; + gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; -#else - memset(&sdev,0,sizeof(Scsi_Device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; -#endif - - if (rsc.flag == 0) { - /* old method: re-init. cache service */ - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_INIT; - cmd.u.cache.DeviceNo = LINUX_OS; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - i = 0; - hdr_cnt = (status == S_OK ? (ushort)info : 0); + rsc = kmalloc(sizeof(*rsc), GFP_KERNEL); + cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd || !rsc) + goto free_fail; + + if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) || + rsc->ionode >= gdth_ctr_count) { + rc = -EFAULT; + goto free_fail; + } + hanum = rsc->ionode; + ha = HADATA(gdth_ctr_tab[hanum]); + memset(cmd, 0, sizeof(gdth_cmd_str)); + + if (rsc->flag == 0) { + /* old method: re-init. cache service */ + cmd->Service = CACHESERVICE; + if (ha->cache_feat & GDT_64BIT) { + cmd->OpCode = GDT_X_INIT_HOST; + cmd->u.cache64.DeviceNo = LINUX_OS; } else { - i = rsc.hdr_no; - hdr_cnt = i + 1; + cmd->OpCode = GDT_INIT; + cmd->u.cache.DeviceNo = LINUX_OS; } - for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) { - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_INFO; - cmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - rsc.hdr_list[i].bus = ha->virt_bus; - rsc.hdr_list[i].target = i; - rsc.hdr_list[i].lun = 0; - if (status != S_OK) { - ha->hdr[i].present = FALSE; - } else { - ha->hdr[i].present = TRUE; - ha->hdr[i].size = info; - /* evaluate mapping */ - ha->hdr[i].size &= ~SECS32; - gdth_eval_mapping(ha->hdr[i].size,&cyls,&hds,&secs); - ha->hdr[i].heads = hds; - ha->hdr[i].secs = secs; - /* round size */ - ha->hdr[i].size = cyls * hds * secs; - } - GDTH_UNLOCK_HA(ha, flags); - if (status != S_OK) - continue; - - /* devtype, cluster info, R/W attribs */ - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_DEVTYPE; - cmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0); - GDTH_UNLOCK_HA(ha, flags); - - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_CLUST_INFO; - cmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[i].cluster_type = - ((status == S_OK && !shared_access) ? (ushort)info : 0); - GDTH_UNLOCK_HA(ha, flags); - rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type; - - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_RW_ATTRIBS; - cmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0); - GDTH_UNLOCK_HA(ha, flags); + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + i = 0; + hdr_cnt = (status == S_OK ? (ushort)info : 0); + } else { + i = rsc->hdr_no; + hdr_cnt = i + 1; + } + + for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) { + cmd->Service = CACHESERVICE; + cmd->OpCode = GDT_INFO; + if (ha->cache_feat & GDT_64BIT) + cmd->u.cache64.DeviceNo = i; + else + cmd->u.cache.DeviceNo = i; + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + + spin_lock_irqsave(&ha->smp_lock, flags); + rsc->hdr_list[i].bus = ha->virt_bus; + rsc->hdr_list[i].target = i; + rsc->hdr_list[i].lun = 0; + if (status != S_OK) { + ha->hdr[i].present = FALSE; + } else { + ha->hdr[i].present = TRUE; + ha->hdr[i].size = info; + /* evaluate mapping */ + ha->hdr[i].size &= ~SECS32; + gdth_eval_mapping(ha->hdr[i].size,&cyls,&hds,&secs); + ha->hdr[i].heads = hds; + ha->hdr[i].secs = secs; + /* round size */ + ha->hdr[i].size = cyls * hds * secs; } -#if LINUX_VERSION_CODE >= 0x020503 - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#endif + spin_unlock_irqrestore(&ha->smp_lock, flags); + if (status != S_OK) + continue; + + /* extended info, if GDT_64BIT, for drives > 2 TB */ + /* but we need ha->info2, not yet stored in scp->SCp */ + + /* devtype, cluster info, R/W attribs */ + cmd->Service = CACHESERVICE; + cmd->OpCode = GDT_DEVTYPE; + if (ha->cache_feat & GDT_64BIT) + cmd->u.cache64.DeviceNo = i; + else + cmd->u.cache.DeviceNo = i; + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + + spin_lock_irqsave(&ha->smp_lock, flags); + ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0); + spin_unlock_irqrestore(&ha->smp_lock, flags); + + cmd->Service = CACHESERVICE; + cmd->OpCode = GDT_CLUST_INFO; + if (ha->cache_feat & GDT_64BIT) + cmd->u.cache64.DeviceNo = i; + else + cmd->u.cache.DeviceNo = i; + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + + spin_lock_irqsave(&ha->smp_lock, flags); + ha->hdr[i].cluster_type = + ((status == S_OK && !shared_access) ? (ushort)info : 0); + spin_unlock_irqrestore(&ha->smp_lock, flags); + rsc->hdr_list[i].cluster_type = ha->hdr[i].cluster_type; + + cmd->Service = CACHESERVICE; + cmd->OpCode = GDT_RW_ATTRIBS; + if (ha->cache_feat & GDT_64BIT) + cmd->u.cache64.DeviceNo = i; + else + cmd->u.cache.DeviceNo = i; + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + + spin_lock_irqsave(&ha->smp_lock, flags); + ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0); + spin_unlock_irqrestore(&ha->smp_lock, flags); + } - if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) - return -EFAULT; - return 0; + if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan))) + rc = -EFAULT; + else + rc = 0; + +free_fail: + kfree(rsc); + kfree(cmd); + return rc; } static int gdth_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Cmnd *scp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 Scsi_Cmnd *scp; - Scsi_Device *sdev; -#else - Scsi_Cmnd scp; - Scsi_Device sdev; -#endif ulong flags; char cmnd[MAX_COMMAND_SIZE]; + void __user *argp = (void __user *)arg; memset(cmnd, 0xff, 12); @@ -5450,16 +5408,16 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, case GDTIOCTL_CTRCNT: { int cnt = gdth_ctr_count; - if (put_user(cnt, (int *)arg)) - return -EFAULT; + if (put_user(cnt, (int __user *)argp)) + return -EFAULT; break; } case GDTIOCTL_DRVERS: { int ver = (GDTH_VERSION<<8) | GDTH_SUBVERSION; - if (put_user(ver, (int *)arg)) - return -EFAULT; + if (put_user(ver, (int __user *)argp)) + return -EFAULT; break; } @@ -5470,8 +5428,8 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, osv.version = (unchar)(LINUX_VERSION_CODE >> 16); osv.subversion = (unchar)(LINUX_VERSION_CODE >> 8); osv.revision = (ushort)(LINUX_VERSION_CODE & 0xff); - if (copy_to_user((char *)arg, &osv, sizeof(gdth_ioctl_osvers))) - return -EFAULT; + if (copy_to_user(argp, &osv, sizeof(gdth_ioctl_osvers))) + return -EFAULT; break; } @@ -5479,7 +5437,7 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, { gdth_ioctl_ctrtype ctrt; - if (copy_from_user(&ctrt, (char *)arg, sizeof(gdth_ioctl_ctrtype)) || + if (copy_from_user(&ctrt, argp, sizeof(gdth_ioctl_ctrtype)) || ctrt.ionode >= gdth_ctr_count) return -EFAULT; ha = HADATA(gdth_ctr_tab[ctrt.ionode]); @@ -5501,26 +5459,26 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, } ctrt.info = ha->brd_phys; ctrt.oem_id = ha->oem_id; - if (copy_to_user((char *)arg, &ctrt, sizeof(gdth_ioctl_ctrtype))) + if (copy_to_user(argp, &ctrt, sizeof(gdth_ioctl_ctrtype))) return -EFAULT; break; } case GDTIOCTL_GENERAL: - return ioc_general(arg, cmnd); + return ioc_general(argp, cmnd); case GDTIOCTL_EVENT: - return ioc_event(arg); + return ioc_event(argp); case GDTIOCTL_LOCKDRV: - return ioc_lockdrv(arg); + return ioc_lockdrv(argp); case GDTIOCTL_LOCKCHN: { gdth_ioctl_lockchn lchn; unchar i, j; - if (copy_from_user(&lchn, (char *)arg, sizeof(gdth_ioctl_lockchn)) || + if (copy_from_user(&lchn, argp, sizeof(gdth_ioctl_lockchn)) || lchn.ionode >= gdth_ctr_count) return -EFAULT; ha = HADATA(gdth_ctr_tab[lchn.ionode]); @@ -5528,17 +5486,17 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, i = lchn.channel; if (i < ha->bus_cnt) { if (lchn.lock) { - GDTH_LOCK_HA(ha, flags); + spin_lock_irqsave(&ha->smp_lock, flags); ha->raw[i].lock = 1; - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); for (j = 0; j < ha->tid_cnt; ++j) { gdth_wait_completion(lchn.ionode, i, j); gdth_stop_timeout(lchn.ionode, i, j); } } else { - GDTH_LOCK_HA(ha, flags); + spin_lock_irqsave(&ha->smp_lock, flags); ha->raw[i].lock = 0; - GDTH_UNLOCK_HA(ha, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); for (j = 0; j < ha->tid_cnt; ++j) { gdth_start_timeout(lchn.ionode, i, j); gdth_next(lchn.ionode); @@ -5549,41 +5507,36 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, } case GDTIOCTL_RESCAN: - return ioc_rescan(arg, cmnd); + return ioc_rescan(argp, cmnd); case GDTIOCTL_HDRLIST: - return ioc_hdrlist(arg, cmnd); + return ioc_hdrlist(argp, cmnd); case GDTIOCTL_RESET_BUS: { gdth_ioctl_reset res; int hanum, rval; - if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) || + if (copy_from_user(&res, argp, sizeof(gdth_ioctl_reset)) || res.ionode >= gdth_ctr_count) return -EFAULT; hanum = res.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); - /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.5.x */ -#if LINUX_VERSION_CODE >= 0x02053C - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_get_command(sdev, GFP_KERNEL); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + scp = kmalloc(sizeof(*scp), GFP_KERNEL); if (!scp) return -ENOMEM; + memset(scp, 0, sizeof(*scp)); + scp->device = ha->sdev; scp->cmd_len = 12; scp->use_sg = 0; scp->device->channel = virt_ctr ? 0 : res.number; rval = gdth_eh_bus_reset(scp); res.status = (rval == SUCCESS ? S_OK : S_GENERR); - scsi_put_command(scp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x020503 - scp = scsi_allocate_device(sdev, 1); + kfree(scp); #else - scp = scsi_allocate_device(sdev, 1, FALSE); -#endif + scp = scsi_allocate_device(ha->sdev, 1, FALSE); if (!scp) return -ENOMEM; scp->cmd_len = 12; @@ -5592,143 +5545,73 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, rval = gdth_eh_bus_reset(scp); res.status = (rval == SUCCESS ? S_OK : S_GENERR); scsi_release_command(scp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x02015F - memset(&sdev,0,sizeof(Scsi_Device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; - scp.channel = virt_ctr ? 0 : res.number; - rval = gdth_eh_bus_reset(&scp); - res.status = (rval == SUCCESS ? S_OK : S_GENERR); -#else - res.status = S_OK; #endif - if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset))) + if (copy_to_user(argp, &res, sizeof(gdth_ioctl_reset))) return -EFAULT; break; } case GDTIOCTL_RESET_DRV: - return ioc_resetdrv(arg, cmnd); + return ioc_resetdrv(argp, cmnd); default: break; } return 0; } -#endif -#if LINUX_VERSION_CODE >= 0x010300 + /* flush routine */ static void gdth_flush(int hanum) { int i; gdth_ha_str *ha; gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; -#else - Scsi_Cmnd scp; - Scsi_Device sdev; -#endif char cmnd[MAX_COMMAND_SIZE]; memset(cmnd, 0xff, MAX_COMMAND_SIZE); TRACE2(("gdth_flush() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return; - scp->cmd_len = 12; - scp->use_sg = 0; -#else - memset(&sdev,0,sizeof(Scsi_Device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; -#endif - for (i = 0; i < MAX_HDRIVES; ++i) { if (ha->hdr[i].present) { gdtcmd.BoardNode = LOCALBOARD; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_FLUSH; - gdtcmd.u.cache.DeviceNo = i; - gdtcmd.u.cache.BlockNo = 1; - gdtcmd.u.cache.sg_canz = 0; + if (ha->cache_feat & GDT_64BIT) { + gdtcmd.u.cache64.DeviceNo = i; + gdtcmd.u.cache64.BlockNo = 1; + gdtcmd.u.cache64.sg_canz = 0; + } else { + gdtcmd.u.cache.DeviceNo = i; + gdtcmd.u.cache.BlockNo = 1; + gdtcmd.u.cache.sg_canz = 0; + } TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i)); -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &gdtcmd, cmnd, 30); -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); -#endif + + gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 30, NULL); } } -#if LINUX_VERSION_CODE >= 0x020503 - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#endif } /* shutdown routine */ -#if LINUX_VERSION_CODE >= 0x020100 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) -#else -void gdth_halt(void) -#endif { int hanum; #ifndef __alpha__ gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; -#else - Scsi_Cmnd scp; - Scsi_Device sdev; -#endif char cmnd[MAX_COMMAND_SIZE]; #endif -#if LINUX_VERSION_CODE >= 0x020100 + if (notifier_disabled) + return NOTIFY_OK; + TRACE2(("gdth_halt() event %d\n",(int)event)); if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) return NOTIFY_DONE; -#else - TRACE2(("gdth_halt()\n")); - if (halt_called) { - TRACE2(("already called\n")); - return; - } - halt_called = TRUE; -#endif - printk("GDT: Flushing all host drives .. "); + notifier_disabled = 1; + printk("GDT-HA: Flushing all host drives .. "); for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { gdth_flush(hanum); @@ -5739,46 +5622,7 @@ void gdth_halt(void) gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_RESET; TRACE2(("gdth_halt(): reset controller %d\n", hanum)); -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) { -#if LINUX_VERSION_CODE >= 0x020100 - unregister_reboot_notifier(&gdth_notifier); - return NOTIFY_OK; -#else - return; -#endif - } - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &gdtcmd, cmnd, 10); - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) { -#if LINUX_VERSION_CODE >= 0x020100 - unregister_reboot_notifier(&gdth_notifier); - return NOTIFY_OK; -#else - return; -#endif - } - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &gdtcmd, cmnd, 10); - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#else - memset(&sdev,0,sizeof(Scsi_Device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; - gdth_do_cmd(&scp, &gdtcmd, cmnd, 10); -#endif + gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 10, NULL); #endif } printk("Done.\n"); @@ -5786,50 +5630,48 @@ void gdth_halt(void) #ifdef GDTH_STATISTICS del_timer(&gdth_timer); #endif -#if LINUX_VERSION_CODE >= 0x020100 - unregister_reboot_notifier(&gdth_notifier); return NOTIFY_OK; -#endif } -#endif - -#if LINUX_VERSION_CODE < 0x020400 && !defined(MODULE) - -GDTH_INITFUNC(void, gdth_setup(char *str,int *ints)) -{ - TRACE2(("gdth_setup() str %s ints[0] %d\n", - str ? str:"NULL", ints ? ints[0]:0)); - internal_setup(str, ints); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +/* configure lun */ +static int gdth_slave_configure(struct scsi_device *sdev) +{ + scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); + sdev->skip_ms_page_3f = 1; + sdev->skip_ms_page_8 = 1; + return 0; } +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static struct scsi_host_template driver_template = { #else - static Scsi_Host_Template driver_template = { -#if LINUX_VERSION_CODE >= 0x02015F - .proc_name = "gdth", -#else - .proc_dir = &proc_scsi_gdth, #endif - .proc_info = gdth_proc_info, - .name = "GDT SCSI Disk Array Controller", - .detect = gdth_detect, - .release = gdth_release, - .info = gdth_info, - .queuecommand = gdth_queuecommand, - .eh_abort_handler = gdth_eh_abort, - .eh_device_reset_handler = gdth_eh_device_reset, - .eh_bus_reset_handler = gdth_eh_bus_reset, - .eh_host_reset_handler = gdth_eh_host_reset, - .bios_param = gdth_bios_param, - .can_queue = GDTH_MAXCMDS, - .this_id = -1, - .sg_tablesize = GDTH_MAXSG, - .cmd_per_lun = GDTH_MAXC_P_L, - .unchecked_isa_dma = 1, - .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE < 0x020501 - .use_new_eh_code = 1, + .proc_name = "gdth", + .proc_info = gdth_proc_info, + .name = "GDT SCSI Disk Array Controller", + .detect = gdth_detect, + .release = gdth_release, + .info = gdth_info, + .queuecommand = gdth_queuecommand, + .eh_bus_reset_handler = gdth_eh_bus_reset, + .bios_param = gdth_bios_param, + .can_queue = GDTH_MAXCMDS, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + .slave_configure = gdth_slave_configure, +#endif + .this_id = -1, + .sg_tablesize = GDTH_MAXSG, + .cmd_per_lun = GDTH_MAXC_P_L, + .unchecked_isa_dma = 1, + .use_clustering = ENABLE_CLUSTERING, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + .use_new_eh_code = 1, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) + .highmem_io = 1, +#endif #endif }; @@ -5837,5 +5679,3 @@ static Scsi_Host_Template driver_template = { #ifndef MODULE __setup("gdth=", option_setup); #endif - -#endif