Commit c83b4e61 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] gdth update from Intel

parent 8c8373b4
......@@ -4,7 +4,7 @@
* Intel Corporation: Storage RAID Controllers *
* *
* gdth.c *
* Copyright (C) 1995-02 ICP vortex, an Intel company, Achim Leubner *
* Copyright (C) 1995-03 ICP vortex, an Intel company, Achim Leubner *
* <achim.leubner@intel.com> *
* *
* Additions/Fixes: Boji Tony Kannanthanam *
......@@ -24,11 +24,17 @@
* 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.18 *
* Tested with Linux 1.2.13, ..., 2.2.20, ..., 2.4.20 *
* *
* $Log: gdth.c,v $
* Revision 1.61 2002/10/03 09:35:22 boji
* Fixed SCREENSERVICE initialisation in SMP cases.
* Revision 1.62 2003/02/27 15:01:59 achim
* Dynamic DMA mapping implemented
* New (character device) IOCTL interface added
* Other controller related changes made
*
* Revision 1.61 2002/11/08 13:09:52 boji
* Added support for XSCALE based RAID Controllers
* Fixed SCREENSERVICE initialization in SMP cases
* Added checks for gdth_polling before GDTH_HA_LOCK
*
* Revision 1.60 2002/02/05 09:35:22 achim
......@@ -216,7 +222,7 @@
*
* Revision 1.9 1997/09/04 10:07:25 achim
* IO-mapping with virt_to_bus(), gdth_readb(), gdth_writeb(), ...
* register_reboot_notifier() to get a notify on shutdown used
* register_reboot_notifier() to get a notify on shutown used
*
* Revision 1.8 1997/04/02 12:14:30 achim
* Version 1.00 (see gdth.h), tested with kernel 2.0.29
......@@ -248,7 +254,7 @@
* Initial revision
*
************************************************************************/
#ident "$Id: gdth.c,v 1.60 2002/02/05 09:35:22 achim Exp $"
#ident "$Id: gdth.c,v 1.62 2003/02/27 15:01:59 achim Exp $"
/* All GDT Disk Array Controllers are fully supported by this driver.
* This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
......@@ -300,18 +306,21 @@
*/
/* The meaning of the Scsi_Pointer members in this driver is as follows:
* ptr: Chaining
* this_residual: Command priority
* buffer: Unused
* buffers_residual: Timeout value
* Status: Command status (gdth_do_cmd())
* Message: Additional info (gdth_do_cmd())
* have_data_in: Flag for gdth_wait_completion()
* sent_command: Opcode special command
* phase: Service/parameter/return code special command
* ptr: Chaining
* this_residual: Command priority
* buffer: phys. DMA sense buffer
* dma_handle: phys. DMA buffer (kernel >= 2.4.0)
* buffers_residual: Timeout value
* Status: Command status (gdth_do_cmd()), DMA mem. mappings
* Message: Additional info (gdth_do_cmd()), DMA direction
* have_data_in: Flag for gdth_wait_completion()
* sent_command: Opcode special command
* phase: Service/parameter/return code special command
*/
#error Please convert me to Documentation/DMA-mapping.txt
/* default: activate /proc and character device IOCTL interface */
#define GDTH_IOCTL_PROC
#define GDTH_IOCTL_CHRDEV
#include <linux/module.h>
......@@ -324,6 +333,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/in.h>
#include <linux/proc_fs.h>
#include <linux/time.h>
......@@ -340,6 +350,7 @@
#include <asm/dma.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#if LINUX_VERSION_CODE >= 0x020322
#include <linux/spinlock.h>
#elif LINUX_VERSION_CODE >= 0x02015F
......@@ -353,6 +364,9 @@
#endif
#include "scsi.h"
#include "hosts.h"
#if LINUX_VERSION_CODE < 0x020503
#include "sd.h"
#endif
#include "gdth.h"
......@@ -378,7 +392,8 @@ static void gdth_readapp_event(gdth_ha_str *ha, unchar application,
gdth_evt_str *estr);
static void gdth_clear_events(void);
static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count);
static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
char *buffer,ushort count);
static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp);
static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive);
......@@ -408,6 +423,13 @@ 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
......@@ -604,6 +626,9 @@ 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 */
......@@ -641,24 +666,35 @@ static unchar gdth_direction_tab[0x100] = {
#define __init
#endif
#if LINUX_VERSION_CODE >= 0x02015F
#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(dev, flags) spin_lock_irqsave(dev->host_lock,flags)
#define GDTH_UNLOCK_SCSI_DONE(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)
#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(dev, flags) do {} while (0)
#define GDTH_UNLOCK_SCSI_DONE(dev, flags) do {} while (0)
#define GDTH_LOCK_SCSI_DOCMD(dev) do {} while (0)
#define GDTH_UNLOCK_SCSI_DOCMD(dev) do {} 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 */
......@@ -702,10 +738,21 @@ MODULE_PARM(rescan, "i");
MODULE_PARM(virt_ctr, "i");
MODULE_PARM(shared_access, "i");
MODULE_AUTHOR("Achim Leubner");
#endif
#if LINUX_VERSION_CODE >= 0x02040B
MODULE_LICENSE("GPL");
#endif
#endif
#ifdef GDTH_IOCTL_CHRDEV
/* ioctl interface */
static struct file_operations gdth_fops = {
ioctl:gdth_ioctl,
open:gdth_open,
release:gdth_close,
};
#endif
/* /proc support */
#if LINUX_VERSION_CODE >= 0x010300
#include <linux/stat.h>
......@@ -813,6 +860,8 @@ GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr))
PCI_DEVICE_ID_VORTEX_GDTNEWRX);
gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_SRC);
gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_SRC_XSCALE);
return cnt;
}
......@@ -820,10 +869,11 @@ GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr))
/* 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[] = {
{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 },
{0}
static struct pci_device_id gdthtable[] __devinitdata = {
{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
......@@ -1235,6 +1285,9 @@ 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));
......@@ -1511,6 +1564,11 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
PCI_ROM_ADDRESS, rom_addr);
#endif
/* 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 )
gdth_delay(1);
/* check and reset interface area */
dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
......@@ -1840,7 +1898,7 @@ static void gdth_release_event(int hanum)
if (ha->type == GDT_EISA) {
if (ha->pccb->OpCode == GDT_INIT) /* store DMA buffer */
outl(virt_to_bus(ha->pccb), ha->bmic + MAILBOXREG);
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);
......@@ -1916,7 +1974,7 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
cmd_ptr->u.ioctl.subfunc = p1;
cmd_ptr->u.ioctl.channel = p2;
cmd_ptr->u.ioctl.param_size = (ushort)p3;
cmd_ptr->u.ioctl.p_param = virt_to_bus(ha->pscratch);
cmd_ptr->u.ioctl.p_param = ha->scratch_phys;
} else {
cmd_ptr->u.cache.DeviceNo = (ushort)p1;
cmd_ptr->u.cache.BlockNo = p2;
......@@ -1965,6 +2023,8 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum))
gdth_raw_iochan_str *iocr;
gdth_arcdl_str *alst;
gdth_alist_str *alst2;
gdth_oem_str_ioctl *oemstr;
#ifdef GDTH_RTC
unchar rtc[12];
ulong flags;
......@@ -2233,6 +2293,27 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum))
}
}
/* Determine OEM string using IOCTL */
oemstr = (gdth_oem_str_ioctl *)ha->pscratch;
oemstr->params.ctl_version = 0x01;
oemstr->params.buffer_size = sizeof(oemstr->text);
if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
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);
/* Save the Host Drive inquiry data */
strncpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,7);
ha->oem_name[7] = '\0';
} else {
/* Old method, based on PCI ID */
TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n"));
if (ha->oem_id == OEM_ID_INTEL)
strcpy(ha->oem_name,"Intel ");
else
strcpy(ha->oem_name,"ICP ");
}
/* scanning for host drives */
for (i = 0; i < cdev_cnt; ++i)
gdth_analyse_hdrive(hanum,i);
......@@ -2313,8 +2394,13 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
GDTH_LOCK_HA(ha, 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) ||
......@@ -2357,7 +2443,7 @@ static void gdth_next(int hanum)
register gdth_ha_str *ha;
register Scsi_Cmnd *pscp;
register Scsi_Cmnd *nscp;
unchar b, t, firsttime;
unchar b, t, l, firsttime;
unchar this_cmd, next_cmd;
ulong flags = 0;
int cmd_index;
......@@ -2365,7 +2451,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);
GDTH_LOCK_HA(ha, flags);
ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
this_cmd = firsttime = TRUE;
......@@ -2375,8 +2461,15 @@ 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))
......@@ -2404,16 +2497,16 @@ static void gdth_next(int hanum)
nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */
if (nscp->cmnd[0] == TEST_UNIT_READY) {
TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
b, t, nscp->lun));
b, t, l));
/* TEST_UNIT_READY -> set scan mode */
if ((ha->scan_mode & 0x0f) == 0) {
if (b == 0 && t == 0 && nscp->device->lun == 0) {
if (b == 0 && t == 0 && l == 0) {
ha->scan_mode |= 1;
TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
}
} else if ((ha->scan_mode & 0x0f) == 1) {
if (b == 0 && ((t == 0 && nscp->device->lun == 1) ||
(t == 1 && nscp->device->lun == 0))) {
if (b == 0 && ((t == 0 && l == 1) ||
(t == 1 && l == 0))) {
nscp->SCp.sent_command = GDT_SCAN_START;
nscp->SCp.phase = ((ha->scan_mode & 0x10 ? 1:0) << 8)
| SCSIRAWSERVICE;
......@@ -2465,7 +2558,7 @@ static void gdth_next(int hanum)
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
GDTH_LOCK_HA(ha,flags);
}
}
} else
......@@ -2483,19 +2576,19 @@ static void gdth_next(int hanum)
this_cmd = FALSE;
else
ha->raw[BUS_L2P(ha,b)].io_cnt[t]++;
} else if (t >= MAX_HDRIVES || !ha->hdr[t].present || nscp->device->lun != 0) {
} else if (t >= MAX_HDRIVES || !ha->hdr[t].present || l != 0) {
TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
nscp->cmnd[0], b, t, nscp->lun));
nscp->cmnd[0], b, t, l));
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);
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
GDTH_LOCK_HA(ha,flags);
}
} else {
switch (nscp->cmnd[0]) {
......@@ -2521,20 +2614,20 @@ static void gdth_next(int hanum)
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
else {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
}
} else if (gdth_internal_cache_cmd(hanum,nscp)) {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
GDTH_LOCK_HA(ha,flags);
}
break;
......@@ -2549,12 +2642,12 @@ static void gdth_next(int hanum)
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
else {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
}
} else {
nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
......@@ -2589,12 +2682,12 @@ static void gdth_next(int hanum)
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
else {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
}
} else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
this_cmd = FALSE;
......@@ -2611,11 +2704,11 @@ static void gdth_next(int hanum)
nscp->SCp.have_data_in++;
else {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
GDTH_LOCK_HA(ha,flags);
}
break;
}
......@@ -2636,7 +2729,7 @@ static void gdth_next(int hanum)
}
if (!gdth_polling)
GDTH_UNLOCK_HA(ha, flags);
GDTH_UNLOCK_HA(ha, flags);
if (gdth_polling && ha->cmd_cnt > 0) {
if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
......@@ -2645,27 +2738,54 @@ static void gdth_next(int hanum)
}
}
static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count)
static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
char *buffer,ushort count)
{
ushort cpcount,i;
ushort cpsum,cpnow;
struct scatterlist *sl;
gdth_ha_str *ha;
int sgcnt;
char *address;
cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen;
ha = HADATA(gdth_ctr_tab[hanum]);
if (scp->use_sg) {
sl = (struct scatterlist *)scp->request_buffer;
for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) {
cpnow = (ushort)sl->length;
#if LINUX_VERSION_CODE >= 0x020400
sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE);
for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
cpnow = (ushort)sg_dma_len(sl);
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;
memcpy((char*)sl->address,buffer,cpnow);
address = (char *)phys_to_virt(sg_dma_address(sl));
memcpy(address,buffer,cpnow);
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; i<sgcnt; ++i,++sl) {
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 *)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);
......@@ -2682,7 +2802,11 @@ 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));
......@@ -2706,13 +2830,10 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
inq.version = 2;
inq.resp_aenc = 2;
inq.add_length= 32;
if (ha->oem_id == OEM_ID_INTEL)
strcpy(inq.vendor,"Intel ");
else
strcpy(inq.vendor,"ICP ");
strcpy(inq.vendor,ha->oem_name);
sprintf(inq.product,"Host Drive #%02d",t);
strcpy(inq.revision," ");
gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data));
gdth_copy_internal_data(hanum,scp,(char*)&inq,sizeof(gdth_inq_data));
break;
case REQUEST_SENSE:
......@@ -2722,7 +2843,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
sd.key = NO_SENSE;
sd.info = 0;
sd.add_length= 0;
gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data));
gdth_copy_internal_data(hanum,scp,(char*)&sd,sizeof(gdth_sense_data));
break;
case MODE_SENSE:
......@@ -2734,14 +2855,14 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data));
gdth_copy_internal_data(hanum,scp,(char*)&mpd,sizeof(gdth_modep_data));
break;
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);
gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data));
gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data));
break;
default:
......@@ -2766,8 +2887,8 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
register gdth_cmd_str *cmdp;
struct scatterlist *sl;
ushort i, cnt;
ulong32 no;
int cmd_index, read_write;
ulong32 no, phys_addr;
int cmd_index, read_write, sgcnt;
ha = HADATA(gdth_ctr_tab[hanum]);
cmdp = ha->pccb;
......@@ -2789,7 +2910,7 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
gdth_set_sema0(hanum);
/* fill command */
read_write = FALSE;
read_write = 0;
if (scp->SCp.sent_command != -1)
cmdp->OpCode = scp->SCp.sent_command; /* special cache cmd. */
else if (scp->cmnd[0] == RESERVE)
......@@ -2803,15 +2924,16 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
cmdp->OpCode = GDT_UNMOUNT;
else
cmdp->OpCode = GDT_FLUSH;
} else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10) {
read_write = TRUE;
} else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 ||
scp->cmnd[0] == WRITE_12) {
read_write = 1;
if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) &&
(ha->cache_feat & GDT_WR_THROUGH)))
cmdp->OpCode = GDT_WRITE_THR;
else
cmdp->OpCode = GDT_WRITE;
} else {
read_write = TRUE;
read_write = 2;
cmdp->OpCode = GDT_READ;
}
......@@ -2835,10 +2957,22 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
if (scp->use_sg) {
cmdp->u.cache.DestAddr= 0xffffffff;
sl = (struct scatterlist *)scp->request_buffer;
for (i=0; i<scp->use_sg; ++i,++sl) {
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; i<sgcnt; ++i,++sl) {
cmdp->u.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; i<sgcnt; ++i,++sl) {
cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
}
#endif
cmdp->u.cache.sg_canz = (ulong32)i;
#ifdef GDTH_STATISTICS
......@@ -2850,15 +2984,24 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
if (i<GDTH_MAXSG)
cmdp->u.cache.sg_lst[i].sg_len = 0;
} else {
#if LINUX_VERSION_CODE >= 0x020400
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);
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 =
virt_to_bus(scp->request_buffer);
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 = virt_to_bus(scp->request_buffer);
cmdp->u.cache.DestAddr = phys_addr;
cmdp->u.cache.sg_canz= 0;
}
}
......@@ -2896,12 +3039,18 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
register gdth_cmd_str *cmdp;
struct scatterlist *sl;
ushort i;
int cmd_index;
ulong32 phys_addr, sense_paddr;
int cmd_index, sgcnt;
unchar t,l;
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));
......@@ -2931,6 +3080,13 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
/* 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
cmdp->OpCode = GDT_WRITE; /* always */
cmdp->BoardNode = LOCALBOARD;
cmdp->u.raw.reserved = 0;
......@@ -2944,7 +3100,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
cmdp->u.raw.link_p = 0;
cmdp->u.raw.sdlen = scp->request_bufflen;
cmdp->u.raw.sense_len = 16;
cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
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);
......@@ -2952,10 +3108,21 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
if (scp->use_sg) {
cmdp->u.raw.sdata = 0xffffffff;
sl = (struct scatterlist *)scp->request_buffer;
for (i=0; i<scp->use_sg; ++i,++sl) {
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; i<sgcnt; ++i,++sl) {
cmdp->u.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; i<sgcnt; ++i,++sl) {
cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
}
#endif
cmdp->u.raw.sg_ranz = (ulong32)i;
#ifdef GDTH_STATISTICS
......@@ -2967,14 +3134,23 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
if (i<GDTH_MAXSG)
cmdp->u.raw.sg_lst[i].sg_len = 0;
} else {
#if LINUX_VERSION_CODE >= 0x020400
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);
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 = virt_to_bus(scp->request_buffer);
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 = virt_to_bus(scp->request_buffer);
cmdp->u.raw.sdata = phys_addr;
cmdp->u.raw.sg_ranz= 0;
}
}
......@@ -3372,9 +3548,19 @@ static void gdth_interrupt(int irq,struct pt_regs *regs)
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->host,flags);
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
}
gdth_next(hanum);
}
......@@ -3384,7 +3570,7 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
register gdth_ha_str *ha;
gdth_msg_str *msg;
gdth_cmd_str *cmdp;
unchar b;
unchar b, t;
ha = HADATA(gdth_ctr_tab[hanum]);
cmdp = ha->pccb;
......@@ -3413,7 +3599,7 @@ 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 = virt_to_bus(msg);
cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys;
ha->scratch_busy = TRUE;
ha->cmd_offs_dpmem = 0;
ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
......@@ -3448,7 +3634,7 @@ 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 = virt_to_bus(msg);
cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys;
ha->scratch_busy = TRUE;
ha->cmd_offs_dpmem = 0;
ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
......@@ -3461,11 +3647,35 @@ 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[scp->device->id]--;
ha->raw[BUS_L2P(ha,b)].io_cnt[t]--;
}
/* cache or raw service */
if (ha->status == S_BSY) {
TRACE2(("Controller busy -> retry !\n"));
if (scp->SCp.sent_command == GDT_MOUNT)
scp->SCp.sent_command = GDT_CLUST_INFO;
/* 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
if (ha->status == S_OK) {
scp->SCp.Status = S_OK;
scp->SCp.Message = ha->info;
......@@ -3474,12 +3684,12 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
scp->SCp.sent_command));
/* special commands GDT_CLUST_INFO/GDT_MOUNT ? */
if (scp->SCp.sent_command == GDT_CLUST_INFO) {
ha->hdr[scp->device->id].cluster_type = (unchar)ha->info;
if (!(ha->hdr[scp->device->id].cluster_type &
ha->hdr[t].cluster_type = (unchar)ha->info;
if (!(ha->hdr[t].cluster_type &
CLUSTER_MOUNTED)) {
/* NOT MOUNTED -> MOUNT */
scp->SCp.sent_command = GDT_MOUNT;
if (ha->hdr[scp->device->id].cluster_type &
if (ha->hdr[t].cluster_type &
CLUSTER_RESERVED) {
/* cluster drive RESERVED (on the other node) */
scp->SCp.phase = -2; /* reservation conflict */
......@@ -3489,11 +3699,11 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
}
} else {
if (scp->SCp.sent_command == GDT_MOUNT) {
ha->hdr[scp->device->id].cluster_type |= CLUSTER_MOUNTED;
ha->hdr[scp->device->id].media_changed = TRUE;
ha->hdr[t].cluster_type |= CLUSTER_MOUNTED;
ha->hdr[t].media_changed = TRUE;
} else if (scp->SCp.sent_command == GDT_UNMOUNT) {
ha->hdr[scp->device->id].cluster_type &= ~CLUSTER_MOUNTED;
ha->hdr[scp->device->id].media_changed = TRUE;
ha->hdr[t].cluster_type &= ~CLUSTER_MOUNTED;
ha->hdr[t].media_changed = TRUE;
}
scp->SCp.sent_command = -1;
}
......@@ -3503,21 +3713,13 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
} else {
/* RESERVE/RELEASE ? */
if (scp->cmnd[0] == RESERVE) {
ha->hdr[scp->device->id].cluster_type |= CLUSTER_RESERVED;
ha->hdr[t].cluster_type |= CLUSTER_RESERVED;
} else if (scp->cmnd[0] == RELEASE) {
ha->hdr[scp->device->id].cluster_type &= ~CLUSTER_RESERVED;
ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
}
scp->result = DID_OK << 16;
scp->sense_buffer[0] = 0;
}
} else if (ha->status == S_BSY) {
TRACE2(("Controller busy -> retry !\n"));
scp->SCp.Status = S_BSY;
scp->SCp.Message = ha->info;
if (scp->SCp.sent_command == GDT_MOUNT)
scp->SCp.sent_command = GDT_CLUST_INFO;
/* retry */
return 2;
} else {
scp->SCp.Status = ha->status;
scp->SCp.Message = ha->info;
......@@ -3538,10 +3740,10 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
} else if (service == CACHESERVICE) {
if (ha->status == S_CACHE_UNKNOWN &&
(ha->hdr[scp->device->id].cluster_type &
(ha->hdr[t].cluster_type &
CLUSTER_RESERVE_STATE) == CLUSTER_RESERVE_STATE) {
/* bus reset -> force GDT_CLUST_INFO */
ha->hdr[scp->device->id].cluster_type &= ~CLUSTER_RESERVED;
ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
}
memset((char*)scp->sense_buffer,0,16);
if (ha->status == (ushort)S_CACHE_RESERV) {
......@@ -3560,7 +3762,7 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
ha->dvr.eu.sync.service = service;
ha->dvr.eu.sync.status = ha->status;
ha->dvr.eu.sync.info = ha->info;
ha->dvr.eu.sync.hostdrive = scp->device->id;
ha->dvr.eu.sync.hostdrive = t;
if (ha->status >= 0x8000)
gdth_store_event(ha, ES_SYNC, 0, &ha->dvr);
else
......@@ -3765,7 +3967,7 @@ 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 = virt_to_bus(msg);
cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys;
ha->scratch_busy = TRUE;
ha->cmd_offs_dpmem = 0;
ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
......@@ -4028,8 +4230,8 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
break;
if (gdth_search_isa(isa_bios)) { /* controller found */
shp = scsi_register(shtp,sizeof(gdth_ext_str));
if(shp == NULL)
continue;
if (shp == NULL)
continue;
ha = HADATA(shp);
if (!gdth_init_isa(isa_bios,ha)) {
......@@ -4076,11 +4278,15 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
NUMDATA(shp)->busnum= 0;
ha->pccb = CMDDATA(shp);
#if LINUX_VERSION_CODE >= 0x020322
ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA,
GDTH_SCRATCH_ORD);
ha->ccb_phys = 0L;
#if LINUX_VERSION_CODE >= 0x020400
ha->pdev = NULL;
ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
&ha->scratch_phys);
#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;
......@@ -4095,12 +4301,14 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
printk("GDT-ISA: Error during device scan\n");
--gdth_ctr_count;
--gdth_ctr_vcount;
if (ha->pscratch != NULL)
#if LINUX_VERSION_CODE >= 0x020322
free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
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
......@@ -4145,8 +4353,8 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
break;
if (gdth_search_eisa(eisa_slot)) { /* controller found */
shp = scsi_register(shtp,sizeof(gdth_ext_str));
if(shp == NULL)
continue;
if (shp == NULL)
continue;
ha = HADATA(shp);
if (!gdth_init_eisa(eisa_slot,ha)) {
......@@ -4180,11 +4388,19 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
NUMDATA(shp)->hanum));
ha->pccb = CMDDATA(shp);
#if LINUX_VERSION_CODE >= 0x020322
ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA,
GDTH_SCRATCH_ORD);
ha->ccb_phys = 0L;
#if LINUX_VERSION_CODE >= 0x020400
ha->pdev = NULL;
ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
&ha->scratch_phys);
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;
......@@ -4199,12 +4415,16 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
printk("GDT-EISA: Error during device scan\n");
--gdth_ctr_count;
--gdth_ctr_vcount;
if (ha->pscratch != NULL)
#if LINUX_VERSION_CODE >= 0x020322
free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
if (ha->pscratch != NULL) {
#if LINUX_VERSION_CODE >= 0x020400
pci_free_consistent(ha->pdev, GDTH_SCRATCH,
ha->pscratch, ha->scratch_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
free_irq(ha->irq,ha);
#else
......@@ -4252,14 +4472,14 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
gdth_pci_str pcistr[MAXHA];
cnt = gdth_search_pci(pcistr);
printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt);
printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt);
gdth_sort_pci(pcistr,cnt);
for (ctr = 0; ctr < cnt; ++ctr) {
if (gdth_ctr_count >= MAXHA)
break;
shp = scsi_register(shtp,sizeof(gdth_ext_str));
if(shp == NULL)
continue;
if (shp == NULL)
continue;
ha = HADATA(shp);
if (!gdth_init_pci(&pcistr[ctr],ha)) {
......@@ -4293,11 +4513,14 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
NUMDATA(shp)->busnum= 0;
ha->pccb = CMDDATA(shp);
#if LINUX_VERSION_CODE >= 0x020322
ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA,
GDTH_SCRATCH_ORD);
ha->ccb_phys = 0L;
#if LINUX_VERSION_CODE >= 0x020400
ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
&ha->scratch_phys);
#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;
......@@ -4312,12 +4535,14 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
printk("GDT-PCI: Error during device scan\n");
--gdth_ctr_count;
--gdth_ctr_vcount;
if (ha->pscratch != NULL)
#if LINUX_VERSION_CODE >= 0x020322
free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
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
......@@ -4365,6 +4590,9 @@ 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
register_reboot_notifier(&gdth_notifier);
#endif
......@@ -4399,8 +4627,12 @@ int gdth_release(struct Scsi_Host *shp)
free_dma(shp->dma_channel);
}
#endif
#if LINUX_VERSION_CODE >= 0x020322
free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
#if LINUX_VERSION_CODE >= 0x020400
pci_free_consistent(ha->pdev, GDTH_SCRATCH,
ha->pscratch, ha->scratch_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
......@@ -4412,6 +4644,9 @@ 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
......@@ -4507,15 +4742,24 @@ 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);
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);
......@@ -4558,16 +4802,31 @@ int gdth_eh_host_reset(Scsi_Cmnd *scp)
}
#endif
int gdth_bios_param(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int *ip)
#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)
#else
int gdth_bios_param(Disk *disk,int dev,int *ip)
#endif
{
unchar b, t;
int hanum;
gdth_ha_str *ha;
struct scsi_device *sd;
unsigned capacity;
hanum = NUMDATA(sdev->host)->hanum;
b = virt_ctr ? NUMDATA(sdev->host)->busnum : sdev->channel;
t = sdev->id;
#if LINUX_VERSION_CODE >= 0x020503
sd = sdev;
capacity = cap;
#else
sd = disk->device;
capacity = disk->capacity;
#endif
hanum = NUMDATA(sd->host)->hanum;
b = virt_ctr ? NUMDATA(sd->host)->busnum : sd->channel;
t = sd->id;
TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t));
ha = HADATA(gdth_ctr_tab[hanum]);
......@@ -4592,14 +4851,19 @@ int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
int hanum;
int priority;
TRACE(("gdth_queuecommand() cmd 0x%x id %d lun %d\n",
scp->cmnd[0],scp->device->id,scp->lun));
TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0]));
scp->scsi_done = (void *)done;
scp->SCp.have_data_in = 1;
scp->SCp.phase = -1;
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
......@@ -4615,6 +4879,667 @@ int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
return 0;
}
#ifdef GDTH_IOCTL_CHRDEV
static int gdth_open(struct inode *inode, struct file *filep)
{
TRACE(("gdth_open()\n"));
return 0;
}
static int gdth_close(struct inode *inode, struct file *filep)
{
TRACE(("gdth_close()\n"));
return 0;
}
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_Request *srp;
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];
memset(cmnd, 0xff, 12);
TRACE(("gdth_ioctl() cmd 0x%x\n", cmd));
switch (cmd) {
case GDTIOCTL_CTRCNT:
{
int cnt = gdth_ctr_count;
put_user(cnt, (int *)arg);
break;
}
case GDTIOCTL_DRVERS:
{
int ver = (GDTH_VERSION<<8) | GDTH_SUBVERSION;
put_user(ver, (int *)arg);
break;
}
case GDTIOCTL_OSVERS:
{
gdth_ioctl_osvers osv;
osv.version = (unchar)(LINUX_VERSION_CODE >> 16);
osv.subversion = (unchar)(LINUX_VERSION_CODE >> 8);
osv.revision = (ushort)(LINUX_VERSION_CODE & 0xff);
copy_to_user((char *)arg, &osv, sizeof(gdth_ioctl_osvers));
break;
}
case GDTIOCTL_CTRTYPE:
{
gdth_ioctl_ctrtype ctrt;
if (copy_from_user(&ctrt, (char *)arg, sizeof(gdth_ioctl_ctrtype)) ||
ctrt.ionode >= gdth_ctr_count)
return -EFAULT;
ha = HADATA(gdth_ctr_tab[ctrt.ionode]);
if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
ctrt.type = (unchar)((ha->stype>>20) - 0x10);
} else {
if (ha->type != GDT_PCIMPR) {
ctrt.type = (unchar)((ha->stype<<4) + 6);
} else {
ctrt.type =
(ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe);
if (ha->stype >= 0x300)
ctrt.ext_type = 0x6000 | ha->subdevice_id;
else
ctrt.ext_type = 0x6000 | ha->stype;
}
ctrt.device_id = ha->stype;
ctrt.sub_device_id = ha->subdevice_id;
}
ctrt.info = ha->brd_phys;
ctrt.oem_id = ha->oem_id;
if (copy_to_user((char *)arg, &ctrt, sizeof(gdth_ioctl_ctrtype)))
return -EFAULT;
break;
}
case GDTIOCTL_GENERAL:
{
gdth_ioctl_general gen;
char *buf = NULL;
ulong32 paddr;
int hanum;
if (copy_from_user(&gen, (char *)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;
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 (gen.command.OpCode == GDT_IOCTL) {
gen.command.u.ioctl.p_param = paddr;
} else if (gen.command.Service == CACHESERVICE) {
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_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) {
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_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;
}
}
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
srp = scsi_allocate_request(sdev);
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))) {
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);
break;
}
case GDTIOCTL_EVENT:
{
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;
break;
}
case GDTIOCTL_LOCKDRV:
{
gdth_ioctl_lockdrv ldrv;
unchar i, j;
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]);
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);
}
}
break;
}
case GDTIOCTL_LOCKCHN:
{
gdth_ioctl_lockchn lchn;
unchar i, j;
if (copy_from_user(&lchn, (char *)arg, sizeof(gdth_ioctl_lockchn)) ||
lchn.ionode >= gdth_ctr_count)
return -EFAULT;
ha = HADATA(gdth_ctr_tab[lchn.ionode]);
i = lchn.channel;
if (i < ha->bus_cnt) {
if (lchn.lock) {
GDTH_LOCK_HA(ha, flags);
ha->raw[i].lock = 1;
GDTH_UNLOCK_HA(ha, 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);
ha->raw[i].lock = 0;
GDTH_UNLOCK_HA(ha, flags);
for (j = 0; j < ha->tid_cnt; ++j) {
gdth_start_timeout(lchn.ionode, i, j);
gdth_next(lchn.ionode);
}
}
}
break;
}
case GDTIOCTL_RESCAN:
{
gdth_ioctl_rescan rsc;
gdth_cmd_str cmd;
ushort i, status, hdr_cnt;
ulong32 info;
int hanum, cyls, hds, secs;
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]);
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
srp = scsi_allocate_request(sdev);
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);
} else {
i = rsc.hdr_no;
hdr_cnt = i + 1;
}
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);
}
#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;
break;
}
case GDTIOCTL_HDRLIST:
{
gdth_ioctl_rescan rsc;
gdth_cmd_str cmd;
gdth_ha_str *ha;
unchar i;
int hanum;
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]);
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
srp = scsi_allocate_request(sdev);
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
}
}
#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;
break;
}
case GDTIOCTL_RESET_BUS:
{
gdth_ioctl_reset res;
int hanum, rval;
if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) ||
res.ionode >= gdth_ctr_count)
return -EFAULT;
hanum = res.ionode;
/* 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 (!scp)
return -ENOMEM;
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);
#else
scp = scsi_allocate_device(sdev, 1, FALSE);
#endif
if (!scp)
return -ENOMEM;
scp->cmd_len = 12;
scp->use_sg = 0;
scp->channel = virt_ctr ? 0 : res.number;
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)))
return -EFAULT;
break;
}
case GDTIOCTL_RESET_DRV:
{
gdth_ioctl_reset res;
gdth_cmd_str cmd;
int hanum;
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 (!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);
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;
break;
}
default:
break;
}
return 0;
}
#endif
#if LINUX_VERSION_CODE >= 0x010300
/* flush routine */
static void gdth_flush(int hanum)
......@@ -4622,7 +5547,10 @@ static void gdth_flush(int hanum)
int i;
gdth_ha_str *ha;
gdth_cmd_str gdtcmd;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
Scsi_Request *srp;
Scsi_Device *sdev;
#elif LINUX_VERSION_CODE >= 0x020322
Scsi_Cmnd *scp;
Scsi_Device *sdev;
#else
......@@ -4635,9 +5563,18 @@ static void gdth_flush(int hanum)
TRACE2(("gdth_flush() hanum %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
scp = scsi_get_command(sdev, GFP_KERNEL);
srp = scsi_allocate_request(sdev);
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
......@@ -4657,15 +5594,20 @@ static void gdth_flush(int hanum)
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 >= 0x020322
#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
}
}
#if LINUX_VERSION_CODE >= 0x020322
scsi_put_command(scp);
#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
}
......@@ -4680,7 +5622,10 @@ void gdth_halt(void)
int hanum;
#ifndef __alpha__
gdth_cmd_str gdtcmd;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
Scsi_Request *srp;
Scsi_Device *sdev;
#elif LINUX_VERSION_CODE >= 0x020322
Scsi_Cmnd *scp;
Scsi_Device *sdev;
#else
......@@ -4702,6 +5647,7 @@ void gdth_halt(void)
}
halt_called = TRUE;
#endif
printk("GDT: Flushing all host drives .. ");
for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
gdth_flush(hanum);
......@@ -4709,28 +5655,48 @@ void gdth_halt(void)
#ifndef __alpha__
/* controller reset */
memset(cmnd, 0xff, MAX_COMMAND_SIZE);
#if LINUX_VERSION_CODE >= 0x020322
gdtcmd.BoardNode = LOCALBOARD;
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]);
scp = scsi_get_command(sdev, GFP_KERNEL);
srp = scsi_allocate_request(sdev);
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;
#endif
gdtcmd.BoardNode = LOCALBOARD;
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_RESET;
TRACE2(("gdth_halt(): reset controller %d\n", hanum));
#if LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
scsi_put_command(scp);
scsi_free_host_dev(sdev);
#else
gdth_do_cmd(&scp, &gdtcmd, cmnd, 10);
#endif
#endif
......
......@@ -10,7 +10,7 @@
*
* <achim.leubner@intel.com>
*
* $Id: gdth.h,v 1.46 2002/02/05 09:39:53 achim Exp $
* $Id: gdth.h,v 1.48 2003/02/27 14:58:22 achim Exp $
*/
#include <linux/version.h>
......@@ -29,16 +29,16 @@
/* defines, macros */
/* driver version */
#define GDTH_VERSION_STR "2.05"
#define GDTH_VERSION_STR "2.07"
#define GDTH_VERSION 2
#define GDTH_SUBVERSION 5
#define GDTH_SUBVERSION 7
/* protocol version */
#define PROTOCOL_VERSION 1
/* OEM IDs */
#define OEM_ID_ICP 0x941c
#define OEM_ID_INTEL 0x8000
#define OEM_ID_ICP 0x941c
#define OEM_ID_INTEL 0x8000
/* controller classes */
#define GDT_ISA 0x01 /* ISA controller */
......@@ -134,12 +134,17 @@
#ifndef PCI_DEVICE_ID_VORTEX_GDTNEWRX
/* new GDT Rx Controller */
#define PCI_DEVICE_ID_VORTEX_GDTNEWRX 0x300
#define PCI_DEVICE_ID_VORTEX_GDTNEWRX 0x300
#endif
#ifndef PCI_DEVICE_ID_INTEL_SRC
/* Intel Storage RAID Controller */
#define PCI_DEVICE_ID_INTEL_SRC 0x600
#define PCI_DEVICE_ID_INTEL_SRC 0x600
#endif
#ifndef PCI_DEVICE_ID_INTEL_SRC_XSCALE
/* Intel Storage RAID Controller */
#define PCI_DEVICE_ID_INTEL_SRC_XSCALE 0x601
#endif
/* limits */
......@@ -153,8 +158,6 @@
#define MAXID 127
#define MAXLUN 8
#define MAXBUS 6
#define MAX_HDRIVES 100 /* max. host drive count */
#define MAX_LDRIVES 255 /* max. log. drive count */
#define MAX_EVENTS 100 /* event buffer count */
#define MAX_RES_ARGS 40 /* device reservation,
must be a multiple of 4 */
......@@ -254,6 +257,7 @@
#define CACHE_DRV_INFO 0x07 /* cache drive info */
#define BOARD_FEATURES 0x15 /* controller features */
#define BOARD_INFO 0x28 /* controller info */
#define CACHE_READ_OEM_STRING_RECORD 0x84 /* read OEM string record */
#define HOST_GET 0x10001L /* get host drive list */
#define IO_CHANNEL 0x00020000L /* default IO channel */
#define INVALID_CHANNEL 0x0000ffffL /* invalid channel */
......@@ -265,7 +269,7 @@
#define S_CACHE_UNKNOWN 12 /* cache serv.: drive unknown */
#define S_RAW_SCSI 12 /* raw serv.: target error */
#define S_RAW_ILL 0xff /* raw serv.: illegal */
#define S_CACHE_RESERV -24 /* cache: reserv. conflict */
#define S_CACHE_RESERV -24 /* cache: reserv. conflict */
/* timeout values */
#define INIT_RETRIES 100000 /* 100000 * 1ms = 100s */
......@@ -292,10 +296,15 @@
#define MAILBOXREG 0x0c90 /* mailbox reg. (16 bytes) */
#define EISAREG 0x0cc0 /* EISA configuration */
/* DMA memory mappings */
#define GDTH_MAP_NONE 0
#define GDTH_MAP_SINGLE 1
#define GDTH_MAP_SG 2
#define GDTH_MAP_IOCTL 3
/* other defines */
#define LINUX_OS 8 /* used for cache optim. */
#define SCATTER_GATHER 1 /* s/g feature */
#define GDTH_MAXSG 32 /* max. s/g elements */
#define SECS32 0x1f /* round capacity */
#define BIOS_ID_OFFS 0x10 /* offset contr-ID in ISABIOS */
#define LOCALBOARD 0 /* board node always 0 */
......@@ -303,10 +312,7 @@
#define SPEZINDEX 1 /* cmd index unknown service */
#define GDT_WR_THROUGH 0x100 /* WRITE_THROUGH supported */
/* typedefs */
typedef u32 ulong32;
#define PACKED __attribute__((packed))
#include "gdth_ioctl.h"
/* screenservice message */
typedef struct {
......@@ -535,6 +541,50 @@ typedef struct {
unchar ld_error; /* error */
} PACKED gdth_cdrinfo_str;
/* OEM string */
typedef struct {
ulong32 ctl_version;
ulong32 file_major_version;
ulong32 file_minor_version;
ulong32 buffer_size;
ulong32 cpy_count;
ulong32 ext_error;
ulong32 oem_id;
ulong32 board_id;
} PACKED gdth_oem_str_params;
typedef struct {
unchar product_0_1_name[16];
unchar product_4_5_name[16];
unchar product_cluster_name[16];
unchar product_reserved[16];
unchar scsi_cluster_target_vendor_id[16];
unchar cluster_raid_fw_name[16];
unchar oem_brand_name[16];
unchar oem_raid_type[16];
unchar bios_type[13];
unchar bios_title[50];
unchar oem_company_name[37];
ulong32 pci_id_1;
ulong32 pci_id_2;
unchar validation_status[80];
unchar reserved_1[4];
unchar scsi_host_drive_inquiry_vendor_id[16];
unchar library_file_template[16];
unchar reserved_2[16];
unchar tool_name_1[32];
unchar tool_name_2[32];
unchar tool_name_3[32];
unchar oem_contact_1[84];
unchar oem_contact_2[84];
unchar oem_contact_3[84];
} PACKED gdth_oem_str;
typedef struct {
gdth_oem_str_params params;
gdth_oem_str text;
} PACKED gdth_oem_str_ioctl;
/* board features */
typedef struct {
unchar chaining; /* Chaining supported */
......@@ -594,118 +644,6 @@ typedef struct {
gdth_hentry_str entry[MAX_HDRIVES]; /* entries */
} PACKED gdth_hget_str;
/* scatter/gather element */
typedef struct {
ulong32 sg_ptr; /* address */
ulong32 sg_len; /* length */
} PACKED gdth_sg_str;
/* command structure */
typedef struct {
ulong32 BoardNode; /* board node (always 0) */
ulong32 CommandIndex; /* command number */
ushort OpCode; /* the command (READ,..) */
union {
struct {
ushort DeviceNo; /* number of cache drive */
ulong32 BlockNo; /* block number */
ulong32 BlockCnt; /* block count */
ulong32 DestAddr; /* dest. addr. (if s/g: -1) */
ulong32 sg_canz; /* s/g element count */
gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */
} PACKED cache; /* cache service cmd. str. */
struct {
ushort param_size; /* size of p_param buffer */
ulong32 subfunc; /* IOCTL function */
ulong32 channel; /* device */
ulong32 p_param; /* buffer */
} PACKED ioctl; /* IOCTL command structure */
struct {
ushort reserved;
union {
struct {
ulong32 msg_handle; /* message handle */
ulong32 msg_addr; /* message buffer address */
} PACKED msg;
unchar data[12]; /* buffer for rtc data, ... */
} su;
} PACKED screen; /* screen service cmd. str. */
struct {
ushort reserved;
ulong32 direction; /* data direction */
ulong32 mdisc_time; /* disc. time (0: no timeout)*/
ulong32 mcon_time; /* connect time(0: no to.) */
ulong32 sdata; /* dest. addr. (if s/g: -1) */
ulong32 sdlen; /* data length (bytes) */
ulong32 clen; /* SCSI cmd. length(6,10,12) */
unchar cmd[12]; /* SCSI command */
unchar target; /* target ID */
unchar lun; /* LUN */
unchar bus; /* SCSI bus number */
unchar priority; /* only 0 used */
ulong32 sense_len; /* sense data length */
ulong32 sense_data; /* sense data addr. */
ulong32 link_p; /* linked cmds (not supp.) */
ulong32 sg_ranz; /* s/g element count */
gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */
} PACKED raw; /* raw service cmd. struct. */
} u;
/* additional variables */
unchar Service; /* controller service */
ushort Status; /* command result */
ulong32 Info; /* additional information */
Scsi_Cmnd *RequestBuffer; /* request buffer */
} PACKED gdth_cmd_str;
/* controller event structure */
#define ES_ASYNC 1
#define ES_DRIVER 2
#define ES_TEST 3
#define ES_SYNC 4
typedef struct {
ushort size; /* size of structure */
union {
char stream[16];
struct {
ushort ionode;
ushort service;
ulong32 index;
} PACKED driver;
struct {
ushort ionode;
ushort service;
ushort status;
ulong32 info;
unchar scsi_coord[3];
} PACKED async;
struct {
ushort ionode;
ushort service;
ushort status;
ulong32 info;
ushort hostdrive;
unchar scsi_coord[3];
unchar sense_key;
} PACKED sync;
struct {
ulong32 l1, l2, l3, l4;
} PACKED test;
} eu;
ulong32 severity;
unchar event_string[256];
} PACKED gdth_evt_data;
typedef struct {
ulong32 first_stamp;
ulong32 last_stamp;
ushort same_count;
ushort event_source;
ushort event_idx;
unchar application;
unchar reserved;
gdth_evt_data event_data;
} PACKED gdth_evt_str;
/* DPRAM structures */
......@@ -889,7 +827,9 @@ typedef struct {
ulong32 brd_phys; /* slot number/BIOS address */
gdt6c_plx_regs *plx; /* PLX regs (new PCI contr.) */
gdth_cmd_str *pccb; /* address command structure */
ulong32 ccb_phys; /* phys. address */
char *pscratch; /* scratch (DMA) buffer */
ulong32 scratch_phys; /* phys. address */
unchar scratch_busy; /* in use? */
unchar scan_mode; /* current scan mode */
unchar irq; /* IRQ */
......@@ -946,6 +886,10 @@ typedef struct {
#if LINUX_VERSION_CODE >= 0x02015F
spinlock_t smp_lock;
#endif
#if LINUX_VERSION_CODE >= 0x020400
struct pci_dev *pdev;
#endif
char oem_name[8];
} gdth_ha_str;
/* structure for scsi_register(), SCSI bus != 0 */
......@@ -1032,34 +976,145 @@ int gdth_reset(Scsi_Cmnd *);
#endif
const char *gdth_info(struct Scsi_Host *);
#if LINUX_VERSION_CODE >= 0x020501
int gdth_bios_param(struct scsi_device *,struct block_device *,sector_t,int *);
int gdth_proc_info(char *,char **,off_t,int,int,int);
int gdth_eh_abort(Scsi_Cmnd *scp);
int gdth_eh_device_reset(Scsi_Cmnd *scp);
int gdth_eh_bus_reset(Scsi_Cmnd *scp);
int gdth_eh_host_reset(Scsi_Cmnd *scp);
#define GDTH { .proc_name = "gdth", \
.proc_info = gdth_proc_info, \
.name = "GDT SCSI Disk Array Controller",\
.detect = gdth_detect, \
.release = gdth_release, \
.info = gdth_info, \
.command = NULL, \
.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, \
.abort = gdth_abort, \
.reset = gdth_reset, \
.bios_param = gdth_bios_param, \
.can_queue = GDTH_MAXCMDS, \
.this_id = -1, \
.sg_tablesize = GDTH_MAXSG, \
.cmd_per_lun = GDTH_MAXC_P_L, \
.present = 0, \
.unchecked_isa_dma = 1, \
.use_clustering = ENABLE_CLUSTERING }
#define GDTH { .proc_name = "gdth", \
.proc_info = gdth_proc_info, \
.name = "GDT SCSI Disk Array Controller",\
.detect = gdth_detect, \
.release = gdth_release, \
.info = gdth_info, \
.command = NULL, \
.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, \
.abort = NULL, \
.reset = NULL, \
.bios_param = gdth_bios_param, \
.can_queue = GDTH_MAXCMDS, \
.this_id = -1, \
.sg_tablesize = GDTH_MAXSG, \
.cmd_per_lun = GDTH_MAXC_P_L, \
.present = 0, \
.unchecked_isa_dma = 1, \
.use_clustering = ENABLE_CLUSTERING}
#elif LINUX_VERSION_CODE >= 0x020322
int gdth_bios_param(Disk *,kdev_t,int *);
int gdth_proc_info(char *,char **,off_t,int,int,int);
int gdth_eh_abort(Scsi_Cmnd *scp);
int gdth_eh_device_reset(Scsi_Cmnd *scp);
int gdth_eh_bus_reset(Scsi_Cmnd *scp);
int gdth_eh_host_reset(Scsi_Cmnd *scp);
#define GDTH { proc_name: "gdth", \
proc_info: gdth_proc_info, \
name: "GDT SCSI Disk Array Controller",\
detect: gdth_detect, \
release: gdth_release, \
info: gdth_info, \
command: NULL, \
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, \
abort: gdth_abort, \
reset: gdth_reset, \
bios_param: gdth_bios_param, \
can_queue: GDTH_MAXCMDS, \
this_id: -1, \
sg_tablesize: GDTH_MAXSG, \
cmd_per_lun: GDTH_MAXC_P_L, \
present: 0, \
unchecked_isa_dma: 1, \
use_clustering: ENABLE_CLUSTERING, \
use_new_eh_code: 1 /* use new error code */ }
#elif LINUX_VERSION_CODE >= 0x02015F
int gdth_bios_param(Disk *,kdev_t,int *);
extern struct proc_dir_entry proc_scsi_gdth;
int gdth_proc_info(char *,char **,off_t,int,int,int);
int gdth_eh_abort(Scsi_Cmnd *scp);
int gdth_eh_device_reset(Scsi_Cmnd *scp);
int gdth_eh_bus_reset(Scsi_Cmnd *scp);
int gdth_eh_host_reset(Scsi_Cmnd *scp);
#define GDTH { proc_dir: &proc_scsi_gdth, \
proc_info: gdth_proc_info, \
name: "GDT SCSI Disk Array Controller",\
detect: gdth_detect, \
release: gdth_release, \
info: gdth_info, \
command: NULL, \
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, \
abort: gdth_abort, \
reset: gdth_reset, \
bios_param: gdth_bios_param, \
can_queue: GDTH_MAXCMDS, \
this_id: -1, \
sg_tablesize: GDTH_MAXSG, \
cmd_per_lun: GDTH_MAXC_P_L, \
present: 0, \
unchecked_isa_dma: 1, \
use_clustering: ENABLE_CLUSTERING, \
use_new_eh_code: 1 /* use new error code */ }
#elif LINUX_VERSION_CODE >= 0x010300
int gdth_bios_param(Disk *,kdev_t,int *);
extern struct proc_dir_entry proc_scsi_gdth;
int gdth_proc_info(char *,char **,off_t,int,int,int);
#define GDTH { NULL, NULL, \
&proc_scsi_gdth, \
gdth_proc_info, \
"GDT SCSI Disk Array Controller", \
gdth_detect, \
gdth_release, \
gdth_info, \
NULL, \
gdth_queuecommand, \
gdth_abort, \
gdth_reset, \
NULL, \
gdth_bios_param, \
GDTH_MAXCMDS, \
-1, \
GDTH_MAXSG, \
GDTH_MAXC_P_L, \
0, \
1, \
ENABLE_CLUSTERING}
#else
int gdth_bios_param(Disk *,int,int *);
#define GDTH { NULL, NULL, \
"GDT SCSI Disk Array Controller", \
gdth_detect, \
gdth_release, \
gdth_info, \
NULL, \
gdth_queuecommand, \
gdth_abort, \
gdth_reset, \
NULL, \
gdth_bios_param, \
GDTH_MAXCMDS, \
-1, \
GDTH_MAXSG, \
GDTH_MAXC_P_L, \
0, \
1, \
ENABLE_CLUSTERING}
#endif
#endif
......@@ -2,7 +2,7 @@
#define _GDTH_IOCTL_H
/* gdth_ioctl.h
* $Id: gdth_ioctl.h,v 1.10 2001/05/22 06:28:59 achim Exp $
* $Id: gdth_ioctl.h,v 1.11 2003/02/27 14:59:03 achim Exp $
*/
/* IOCTLs */
......@@ -23,8 +23,136 @@
#define GDTIOCTL_MAGIC 0xaffe0004
#define EVENT_SIZE 294
#define MAX_HDRIVES 100
#define GDTH_MAXSG 32 /* max. s/g elements */
#define MAX_LDRIVES 255 /* max. log. drive count */
#ifdef GDTH_IOCTL_PROC
#define MAX_HDRIVES 100 /* max. host drive count */
#else
#define MAX_HDRIVES MAX_LDRIVES /* max. host drive count */
#endif
/* typedefs */
#ifdef __KERNEL__
typedef u32 ulong32;
#endif
#define PACKED __attribute__((packed))
/* scatter/gather element */
typedef struct {
ulong32 sg_ptr; /* address */
ulong32 sg_len; /* length */
} PACKED gdth_sg_str;
/* command structure */
typedef struct {
ulong32 BoardNode; /* board node (always 0) */
ulong32 CommandIndex; /* command number */
ushort OpCode; /* the command (READ,..) */
union {
struct {
ushort DeviceNo; /* number of cache drive */
ulong32 BlockNo; /* block number */
ulong32 BlockCnt; /* block count */
ulong32 DestAddr; /* dest. addr. (if s/g: -1) */
ulong32 sg_canz; /* s/g element count */
gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */
} PACKED cache; /* cache service cmd. str. */
struct {
ushort param_size; /* size of p_param buffer */
ulong32 subfunc; /* IOCTL function */
ulong32 channel; /* device */
ulong32 p_param; /* buffer */
} PACKED ioctl; /* IOCTL command structure */
struct {
ushort reserved;
union {
struct {
ulong32 msg_handle; /* message handle */
ulong32 msg_addr; /* message buffer address */
} PACKED msg;
unchar data[12]; /* buffer for rtc data, ... */
} su;
} PACKED screen; /* screen service cmd. str. */
struct {
ushort reserved;
ulong32 direction; /* data direction */
ulong32 mdisc_time; /* disc. time (0: no timeout)*/
ulong32 mcon_time; /* connect time(0: no to.) */
ulong32 sdata; /* dest. addr. (if s/g: -1) */
ulong32 sdlen; /* data length (bytes) */
ulong32 clen; /* SCSI cmd. length(6,10,12) */
unchar cmd[12]; /* SCSI command */
unchar target; /* target ID */
unchar lun; /* LUN */
unchar bus; /* SCSI bus number */
unchar priority; /* only 0 used */
ulong32 sense_len; /* sense data length */
ulong32 sense_data; /* sense data addr. */
ulong32 link_p; /* linked cmds (not supp.) */
ulong32 sg_ranz; /* s/g element count */
gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */
} PACKED raw; /* raw service cmd. struct. */
} u;
/* additional variables */
unchar Service; /* controller service */
unchar reserved;
ushort Status; /* command result */
ulong32 Info; /* additional information */
void *RequestBuffer; /* request buffer */
} PACKED gdth_cmd_str;
/* controller event structure */
#define ES_ASYNC 1
#define ES_DRIVER 2
#define ES_TEST 3
#define ES_SYNC 4
typedef struct {
ushort size; /* size of structure */
union {
char stream[16];
struct {
ushort ionode;
ushort service;
ulong32 index;
} PACKED driver;
struct {
ushort ionode;
ushort service;
ushort status;
ulong32 info;
unchar scsi_coord[3];
} PACKED async;
struct {
ushort ionode;
ushort service;
ushort status;
ulong32 info;
ushort hostdrive;
unchar scsi_coord[3];
unchar sense_key;
} PACKED sync;
struct {
ulong32 l1, l2, l3, l4;
} PACKED test;
} eu;
ulong32 severity;
unchar event_string[256];
} PACKED gdth_evt_data;
typedef struct {
ulong32 first_stamp;
ulong32 last_stamp;
ushort same_count;
ushort event_source;
ushort event_idx;
unchar application;
unchar reserved;
gdth_evt_data event_data;
} PACKED gdth_evt_str;
#ifdef GDTH_IOCTL_PROC
/* IOCTL structure (write) */
typedef struct {
ulong32 magic; /* IOCTL magic */
......@@ -106,7 +234,82 @@ typedef struct {
} hdr_list[MAX_HDRIVES]; /* index is host drive number */
} iu;
} gdth_iord_str;
#endif
#ifdef GDTH_IOCTL_CHRDEV
/* GDTIOCTL_GENERAL */
typedef struct {
ushort ionode; /* controller number */
ushort timeout; /* timeout */
ulong32 info; /* error info */
ushort status; /* status */
ulong data_len; /* data buffer size */
ulong sense_len; /* sense buffer size */
gdth_cmd_str command; /* command */
} gdth_ioctl_general;
/* GDTIOCTL_LOCKDRV */
typedef struct {
ushort ionode; /* controller number */
unchar lock; /* lock/unlock */
unchar drive_cnt; /* drive count */
ushort drives[MAX_HDRIVES]; /* drives */
} gdth_ioctl_lockdrv;
/* GDTIOCTL_LOCKCHN */
typedef struct {
ushort ionode; /* controller number */
unchar lock; /* lock/unlock */
unchar channel; /* channel */
} gdth_ioctl_lockchn;
/* GDTIOCTL_OSVERS */
typedef struct {
unchar version; /* OS version */
unchar subversion; /* OS subversion */
ushort revision; /* revision */
} gdth_ioctl_osvers;
/* GDTIOCTL_CTRTYPE */
typedef struct {
ushort ionode; /* controller number */
unchar type; /* controller type */
ushort info; /* slot etc. */
ushort oem_id; /* OEM ID */
ushort bios_ver; /* not used */
ushort access; /* not used */
ushort ext_type; /* extended type */
ushort device_id; /* device ID */
ushort sub_device_id; /* sub device ID */
} gdth_ioctl_ctrtype;
/* GDTIOCTL_EVENT */
typedef struct {
ushort ionode;
int erase; /* erase event? */
int handle; /* event handle */
gdth_evt_str event;
} gdth_ioctl_event;
/* GDTIOCTL_RESCAN/GDTIOCTL_HDRLIST */
typedef struct {
ushort ionode; /* controller number */
unchar flag; /* add/remove */
ushort hdr_no; /* drive no. */
struct {
unchar bus; /* SCSI bus */
unchar target; /* target ID */
unchar lun; /* LUN */
unchar cluster_type; /* cluster properties */
} hdr_list[MAX_HDRIVES]; /* index is host drive number */
} gdth_ioctl_rescan;
/* GDTIOCTL_RESET_BUS/GDTIOCTL_RESET_DRV */
typedef struct {
ushort ionode; /* controller number */
ushort number; /* bus/host drive number */
ushort status; /* status */
} gdth_ioctl_reset;
#endif
#endif
/* gdth_proc.c
* $Id: gdth_proc.c,v 1.33 2001/08/10 07:54:39 achim Exp $
* $Id: gdth_proc.c,v 1.35 2003/02/27 15:00:44 achim Exp $
*/
#include "gdth_ioctl.h"
#if LINUX_VERSION_CODE >= 0x020407
#include <linux/completion.h>
#endif
......@@ -33,22 +32,33 @@ int gdth_proc_info(char *buffer,char **start,off_t offset,int length,
static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum)
{
int ret_val;
#if LINUX_VERSION_CODE >= 0x020322
int ret_val = -EINVAL;
#if LINUX_VERSION_CODE >= 0x020503
Scsi_Request *scp;
Scsi_Device *sdev;
#elif LINUX_VERSION_CODE >= 0x020322
Scsi_Cmnd *scp;
Scsi_Device *sdev;
#else
Scsi_Cmnd scp;
Scsi_Device sdev;
#endif
#ifdef GDTH_IOCTL_PROC
gdth_iowr_str *piowr;
TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
piowr = (gdth_iowr_str *)buffer;
#endif
TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
#if LINUX_VERSION_CODE >= 0x020322
sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
scp = scsi_get_command(sdev, GFP_KERNEL);
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
scp = scsi_allocate_request(sdev);
if (!scp)
return -ENOMEM;
scp->sr_cmd_len = 12;
scp->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;
......@@ -56,7 +66,7 @@ static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum)
#else
memset(&sdev,0,sizeof(Scsi_Device));
memset(&scp, 0,sizeof(Scsi_Cmnd));
sdev.host = scp.host = gdth_ctr_vtab[vh];
sdev.host = scp.host = gdth_ctr_tab[hanum];
sdev.id = scp.target = sdev.host->this_id;
scp.device = &sdev;
#endif
......@@ -66,6 +76,7 @@ static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum)
buffer += 5;
length -= 5;
ret_val = gdth_set_asc_info( buffer, length, hanum, scp );
#ifdef GDTH_IOCTL_PROC
} else if (piowr->magic == GDTIOCTL_MAGIC) {
ret_val = gdth_set_bin_info( buffer, length, hanum, scp );
} else {
......@@ -75,19 +86,22 @@ static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum)
printk("GDT: Please update your driver.\n");
else
printk("GDT: Please update your tool.\n");
ret_val = -EINVAL;
#endif
}
} else {
ret_val = -EINVAL;
}
#if LINUX_VERSION_CODE >= 0x020322
scsi_put_command(scp);
#if LINUX_VERSION_CODE >= 0x020503
scsi_release_request(scp);
scsi_free_host_dev(sdev);
#elif LINUX_VERSION_CODE >= 0x020322
scsi_release_command(scp);
scsi_free_host_dev(sdev);
#endif
return ret_val;
}
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp)
#elif LINUX_VERSION_CODE >= 0x020322
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
#else
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
......@@ -98,6 +112,7 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdth_ha_str *ha;
gdth_cmd_str gdtcmd;
gdth_cpar_str *pcpar;
ulong32 paddr;
char cmnd[MAX_COMMAND_SIZE];
memset(cmnd, 0xff, 12);
......@@ -133,7 +148,9 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdtcmd.OpCode = GDT_FLUSH;
gdtcmd.u.cache.DeviceNo = i;
gdtcmd.u.cache.BlockNo = 1;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#else
gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
......@@ -178,23 +195,25 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
}
if (wb_mode) {
if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE))
if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE, &paddr))
return(-EBUSY);
pcpar = (gdth_cpar_str *)ha->pscratch;
memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) );
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_IOCTL;
gdtcmd.u.ioctl.p_param = virt_to_bus(pcpar);
gdtcmd.u.ioctl.p_param = paddr;
gdtcmd.u.ioctl.param_size = sizeof(gdth_cpar_str);
gdtcmd.u.ioctl.subfunc = CACHE_CONFIG;
gdtcmd.u.ioctl.channel = INVALID_CHANNEL;
pcpar->write_back = wb_mode==1 ? 0:1;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &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_ioctl_free(hanum, ha->pscratch);
gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr);
printk("Done.\n");
return(orig_length);
}
......@@ -203,7 +222,10 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
return(-EINVAL);
}
#if LINUX_VERSION_CODE >= 0x020322
#ifdef GDTH_IOCTL_PROC
#if LINUX_VERSION_CODE >= 0x020503
static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Request *scp)
#elif LINUX_VERSION_CODE >= 0x020322
static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
#else
static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
......@@ -216,7 +238,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdth_iord_str *piord;
gdth_cmd_str *pcmd;
gdth_evt_str *pevt;
ulong32 *ppadd, add_size, *ppadd2, add_size2, info;
ulong32 *ppadd, add_size, *ppadd2, add_size2, info, paddr;
ulong flags;
gdth_cmd_str gdtcmd;
int drv_cyls, drv_hds, drv_secs;
......@@ -273,21 +295,25 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
return(-EINVAL);
}
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2,
TRUE ))
TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str) + add_size + add_size2;
if (add_size > 0) {
memcpy(piord->iu.general.data, piowr->iu.general.data, add_size);
*ppadd = virt_to_bus(piord->iu.general.data);
*ppadd = paddr + GDTOFFSOF(gdth_iord_str, iu.general.data[0]);
}
if (add_size2 > 0) {
memcpy(piord->iu.general.data+add_size, piowr->iu.general.data, add_size2);
*ppadd2 = virt_to_bus(piord->iu.general.data+add_size);
*ppadd2 = paddr + GDTOFFSOF(gdth_iord_str, iu.general.data[0]) + add_size2;
}
/* do IOCTL */
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, pcmd, cmnd, piowr->timeout);
piord->status = (scp->sr_command->SCp.Message << 16) |
scp->sr_command->SCp.Status;
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout);
piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
#else
......@@ -297,7 +323,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_DRVERS:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
......@@ -306,7 +332,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_CTRTYPE:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
......@@ -332,7 +358,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_CTRCNT:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
......@@ -341,7 +367,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_OSVERS:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
......@@ -352,7 +378,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_LOCKDRV:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
for (i = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) {
......@@ -378,7 +404,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_LOCKCHN:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
i = piowr->iu.lockchn.channel;
if (i < ha->bus_cnt) {
......@@ -406,7 +432,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_EVENT:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
if (piowr->iu.event.erase == 0xff) {
......@@ -439,16 +465,19 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
piord->size = sizeof(gdth_iord_str);
piord->status = S_OK;
break;
case GDTIOCTL_SCSI:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
#if LINUX_VERSION_CODE >= 0x020503
return(-EINVAL);
#else
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
memcpy(cmnd, piowr->iu.scsi.cmd, 12);
#if LINUX_VERSION_CODE >= 0x020322
scp->device->id = piowr->iu.scsi.target;
scp->device->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
scp->target = piowr->iu.scsi.target;
scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
scp->cmd_len = piowr->iu.scsi.cmd_len;
gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout);
piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
......@@ -458,16 +487,48 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
scp.cmd_len = piowr->iu.scsi.cmd_len;
gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout);
piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;
#endif
#endif
break;
case GDTIOCTL_RESET_BUS:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
#if LINUX_VERSION_CODE >= 0x020322
scp->device->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
#if LINUX_VERSION_CODE >= 0x02053C
{
Scsi_Device *sdev;
Scsi_Cmnd *scmnd;
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
scmnd= scsi_get_command(sdev, GFP_KERNEL);
if (!scmnd)
return(-ENOMEM);
scmnd->device->host = scp->sr_host;
scmnd->device->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
piord->status = (ulong32)gdth_eh_bus_reset( scmnd );
if (piord->status == SUCCESS)
piord->status = S_OK;
else
piord->status = S_GENERR;
scsi_put_command(scmnd);
scsi_free_host_dev(sdev);
}
#elif LINUX_VERSION_CODE >= 0x020503
{
Scsi_Cmnd scmnd;
scmnd.host = scp->sr_host;
scmnd.channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
piord->status = (ulong32)gdth_eh_bus_reset( &scmnd );
if (piord->status == SUCCESS)
piord->status = S_OK;
else
piord->status = S_GENERR;
}
#elif LINUX_VERSION_CODE >= 0x020322
scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
piord->status = (ulong32)gdth_eh_bus_reset( scp );
if (piord->status == SUCCESS)
piord->status = S_OK;
......@@ -486,7 +547,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_HDRLIST:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
......@@ -501,7 +562,12 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_CLUST_INFO;
gdtcmd.u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status == S_OK)
piord->iu.hdr_list[i].cluster_type =
(unchar)scp->sr_command->SCp.Message;
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
if (scp->SCp.Status == S_OK)
piord->iu.hdr_list[i].cluster_type =
......@@ -520,7 +586,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_RESCAN:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
......@@ -532,7 +598,11 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_INIT;
gdtcmd.u.cache.DeviceNo = LINUX_OS;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
status = (ushort)scp->sr_command->SCp.Status;
info = (ulong32)scp->sr_command->SCp.Message;
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
......@@ -557,7 +627,11 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_INFO;
gdtcmd.u.cache.DeviceNo = k;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
status = (ushort)scp->sr_command->SCp.Status;
info = (ulong32)scp->sr_command->SCp.Message;
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
......@@ -591,7 +665,11 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_DEVTYPE;
gdtcmd.u.cache.DeviceNo = k;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
status = (ushort)scp->sr_command->SCp.Status;
info = (ulong32)scp->sr_command->SCp.Message;
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
......@@ -609,7 +687,11 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_CLUST_INFO;
gdtcmd.u.cache.DeviceNo = k;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
status = (ushort)scp->sr_command->SCp.Status;
info = (ulong32)scp->sr_command->SCp.Message;
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
......@@ -628,7 +710,11 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_RW_ATTRIBS;
gdtcmd.u.cache.DeviceNo = k;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
status = (ushort)scp->sr_command->SCp.Status;
info = (ulong32)scp->sr_command->SCp.Message;
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
......@@ -646,7 +732,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_RESET_DRV:
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr ))
return(-EBUSY);
piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
......@@ -656,7 +742,10 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_CLUST_RESET;
gdtcmd.u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
piord->status = (ushort)scp->sr_command->SCp.Status;
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
#else
......@@ -671,6 +760,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
}
return length;
}
#endif
static int gdth_get_info(char *buffer,char **start,off_t offset,
int length,int vh,int hanum,int busnum)
......@@ -678,14 +768,16 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
int size = 0,len = 0;
off_t begin = 0,pos = 0;
gdth_ha_str *ha;
gdth_iord_str *piord;
int id, i, j, k, sec, flag;
int no_mdrv = 0, drv_no, is_mirr;
ulong32 cnt;
ulong32 cnt, paddr;
gdth_cmd_str gdtcmd;
gdth_evt_str estr;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
Scsi_Request *scp;
Scsi_Device *sdev;
#elif LINUX_VERSION_CODE >= 0x020322
Scsi_Cmnd *scp;
Scsi_Device *sdev;
#else
......@@ -710,9 +802,16 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum));
ha = HADATA(gdth_ctr_tab[hanum]);
#if LINUX_VERSION_CODE >= 0x020322
sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
scp = scsi_get_command(sdev, GFP_KERNEL);
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
scp = scsi_allocate_request(sdev);
if (!scp)
return -ENOMEM;
scp->sr_cmd_len = 12;
scp->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;
......@@ -720,13 +819,15 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
#else
memset(&sdev,0,sizeof(Scsi_Device));
memset(&scp, 0,sizeof(Scsi_Cmnd));
sdev.host = scp.host = gdth_ctr_vtab[vh];
sdev.host = scp.host = gdth_ctr_tab[hanum];
sdev.id = scp.target = sdev.host->this_id;
scp.device = &sdev;
#endif
#ifdef GDTH_IOCTL_PROC
/* ioctl from tool? */
if (!gdth_ioctl_check_bin(hanum, (ushort)length)) {
#endif
/* request is i.e. "cat /proc/scsi/gdth/0" */
/* format: %-15s\t%-10s\t%-15s\t%s */
/* driver parameters */
......@@ -798,7 +899,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
len += size; pos = begin + len;
flag = FALSE;
buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
if (!buf)
goto stop_output;
for (i = 0; i < ha->bus_cnt; ++i) {
......@@ -807,7 +908,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4);
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_IOCTL;
gdtcmd.u.ioctl.p_param = virt_to_bus(pds);
gdtcmd.u.ioctl.p_param = paddr + GDTH_SCRATCH/4;
gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4;
gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
......@@ -818,7 +919,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
sizeof(pds->list[0]);
if (pds->entries > cnt)
pds->entries = cnt;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status != S_OK)
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
if (scp->SCp.Status != S_OK)
#else
......@@ -837,12 +941,15 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
pdi = (gdth_diskinfo_str *)buf;
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_IOCTL;
gdtcmd.u.ioctl.p_param = virt_to_bus(pdi);
gdtcmd.u.ioctl.p_param = paddr;
gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str);
gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
gdtcmd.u.ioctl.channel =
ha->raw[i].address | ha->raw[i].id_list[j];
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status == S_OK)
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
if (scp->SCp.Status == S_OK)
#else
......@@ -892,13 +999,16 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
pdef = (gdth_defcnt_str *)buf;
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_IOCTL;
gdtcmd.u.ioctl.p_param = virt_to_bus(pdef);
gdtcmd.u.ioctl.p_param = paddr;
gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str);
gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
gdtcmd.u.ioctl.channel =
ha->raw[i].address | ha->raw[i].id_list[j];
pdef->sddc_type = 0x08;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status == S_OK)
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
if (scp->SCp.Status == S_OK)
#else
......@@ -920,7 +1030,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
goto stop_output;
}
}
gdth_ioctl_free(hanum, buf);
gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
if (!flag) {
size = sprintf(buffer+len, "\n --\n");
......@@ -932,7 +1042,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
len += size; pos = begin + len;
flag = FALSE;
buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
if (!buf)
goto stop_output;
for (i = 0; i < MAX_LDRIVES; ++i) {
......@@ -947,11 +1057,14 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
pcdi = (gdth_cdrinfo_str *)buf;
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_IOCTL;
gdtcmd.u.ioctl.p_param = virt_to_bus(pcdi);
gdtcmd.u.ioctl.p_param = paddr;
gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO;
gdtcmd.u.ioctl.channel = drv_no;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status != S_OK)
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
if (scp->SCp.Status != S_OK)
#else
......@@ -1034,7 +1147,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
if (pos > offset + length)
goto stop_output;
}
gdth_ioctl_free(hanum, buf);
gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
if (!flag) {
size = sprintf(buffer+len, "\n --\n");
......@@ -1046,7 +1159,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
len += size; pos = begin + len;
flag = FALSE;
buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
if (!buf)
goto stop_output;
for (i = 0; i < MAX_LDRIVES; ++i) {
......@@ -1057,11 +1170,14 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
pai = (gdth_arrayinf_str *)buf;
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_IOCTL;
gdtcmd.u.ioctl.p_param = virt_to_bus(pai);
gdtcmd.u.ioctl.p_param = paddr;
gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str);
gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
gdtcmd.u.ioctl.channel = i;
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status == S_OK)
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
if (scp->SCp.Status == S_OK)
#else
......@@ -1112,7 +1228,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
goto stop_output;
}
}
gdth_ioctl_free(hanum, buf);
gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
if (!flag) {
size = sprintf(buffer+len, "\n --\n");
......@@ -1124,7 +1240,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
len += size; pos = begin + len;
flag = FALSE;
buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr);
if (!buf)
goto stop_output;
for (i = 0; i < MAX_LDRIVES; ++i) {
......@@ -1136,13 +1252,16 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
phg = (gdth_hget_str *)buf;
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_IOCTL;
gdtcmd.u.ioctl.p_param = virt_to_bus(phg);
gdtcmd.u.ioctl.p_param = paddr;
gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str);
gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
gdtcmd.u.ioctl.channel = i;
phg->entries = MAX_HDRIVES;
phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]);
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
gdth_do_req(scp, &gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status != S_OK)
#elif LINUX_VERSION_CODE >= 0x020322
gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
if (scp->SCp.Status != S_OK)
#else
......@@ -1164,7 +1283,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
}
}
}
gdth_ioctl_free(hanum, buf);
gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr);
for (i = 0; i < MAX_HDRIVES; ++i) {
if (!(ha->hdr[i].present))
......@@ -1221,20 +1340,27 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
if (id == -1)
break;
}
#ifdef GDTH_IOCTL_PROC
} else {
gdth_iord_str *piord;
/* request from tool (GDTMON,..) */
piord = (gdth_iord_str *)ha->pscratch;
if (piord == NULL)
goto stop_output;
length = piord->size;
memcpy(buffer+len, (char *)piord, length);
gdth_ioctl_free(hanum, ha->pscratch);
gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr);
len = length;
}
#endif
stop_output:
#if LINUX_VERSION_CODE >= 0x020322
scsi_put_command(scp);
#if LINUX_VERSION_CODE >= 0x020503
scsi_release_request(scp);
scsi_free_host_dev(sdev);
#elif LINUX_VERSION_CODE >= 0x020322
scsi_release_command(scp);
scsi_free_host_dev(sdev);
#endif
*start = buffer +(offset-begin);
......@@ -1246,6 +1372,26 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
return(len);
}
#if LINUX_VERSION_CODE >= 0x020503
static void gdth_do_req(Scsi_Request *scp, gdth_cmd_str *gdtcmd,
char *cmnd, int timeout)
{
unsigned bufflen;
DECLARE_COMPLETION(wait);
TRACE2(("gdth_do_req()\n"));
if (gdtcmd != NULL) {
bufflen = sizeof(gdth_cmd_str);
} else {
bufflen = 0;
}
scp->sr_request->rq_status = RQ_SCSI_BUSY;
scp->sr_request->waiting = &wait;
scsi_do_req(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
wait_for_completion(&wait);
}
#else
static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd,
char *cmnd, int timeout)
{
......@@ -1266,8 +1412,8 @@ static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd,
scp->SCp.this_residual = DEFAULT_PRI;
bufflen = 0;
}
scp->request.rq_status = RQ_SCSI_BUSY;
#if LINUX_VERSION_CODE >= 0x020407
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);
......@@ -1283,46 +1429,53 @@ static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd,
down(&sem);
#endif
}
#endif
void gdth_scsi_done(Scsi_Cmnd *scp)
{
TRACE2(("gdth_scsi_done()\n"));
#if LINUX_VERSION_CODE >= 0x020503
scp->request->rq_status = RQ_SCSI_DONE;
if (scp->request->waiting != NULL)
complete(scp->request->waiting);
#elif LINUX_VERSION_CODE >= 0x020407
scp->request.rq_status = RQ_SCSI_DONE;
#if LINUX_VERSION_CODE >= 0x020407
if (scp->request.waiting != NULL)
complete(scp->request.waiting);
#else
scp->request.rq_status = RQ_SCSI_DONE;
if (scp->request.sem != NULL)
up(scp->request.sem);
#endif
}
static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch)
static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
ulong32 *paddr)
{
gdth_ha_str *ha;
ulong flags;
char *ret_val;
if (size == 0 || size > GDTH_SCRATCH)
return FALSE;
if (size == 0)
return NULL;
ha = HADATA(gdth_ctr_tab[hanum]);
GDTH_LOCK_HA(ha, flags);
if (scratch) {
if (!ha->scratch_busy) {
ha->scratch_busy = TRUE;
ret_val = ha->pscratch;
} else
ret_val = NULL;
if (!ha->scratch_busy && size <= GDTH_SCRATCH) {
ha->scratch_busy = TRUE;
ret_val = ha->pscratch;
*paddr = ha->scratch_phys;
} else if (scratch) {
ret_val = NULL;
} else {
#if LINUX_VERSION_CODE >= 0x020322
ret_val = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA,
GDTH_SCRATCH_ORD);
#if LINUX_VERSION_CODE >= 0x020400
ret_val = pci_alloc_consistent(ha->pdev, size, paddr);
#else
ret_val = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
ret_val = scsi_init_malloc(size, GFP_ATOMIC | GFP_DMA);
if (ret_val)
*paddr = virt_to_bus(ret_val);
#endif
}
......@@ -1330,7 +1483,7 @@ static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch)
return ret_val;
}
static void gdth_ioctl_free(int hanum, char *buf)
static void gdth_ioctl_free(int hanum, int size, char *buf, ulong32 paddr)
{
gdth_ha_str *ha;
ulong flags;
......@@ -1341,16 +1494,17 @@ static void gdth_ioctl_free(int hanum, char *buf)
if (buf == ha->pscratch) {
ha->scratch_busy = FALSE;
} else {
#if LINUX_VERSION_CODE >= 0x020322
free_pages((unsigned long)buf, GDTH_SCRATCH_ORD);
#if LINUX_VERSION_CODE >= 0x020400
pci_free_consistent(ha->pdev, size, buf, paddr);
#else
scsi_init_free((void *)buf, GDTH_SCRATCH);
scsi_init_free((void *)buf, size);
#endif
}
GDTH_UNLOCK_HA(ha, flags);
}
#ifdef GDTH_IOCTL_PROC
static int gdth_ioctl_check_bin(int hanum, ushort size)
{
gdth_ha_str *ha;
......@@ -1368,7 +1522,7 @@ static int gdth_ioctl_check_bin(int hanum, ushort size)
GDTH_UNLOCK_HA(ha, flags);
return ret_val;
}
#endif
static void gdth_wait_completion(int hanum, int busnum, int id)
{
......@@ -1376,23 +1530,39 @@ static void gdth_wait_completion(int hanum, int busnum, int id)
ulong flags;
int i;
Scsi_Cmnd *scp;
unchar b;
unchar b, t;
ha = HADATA(gdth_ctr_tab[hanum]);
GDTH_LOCK_HA(ha, flags);
for (i = 0; i < GDTH_MAXCMDS; ++i) {
scp = ha->cmd_tab[i].cmnd;
#if LINUX_VERSION_CODE >= 0x02053C
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
if (!SPECIAL_SCP(scp) && scp->device->id == (unchar)id &&
t = scp->device->id;
#else
b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
t = scp->target;
#endif
if (!SPECIAL_SCP(scp) && t == (unchar)id &&
b == (unchar)busnum) {
scp->SCp.have_data_in = 0;
GDTH_UNLOCK_HA(ha, flags);
while (!scp->SCp.have_data_in)
barrier();
#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
GDTH_LOCK_HA(ha, flags);
}
}
......@@ -1404,14 +1574,20 @@ static void gdth_stop_timeout(int hanum, int busnum, int id)
gdth_ha_str *ha;
ulong flags;
Scsi_Cmnd *scp;
unchar b;
unchar b, t;
ha = HADATA(gdth_ctr_tab[hanum]);
GDTH_LOCK_HA(ha, flags);
for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
#if LINUX_VERSION_CODE >= 0x02053C
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
if (scp->device->id == (unchar)id && b == (unchar)busnum) {
t = scp->device->id;
#else
b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
t = scp->target;
#endif
if (t == (unchar)id && b == (unchar)busnum) {
TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
}
......@@ -1424,14 +1600,20 @@ static void gdth_start_timeout(int hanum, int busnum, int id)
gdth_ha_str *ha;
ulong flags;
Scsi_Cmnd *scp;
unchar b;
unchar b, t;
ha = HADATA(gdth_ctr_tab[hanum]);
GDTH_LOCK_HA(ha, flags);
for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
#if LINUX_VERSION_CODE >= 0x02053C
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
if (scp->device->id == (unchar)id && b == (unchar)busnum) {
t = scp->device->id;
#else
b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
t = scp->target;
#endif
if (t == (unchar)id && b == (unchar)busnum) {
TRACE2(("gdth_start_timeout(): update_timeout()\n"));
gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
}
......@@ -1464,7 +1646,7 @@ static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout)
timer_table[SCSI_TIMER].expires = jiffies + timeout;
timer_active |= 1 << SCSI_TIMER;
} else {
if (time_before(jiffies + timeout, timer_table[SCSI_TIMER].expires))
if (jiffies + timeout < timer_table[SCSI_TIMER].expires)
timer_table[SCSI_TIMER].expires = jiffies + timeout;
}
}
......
......@@ -2,26 +2,42 @@
#define _GDTH_PROC_H
/* gdth_proc.h
* $Id: gdth_proc.h,v 1.11 2001/07/25 15:37:40 achim Exp $
* $Id: gdth_proc.h,v 1.13 2003/02/27 14:59:25 achim Exp $
*/
static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum);
static int gdth_get_info(char *buffer,char **start,off_t offset,
int length,int vh,int hanum,int busnum);
#if LINUX_VERSION_CODE >= 0x020322
#if LINUX_VERSION_CODE >= 0x020503
static void gdth_do_req(Scsi_Request *srp, gdth_cmd_str *cmd,
char *cmnd, int timeout);
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp);
#ifdef GDTH_IOCTL_PROC
static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Request *scp);
#endif
#elif LINUX_VERSION_CODE >= 0x020322
static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd,
char *cmnd, int timeout);
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
#ifdef GDTH_IOCTL_PROC
static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
#endif
#else
static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd,
char *cmnd, int timeout);
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
#ifdef GDTH_IOCTL_PROC
static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
#endif
static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd,
char *cmnd, int timeout);
#endif
static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch);
static void gdth_ioctl_free(int hanum, char *buf);
static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
ulong32 *paddr);
static void gdth_ioctl_free(int hanum, int size, char *buf, ulong32 paddr);
#ifdef GDTH_IOCTL_PROC
static int gdth_ioctl_check_bin(int hanum, ushort size);
#endif
static void gdth_wait_completion(int hanum, int busnum, int id);
static void gdth_stop_timeout(int hanum, int busnum, int id);
static void gdth_start_timeout(int hanum, int busnum, int id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment