bk://linux-scsi.bkbits.net/scsi-misc-2.6 jejb@mulgrave.(none)|ChangeSet|20040521155324|50897 jejb # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/05/21 19:06:39-07:00 akpm@bix.(none) # Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6 # into bix.(none):/usr/src/bk-scsi # # drivers/scsi/Kconfig # 2004/05/21 19:06:36-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/21 10:53:24-05:00 jejb@mulgrave.(none) # SCSI: make inquiry timeout tuneable # # From: garloff@suse.de # # Feature # # Make the timeout for INQUIRY during SCSI scan adjustable via boot parameter. # Note that the second INQUIRY does use a shorter timeout, as the long timeout # is for recovery from the initial reset, not because existing devices would # take so long to answer INQUIRY. SPC3 says that INQUIRY should be available # right away, but real life is different unfortunately. # # drivers/scsi/scsi_scan.c # 2004/05/21 10:53:07-05:00 jejb@mulgrave.(none) +9 -2 # SCSI: make inquiry timeout tuneable # # ChangeSet # 2004/05/21 10:51:57-05:00 jejb@mulgrave.(none) # SCSI: make SCSI REPORT LUNS the default # # From: garloff@suse.de # # Cleanup/Feature # # Remove CONFIG_SCSI_REPORT_LUNS config option. # Instead provide BLIST_NOREPORTLUN that can be passed as default_dev_flags # (but also per device if needed). # Provide BLIST_REPORTLUN2 that allows trying to use REPORT_LUNS for SCSI-2 # devices, if they are connected to a host adapter supporting more than 8 LUNs # (and thus avoiding the usual USB crap to render this feature useless when # used with default_dev_flags). # # drivers/scsi/Kconfig | 11 ----------- # drivers/scsi/scsi_scan.c | 19 +++++++++---------- # include/scsi/scsi_devinfo.h | 3 +++ # 3 files changed, 12 insertions(+), 21 deletions(-) # # include/scsi/scsi_devinfo.h # 2004/05/21 10:51:42-05:00 jejb@mulgrave.(none) +3 -0 # SCSI: make SCSI REPORT LUNS the default # # drivers/scsi/scsi_scan.c # 2004/05/21 10:51:42-05:00 jejb@mulgrave.(none) +9 -10 # SCSI: make SCSI REPORT LUNS the default # # drivers/scsi/Kconfig # 2004/05/21 10:51:42-05:00 jejb@mulgrave.(none) +0 -11 # SCSI: make SCSI REPORT LUNS the default # # ChangeSet # 2004/05/21 10:48:13-05:00 jejb@mulgrave.(none) # SCSI: deprecate BLIST_FORCELUN # # From: garloff@suse.de # # Cleanup # # Mark BLIST_FORCELUN as deprecated, as we don't want to collect a list # of perfectly working multi-LUN devices with BLIST_FORCELUN. Instead # document max_luns boot/module parameter. # # include/scsi/scsi_devinfo.h # 2004/05/21 10:47:57-05:00 jejb@mulgrave.(none) +2 -1 # SCSI: deprecate BLIST_FORCELUN # # drivers/scsi/Kconfig # 2004/05/21 10:47:57-05:00 jejb@mulgrave.(none) +2 -2 # SCSI: deprecate BLIST_FORCELUN # # ChangeSet # 2004/05/21 10:46:21-05:00 jejb@mulgrave.(none) # SCSI: logging optimisation # # From: garloff@suse.de # # Optimization. # # Tell the compiler that the SCSI LOG will not likely happen. # # drivers/scsi/scsi_logging.h # 2004/05/21 10:46:04-05:00 jejb@mulgrave.(none) +1 -1 # SCSI: logging optimisation # # ChangeSet # 2004/05/21 10:31:54-05:00 rusty@rustcorp.com.au # [PATCH] [TRIVIAL 2.6] drivers_scsi_nsp32.c: kill duplicate # # From: a.othieno@bluewin.ch (Arthur Othieno) # # drivers/scsi/nsp32.c # 2004/05/20 00:59:33-05:00 rusty@rustcorp.com.au +0 -1 # [TRIVIAL 2.6] drivers_scsi_nsp32.c: kill duplicate # # ChangeSet # 2004/05/21 10:30:21-05:00 g.liakhovetski@gmx.de # [PATCH] tmscsim: remove legacy and void code # # This one is purely cosmetic - it removes legacy (pre 2.4) and some void # (e.g. #defined as nothing locks) code. So, it doesn't affect the resulting # object file. # # drivers/scsi/tmscsim.c # 2004/05/20 18:09:04-05:00 g.liakhovetski@gmx.de +7 -157 # tmscsim: remove legacy and void code # # drivers/scsi/scsiiom.c # 2004/05/20 18:09:12-05:00 g.liakhovetski@gmx.de +2 -18 # tmscsim: remove legacy and void code # # ChangeSet # 2004/05/21 10:28:12-05:00 g.liakhovetski@gmx.de # tmscsim: remove procfs write support from tmscsim # # From: Christoph Hellwig # # When looking at the driver after reviewing the changes I stubled over # that code. Almost all of the funcitonality (except DUMP) should go # through the midlayer and will at least cause some confusion if it # doesn't. # # Also the implementation isn't exactly nice, like kmalloced scsi commands # and the tytpical 'parsing' macros cut & pasted over all historic scsi # drivers. I think we're better of removing it completly and maybe readd # dump as a sysfs attribute if needed. # # 500 lines of code gone. # # drivers/scsi/tmscsim.c # 2004/01/31 00:41:21-06:00 g.liakhovetski@gmx.de +1 -500 # tmscsim: remove procfs write support from tmscsim # # ChangeSet # 2004/05/21 10:27:19-05:00 akpm@osdl.org # [PATCH] qlogicfas408.c warning fix # # drivers/scsi/qlogicfas.c:190: warning: initialization from incompatible pointer type # # drivers/scsi/qlogicfas408.h # 2004/05/16 02:45:03-05:00 akpm@osdl.org +1 -1 # qlogicfas408.c warning fix # # drivers/scsi/qlogicfas408.c # 2004/05/16 02:45:04-05:00 akpm@osdl.org +1 -1 # qlogicfas408.c warning fix # # ChangeSet # 2004/05/21 10:21:03-05:00 g.liakhovetski@gmx.de # [PATCH] tmscsim: no internal queue # # Here comes the 2nd one. I wanted to get Christoph's patches now in, but # already the first his patch comes on the top of this one: remove internal # command queuing in the driver. And, in fact, it fixes some bugs in it. So, # they should go in together. Here's the original comment from Christoph's # email of 1 Feb 2004: # # # # Patch looks mostly good for me. But there's some fishyness in queuecommand, # mostly from before you patch: # # - many failure cases return one with the new EH code although we wouldn't # want to requeue the midlayer in that case. I removed the ifdef and added # a failed goto to handle them. # - we need to set cmd->result onlyh if we have an error instead of always # an overriding it - else it will leak to the midlayer in the return 1 # case. # - the check for ids out of range are superflous (this was one of the errors # above, I decided to remove it instead of fixing it). # - you don't do DC390_UNLOCK_ACB when failing. While it's a noop I think # it's bad to have locking macros in place and don't balance them. You # should probably remove it completly in one of the next patches. # - the pDCB->pWaitingSRB looks a bit strange. By unifying the the codepathes # it becomes much more readable. # # # # drivers/scsi/tmscsim.h # 2004/03/04 15:21:39-06:00 g.liakhovetski@gmx.de +6 -17 # tmscsim: no internal queue # # drivers/scsi/tmscsim.c # 2004/05/19 18:03:25-05:00 g.liakhovetski@gmx.de +26 -153 # tmscsim: no internal queue # # drivers/scsi/scsiiom.c # 2004/03/04 15:21:39-06:00 g.liakhovetski@gmx.de +0 -3 # tmscsim: no internal queue # # ChangeSet # 2004/05/21 10:16:18-05:00 hch@lst.de # [PATCH] fix assorted wd7000 warnings # # - needs linux/delay.h for udelay # - C doesn't allow taking addresses of register variables and gcc even # complains these days # # drivers/scsi/wd7000.c # 2004/05/19 12:46:14-05:00 hch@lst.de +4 -3 # fix assorted wd7000 warnings # # ChangeSet # 2004/05/21 10:07:05-05:00 g.liakhovetski@gmx.de # [PATCH] tmscsim: 64-bit cleanup # # Ok, here comes the first one. I chose this one because it fixes an actual # bug in the driver. This bug was (partially) introduced by myself when # porting to 2.6. Partly the reason was that I disliked using # function-like macros as lvalues: # # sg_dma_address(x) = ... # sg_dma_len(x) = ... # # [OT] wouldn't it be better to introduce some macros like # set_sg_dma_{address|len}(x, y)? # # A part of the original patch has already been merged (s/UINT/ULONG/), so, # the actual version is re-diffed against 2.6.6-bk6 and re-tested (on a # plain Pentium). # # Also updates the driver-version, printed on startup. # # drivers/scsi/tmscsim.c # 2004/04/13 17:50:05-05:00 g.liakhovetski@gmx.de +11 -7 # tmscsim: 64-bit cleanup # # drivers/scsi/scsiiom.c # 2004/04/13 17:46:19-05:00 g.liakhovetski@gmx.de +7 -5 # tmscsim: 64-bit cleanup # # drivers/scsi/dc390.h # 2004/04/13 17:50:26-05:00 g.liakhovetski@gmx.de +1 -1 # tmscsim: 64-bit cleanup # # ChangeSet # 2004/05/19 18:28:38-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-scsi # # drivers/scsi/dpt_i2o.c # 2004/05/19 18:28:35-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/19 11:12:20-05:00 jejb@mulgrave.(none) # SCSI: fix Stack overflow when lldd returns SCSI_MLQUEUE_DEVICE_BUSY # # From: Heiko Carstens # # This happened when sending out the inquiry command and the LLDD was in # recovery for the specific LUN and returned SCSI_MLQUEUE_DEVICE_BUSY. # Problem is that max_device_blocked gets set _after_ the inquiry command # finished. In this specific case max_device_blocked was 0 and thus the # device was never blocked resulting in the observed stack overflow. # I moved the initializazion of max_device_blocked from scsi_add_lun to # sdev_alloc_sdev and the problem is gone. # # drivers/scsi/scsi_scan.c # 2004/05/19 11:11:55-05:00 jejb@mulgrave.(none) +5 -4 # SCSI: fix Stack overflow when lldd returns SCSI_MLQUEUE_DEVICE_BUSY # # ChangeSet # 2004/05/16 01:49:51-07:00 akpm@bix.(none) # Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6 # into bix.(none):/usr/src/bk-scsi # # drivers/scsi/sg.c # 2004/05/16 01:49:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/scsi/Kconfig # 2004/05/16 01:49:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/15 08:42:53-05:00 jejb@mulgrave.(none) # scsi sg: fix smp_call_function() with intrs disabled # # From: Matthew Wilcox , # Douglas Gilbert # # - Fix vmalloc,vfree with intrs disabled # - bump version number # - introduce MODULE_VERSION # - increase over allocation of sg_dev_arr from 6 to 32 # # drivers/scsi/sg.c # 2004/05/15 08:42:13-05:00 jejb@mulgrave.(none) +77 -76 # scsi sg: fix smp_call_function() with intrs disabled # # ChangeSet # 2004/05/15 08:37:26-05:00 akpm@osdl.org # [PATCH] Fix dpt_i2o # # From: Go Taniguchi # # Make it build (and work) again. # # drivers/scsi/dpti.h # 2004/04/27 03:58:25-05:00 akpm@osdl.org +2 -2 # Fix dpt_i2o # # drivers/scsi/dpt_i2o.c # 2004/04/27 03:58:25-05:00 akpm@osdl.org +118 -38 # Fix dpt_i2o # # drivers/scsi/Kconfig # 2004/04/27 03:58:25-05:00 akpm@osdl.org +1 -1 # Fix dpt_i2o # # ChangeSet # 2004/05/13 15:03:44-05:00 jejb@mulgrave.(none) # gdth driver update to 3.04 # # From: Leubner, Achim # # - Support for drives > 2 TB implemented # - 64-bit DMA support depending on the controller firmware version implemented # - Some important bug fixes made # # drivers/scsi/gdth_proc.h # 2004/05/13 15:02:45-05:00 jejb@mulgrave.(none) +9 -20 # gdth driver update to 3.04 # # drivers/scsi/gdth_proc.c # 2004/05/13 15:02:45-05:00 jejb@mulgrave.(none) +525 -1066 # gdth driver update to 3.04 # # drivers/scsi/gdth_ioctl.h # 2004/05/13 15:02:45-05:00 jejb@mulgrave.(none) +41 -9 # gdth driver update to 3.04 # # drivers/scsi/gdth.h # 2004/05/13 15:02:45-05:00 jejb@mulgrave.(none) +115 -42 # gdth driver update to 3.04 # # drivers/scsi/gdth.c # 2004/05/13 15:02:45-05:00 jejb@mulgrave.(none) +1758 -1354 # gdth driver update to 3.04 # # ChangeSet # 2004/05/13 12:40:33-05:00 dougg@torque.net # [PATCH] st.c for GET_IDLUN # # A little more testing of st's SG_IO ioctl turned up a # small problem. # # This is the corresponding patch that was applied to the # sd driver when it received the block layer SG_IO ioctl. # # For least surprise of lk 2.4 utilities that use the # SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER # ioctls (e.g. sg_map) it is better to return the correct # values rather than 0. # # drivers/scsi/st.c # 2004/04/25 03:13:50-05:00 dougg@torque.net +11 -5 # st.c for GET_IDLUN # # ChangeSet # 2004/05/13 12:36:42-05:00 jejb@mulgrave.(none) # Fix SCSI device state model # # Following a prior patch, we made cancel the sole # route into deleted, but forgot to update the # state model checks to reflect this. # # offline and created also go to cancel # # drivers/scsi/scsi_lib.c # 2004/05/13 12:36:01-05:00 jejb@mulgrave.(none) +2 -2 # Fix SCSI device state model # # ChangeSet # 2004/05/11 11:16:45-05:00 jejb@mulgrave.(none) # Make st support the scsi_device timeout # # From: Brian King # # drivers/scsi/st.h # 2004/05/11 11:16:20-05:00 jejb@mulgrave.(none) +0 -1 # Make st support the scsi_device timeout # # drivers/scsi/st.c # 2004/05/11 11:16:20-05:00 jejb@mulgrave.(none) +19 -19 # Make st support the scsi_device timeout # # ChangeSet # 2004/05/11 10:33:58-05:00 alan@redhat.com # [PATCH] PATCH: Do something about aacraid # # This is a fairly minimal fix for aacraid. It removes the happy cast # pointers to u32 garbage in the 2.6 code and replaces it with the working # 2.4 equivalents. I've not backported any of the other changes from 2.4 to # 2.6 yet, and some things have gone which are good to be gone (eg the # proc/scsi horror). There is a certain amount of white space noise caused # by realigning with the 2.4 code so I could see what was going on. # # Tested on a dual opteron # # drivers/scsi/aacraid/sa.c # 2004/05/10 15:21:30-05:00 alan@redhat.com +5 -0 # PATCH: Do something about aacraid # # drivers/scsi/aacraid/dpcsup.c # 2004/05/10 15:23:18-05:00 alan@redhat.com +34 -19 # PATCH: Do something about aacraid # # drivers/scsi/aacraid/commsup.c # 2004/05/10 15:16:08-05:00 alan@redhat.com +48 -33 # PATCH: Do something about aacraid # # drivers/scsi/aacraid/comminit.c # 2004/05/10 15:11:56-05:00 alan@redhat.com +6 -3 # PATCH: Do something about aacraid # # drivers/scsi/aacraid/commctrl.c # 2004/05/10 15:22:40-05:00 alan@redhat.com +20 -17 # PATCH: Do something about aacraid # # drivers/scsi/aacraid/aacraid.h # 2004/05/10 15:02:37-05:00 alan@redhat.com +35 -122 # PATCH: Do something about aacraid # # drivers/scsi/aacraid/README # 2004/05/10 15:20:16-05:00 alan@redhat.com +6 -2 # PATCH: Do something about aacraid # diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig --- a/drivers/scsi/Kconfig Fri May 21 19:07:22 2004 +++ b/drivers/scsi/Kconfig Fri May 21 19:07:22 2004 @@ -149,19 +149,8 @@ can say Y here to force the SCSI driver to probe for multiple LUNs. A SCSI device with multiple LUNs acts logically like multiple SCSI devices. The vast majority of SCSI devices have only one LUN, and - so most people can say N here and should in fact do so, because it - is safer. - -config SCSI_REPORT_LUNS - bool "Build with SCSI REPORT LUNS support" - depends on SCSI - default y - help - If you want support for SCSI REPORT LUNS, say Y here. - The REPORT LUNS command is useful for devices (such as disk arrays) - with large numbers of LUNs where the LUN values are not contiguous - (sparse LUN). REPORT LUNS scanning is done only for SCSI-3 devices. - Most users can safely answer N here. + so most people can say N here. The max_luns boot/module parameter + allows to override this setting. config SCSI_CONSTANTS bool "Verbose SCSI error reporting (kernel size +=12K)" @@ -363,7 +352,7 @@ # All the I2O code and drivers do not seem to be 64bit safe. config SCSI_DPT_I2O tristate "Adaptec I2O RAID support " - depends on !64BIT && SCSI && BROKEN + depends on !64BIT && SCSI help This driver supports all of Adaptec's I2O based RAID controllers as well as the DPT SmartRaid V cards. This is an Adaptec maintained diff -Nru a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README --- a/drivers/scsi/aacraid/README Fri May 21 19:07:22 2004 +++ b/drivers/scsi/aacraid/README Fri May 21 19:07:22 2004 @@ -38,15 +38,19 @@ (fixed 64bit and 64G memory model, changed confusing naming convention where fibs that go to the hardware are consistently called hw_fibs and not just fibs like the name of the driver tracking structure) +Mark Salyzyn Fixed panic issues and added some new product ids for upcoming hbas. + Original Driver ------------------------- Adaptec Unix OEM Product Group Mailing List ------------------------- -None currently. Also note this is very different to Brian's original driver +linux-aacraid-devel@dell.com (Interested parties troll here) +http://mbserver.adaptec.com/ (Currently more Community Support than Devel Support) +Also note this is very different to Brian's original driver so don't expect him to support it. -Adaptec does support this driver. Contact either tech support or deanna bonds. +Adaptec does support this driver. Contact either tech support or Mark Salyzyn. Original by Brian Boerner February 2001 Rewritten by Alan Cox, November 2001 diff -Nru a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h --- a/drivers/scsi/aacraid/aacraid.h Fri May 21 19:07:22 2004 +++ b/drivers/scsi/aacraid/aacraid.h Fri May 21 19:07:22 2004 @@ -1,18 +1,20 @@ -//#define dprintk(x) printk x -#define dprintk(x) +#if (!defined(dprintk)) +# define dprintk(x) +#endif /*------------------------------------------------------------------------------ * D E F I N E S *----------------------------------------------------------------------------*/ + #define MAXIMUM_NUM_CONTAINERS 31 #define MAXIMUM_NUM_ADAPTERS 8 -#define AAC_NUM_FIB 578 +#define AAC_NUM_FIB 578 //#define AAC_NUM_IO_FIB 512 -#define AAC_NUM_IO_FIB 100 +#define AAC_NUM_IO_FIB 100 -#define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1) -#define AAC_MAX_LUN (8) +#define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1) +#define AAC_MAX_LUN (8) #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff) @@ -241,92 +243,6 @@ }; /* - * Implement our own version of these so we have 64 bit compatability - * The adapter uses these and can only handle 32 bit addresses - */ - -struct aac_list_head { - u32 next; - u32 prev; -}; - -#define AAC_INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (u32)(ulong)(ptr); \ - (ptr)->prev = (u32)(ulong)(ptr); \ -} while (0) -/** - * aac_list_empty - tests whether a list is empty - * @head: the list to test. - */ -static __inline__ int aac_list_empty(struct aac_list_head *head) -{ - return head->next == ((u32)(ulong)head); -} - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void aac_list_add(struct aac_list_head * n, - struct aac_list_head * prev, - struct aac_list_head * next) -{ - next->prev = (u32)(ulong)n; - n->next = (u32)(ulong)next; - n->prev = (u32)(ulong)prev; - prev->next = (u32)(ulong)n; -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static __inline__ void aac_list_add_tail(struct aac_list_head *n, struct aac_list_head *head) -{ - aac_list_add(n, (struct aac_list_head*)(ulong)(head->prev), head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void __aac_list_del(struct aac_list_head * p, - struct aac_list_head * n) -{ - n->prev = (u32)(ulong)p; - p->next = (u32)(ulong)n; -} - -/** - * aac_list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is in an undefined state. - */ -static __inline__ void aac_list_del(struct aac_list_head *entry) -{ - __aac_list_del((struct aac_list_head*)(ulong)entry->prev,(struct aac_list_head*)(ulong) entry->next); - entry->next = entry->prev = 0; -} - -/** - * aac_list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define aac_list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(ulong)(&((type *)0)->member))) - -/* * Assign type values to the FSA communication data structures */ @@ -339,11 +255,11 @@ #define FsaNormal 1 #define FsaHigh 2 - /* * Define the FIB. The FIB is the where all the requested data and * command information are put to the application on the FSA adapter. */ + struct aac_fibhdr { u32 XferState; // Current transfer state for this CCB u16 Command; // Routing information for the destination @@ -359,13 +275,9 @@ u32 _ReceiverTimeStart; // Timestamp for receipt of fib u32 _ReceiverTimeDone; // Timestamp for completion of fib } _s; - struct aac_list_head _FibLinks; // Used to link Adapter Initiated Fibs on the host -// struct list_head _FibLinks; // Used to link Adapter Initiated Fibs on the host } _u; }; -#define FibLinks _u._FibLinks - #define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(struct aac_fibhdr)) @@ -558,12 +470,11 @@ spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ unsigned long SavedIrql; /* Previous IRQL when the spin lock is taken */ u32 padding; /* Padding - FIXME - can remove I believe */ - struct aac_list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ -// struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ - /* only valid for command queues which receive entries from the adapter. */ - struct list_head pendingq; /* A queue of outstanding fib's to the adapter. */ - u32 numpending; /* Number of entries on outstanding queue. */ - struct aac_dev * dev; /* Back pointer to adapter structure */ + struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ + /* only valid for command queues which receive entries from the adapter. */ + struct list_head pendingq; /* A queue of outstanding fib's to the adapter. */ + u32 numpending; /* Number of entries on outstanding queue. */ + struct aac_dev * dev; /* Back pointer to adapter structure */ }; /* @@ -744,7 +655,7 @@ struct semaphore wait_sem; // this is used to wait for the next fib to arrive. int wait; // Set to true when thread is in WaitForSingleObject unsigned long count; // total number of FIBs on FibList - struct aac_list_head hw_fib_list; // this holds hw_fibs which should be 32 bit addresses + struct list_head fib_list; // this holds fibs and their attachd hw_fibs }; struct fsa_scsi_hba { @@ -781,7 +692,11 @@ * Outstanding I/O queue. */ struct list_head queue; - + /* + * And for the internal issue/reply queues (we may be able + * to merge these two) + */ + struct list_head fiblink; void *data; struct hw_fib *hw_fib; /* Actual shared object */ dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ @@ -836,19 +751,19 @@ /* * Supported Options */ -#define AAC_OPT_SNAPSHOT cpu_to_le32(1) -#define AAC_OPT_CLUSTERS cpu_to_le32(1<<1) -#define AAC_OPT_WRITE_CACHE cpu_to_le32(1<<2) -#define AAC_OPT_64BIT_DATA cpu_to_le32(1<<3) -#define AAC_OPT_HOST_TIME_FIB cpu_to_le32(1<<4) -#define AAC_OPT_RAID50 cpu_to_le32(1<<5) -#define AAC_OPT_4GB_WINDOW cpu_to_le32(1<<6) -#define AAC_OPT_SCSI_UPGRADEABLE cpu_to_le32(1<<7) -#define AAC_OPT_SOFT_ERR_REPORT cpu_to_le32(1<<8) -#define AAC_OPT_SUPPORTED_RECONDITION cpu_to_le32(1<<9) -#define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) -#define AAC_OPT_ALARM cpu_to_le32(1<<11) -#define AAC_OPT_NONDASD cpu_to_le32(1<<12) +#define AAC_OPT_SNAPSHOT cpu_to_le32(1) +#define AAC_OPT_CLUSTERS cpu_to_le32(1<<1) +#define AAC_OPT_WRITE_CACHE cpu_to_le32(1<<2) +#define AAC_OPT_64BIT_DATA cpu_to_le32(1<<3) +#define AAC_OPT_HOST_TIME_FIB cpu_to_le32(1<<4) +#define AAC_OPT_RAID50 cpu_to_le32(1<<5) +#define AAC_OPT_4GB_WINDOW cpu_to_le32(1<<6) +#define AAC_OPT_SCSI_UPGRADEABLE cpu_to_le32(1<<7) +#define AAC_OPT_SOFT_ERR_REPORT cpu_to_le32(1<<8) +#define AAC_OPT_SUPPORTED_RECONDITION cpu_to_le32(1<<9) +#define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) +#define AAC_OPT_ALARM cpu_to_le32(1<<11) +#define AAC_OPT_NONDASD cpu_to_le32(1<<12) struct aac_dev { @@ -862,11 +777,10 @@ */ dma_addr_t hw_fib_pa; struct hw_fib *hw_fib_va; - ulong fib_base_va; + struct hw_fib *aif_base_va; /* * Fib Headers */ -// dmb struct fib fibs[AAC_NUM_FIB]; /* Doing it here takes up too much from the scsi pool*/ struct fib *fibs; struct fib *free_fib; @@ -887,7 +801,6 @@ unsigned long fsrev; /* Main driver's revision number */ struct aac_init *init; /* Holds initialization info to communicate with adapter */ -// void * init_pa; /* Holds physical address of the init struct */ dma_addr_t init_pa; /* Holds physical address of the init struct */ struct pci_dev *pdev; /* Our PCI interface */ @@ -898,7 +811,7 @@ struct Scsi_Host *scsi_host_ptr; struct fsa_scsi_hba fsa_dev; - int thread_pid; + pid_t thread_pid; int cardtype; /* diff -Nru a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c --- a/drivers/scsi/aacraid/commctrl.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/aacraid/commctrl.c Fri May 21 19:07:22 2004 @@ -148,7 +148,7 @@ * the list to 0. */ fibctx->count = 0; - AAC_INIT_LIST_HEAD(&fibctx->hw_fib_list); + INIT_LIST_HEAD(&fibctx->fib_list); fibctx->jiffies = jiffies/HZ; /* * Now add this context onto the adapter's @@ -179,7 +179,7 @@ { struct fib_ioctl f; struct aac_fib_context *fibctx, *aifcp; - struct hw_fib * hw_fib; + struct fib *fib; int status; struct list_head * entry; int found; @@ -222,25 +222,27 @@ * -EAGAIN */ return_fib: - if (!aac_list_empty(&fibctx->hw_fib_list)) { - struct aac_list_head * entry; + if (!list_empty(&fibctx->fib_list)) { + struct list_head * entry; /* * Pull the next fib from the fibs */ - entry = (struct aac_list_head*)(ulong)fibctx->hw_fib_list.next; - aac_list_del(entry); + entry = fibctx->fib_list.next; + list_del(entry); - hw_fib = aac_list_entry(entry, struct hw_fib, header.FibLinks); + fib = list_entry(entry, struct fib, fiblink); fibctx->count--; spin_unlock_irqrestore(&dev->fib_lock, flags); - if (copy_to_user(f.fib, hw_fib, sizeof(struct hw_fib))) { - kfree(hw_fib); + if (copy_to_user(f.fib, fib->hw_fib, sizeof(struct hw_fib))) { + kfree(fib->hw_fib); + kfree(fib); return -EFAULT; } /* * Free the space occupied by this copy of the fib. */ - kfree(hw_fib); + kfree(fib->hw_fib); + kfree(fib); status = 0; fibctx->jiffies = jiffies/HZ; } else { @@ -262,24 +264,25 @@ int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx) { - struct hw_fib *hw_fib; + struct fib *fib; /* * First free any FIBs that have not been consumed. */ - while (!aac_list_empty(&fibctx->hw_fib_list)) { - struct aac_list_head * entry; + while (!list_empty(&fibctx->fib_list)) { + struct list_head * entry; /* * Pull the next fib from the fibs */ - entry = (struct aac_list_head*)(ulong)(fibctx->hw_fib_list.next); - aac_list_del(entry); - hw_fib = aac_list_entry(entry, struct hw_fib, header.FibLinks); + entry = fibctx->fib_list.next; + list_del(entry); + fib = list_entry(entry, struct fib, fiblink); fibctx->count--; /* * Free the space occupied by this copy of the fib. */ - kfree(hw_fib); + kfree(fib->hw_fib); + kfree(fib); } /* * Remove the Context from the AdapterFibContext List diff -Nru a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c --- a/drivers/scsi/aacraid/comminit.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/aacraid/comminit.c Fri May 21 19:07:22 2004 @@ -81,9 +81,9 @@ * Adapter Fibs are the first thing allocated so that they * start page aligned */ - dev->fib_base_va = (ulong)base; + dev->aif_base_va = (struct hw_fib *)base; - init->AdapterFibsVirtualAddress = cpu_to_le32((u32)(ulong)phys); + init->AdapterFibsVirtualAddress = cpu_to_le32(0); init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys); init->AdapterFibsSize = cpu_to_le32(fibsize); init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib)); @@ -94,6 +94,9 @@ * mapping system, but older Firmware did, and had *troubles* dealing * with the math overloading past 32 bits, thus we must limit this * field. + * + * FIXME: this assumes the memory is mapped zero->n, which isnt + * always true on real computers. */ if ((num_physpages << (PAGE_SHIFT - 12)) <= AAC_MAX_HOSTPHYSMEMPAGES) { init->HostPhysMemPages = @@ -140,7 +143,7 @@ q->dev = dev; INIT_LIST_HEAD(&q->pendingq); init_waitqueue_head(&q->cmdready); - AAC_INIT_LIST_HEAD(&q->cmdq); + INIT_LIST_HEAD(&q->cmdq); init_waitqueue_head(&q->qfull); spin_lock_init(&q->lockdata); q->lock = &q->lockdata; diff -Nru a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c --- a/drivers/scsi/aacraid/commsup.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/aacraid/commsup.c Fri May 21 19:07:22 2004 @@ -133,13 +133,10 @@ unsigned long flags; spin_lock_irqsave(&dev->fib_lock, flags); fibptr = dev->free_fib; - while(!fibptr){ - spin_unlock_irqrestore(&dev->fib_lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - spin_lock_irqsave(&dev->fib_lock, flags); - fibptr = dev->free_fib; - } + /* Cannot sleep here or you get hangs. Instead we did the + maths at compile time. */ + if(!fibptr) + BUG(); dev->free_fib = fibptr->next; spin_unlock_irqrestore(&dev->fib_lock, flags); /* @@ -290,7 +287,7 @@ } } -/*Command thread: * +/** * aac_queue_get - get the next free QE * @dev: Adapter * @index: Returned index @@ -450,8 +447,7 @@ * Map the fib into 32bits by using the fib number */ -// hw_fib->header.SenderFibAddress = ((u32)(fibptr-dev->fibs)) << 1; - hw_fib->header.SenderFibAddress = cpu_to_le32((u32)(ulong)fibptr->hw_fib_pa); + hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr-dev->fibs)) << 1); hw_fib->header.SenderData = (u32)(fibptr - dev->fibs); /* * Set FIB state to indicate where it came from and if we want a @@ -492,7 +488,7 @@ dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command)); dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState)); dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); - dprintk((KERN_DEBUG " hw_fib pa being sent=%xl\n",(ulong)fibptr->hw_fib_pa)); + dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); /* * Fill in the Callback and CallbackContext if we are not @@ -806,8 +802,8 @@ int aac_command_thread(struct aac_dev * dev) { - struct hw_fib *hw_fib, *newfib; - struct fib fibptr; /* for error logging */ + struct hw_fib *hw_fib, *hw_newfib; + struct fib *fib, *newfib; struct aac_queue_block *queues = dev->queues; struct aac_fib_context *fibctx; unsigned long flags; @@ -828,42 +824,44 @@ * Let the DPC know it has a place to send the AIF's to. */ dev->aif_thread = 1; - memset(&fibptr, 0, sizeof(struct fib)); add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); set_current_state(TASK_INTERRUPTIBLE); while(1) { spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); - while(!aac_list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { - struct aac_list_head *entry; + while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { + struct list_head *entry; struct aac_aifcmd * aifcmd; set_current_state(TASK_RUNNING); - entry = (struct aac_list_head*)(ulong)(queues->queue[HostNormCmdQueue].cmdq.next); - dprintk(("aacraid: Command thread: removing fib from cmdq (%p)\n",entry)); - aac_list_del(entry); + entry = queues->queue[HostNormCmdQueue].cmdq.next; + list_del(entry); spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); - hw_fib = aac_list_entry(entry, struct hw_fib, header.FibLinks); + fib = list_entry(entry, struct fib, fiblink); /* * We will process the FIB here or pass it to a * worker thread that is TBD. We Really can't * do anything at this point since we don't have * anything defined for this thread to do. */ - memset(&fibptr, 0, sizeof(struct fib)); - fibptr.type = FSAFS_NTC_FIB_CONTEXT; - fibptr.size = sizeof( struct fib ); - fibptr.hw_fib = hw_fib; - fibptr.data = hw_fib->data; - fibptr.dev = dev; + hw_fib = fib->hw_fib; + memset(fib, 0, sizeof(struct fib)); + fib->type = FSAFS_NTC_FIB_CONTEXT; + fib->size = sizeof( struct fib ); + fib->hw_fib = hw_fib; + fib->data = hw_fib->data; + fib->dev = dev; /* * We only handle AifRequest fibs from the adapter. */ aifcmd = (struct aac_aifcmd *) hw_fib->data; - if (aifcmd->command == le16_to_cpu(AifCmdDriverNotify)) { - aac_handle_aif(dev, &fibptr); + if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { + /* Handle Driver Notify Events */ + aac_handle_aif(dev, fib); + *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); + fib_adapter_complete(fib, sizeof(u32)); } else { struct list_head *entry; /* The u32 here is important and intended. We are using @@ -872,6 +870,10 @@ u32 time_now, time_last; unsigned long flagv; + /* Sniff events */ + if (aifcmd->command == cpu_to_le32(AifCmdEventNotify)) + aac_handle_aif(dev, fib); + time_now = jiffies/HZ; spin_lock_irqsave(&dev->fib_lock, flagv); @@ -893,6 +895,11 @@ */ if (fibctx->count > 20) { + /* + * It's *not* jiffies folks, + * but jiffies / HZ so do not + * panic ... + */ time_last = fibctx->jiffies; /* * Has it been > 2 minutes @@ -909,17 +916,20 @@ * Warning: no sleep allowed while * holding spinlock */ - newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); - if (newfib) { + hw_newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); + newfib = kmalloc(sizeof(struct fib), GFP_ATOMIC); + if (newfib && hw_newfib) { /* * Make the copy of the FIB */ - memcpy(newfib, hw_fib, sizeof(struct hw_fib)); + memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); + memcpy(newfib, fib, sizeof(struct fib)); + newfib->hw_fib = hw_newfib; /* * Put the FIB onto the * fibctx's fibs */ - aac_list_add_tail(&newfib->header.FibLinks, &fibctx->hw_fib_list); + list_add_tail(&newfib->fiblink, &fibctx->fib_list); fibctx->count++; /* * Set the event to wake up the @@ -928,6 +938,10 @@ up(&fibctx->wait_sem); } else { printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); + if(newfib) + kfree(newfib); + if(hw_newfib) + kfree(hw_newfib); } entry = entry->next; } @@ -935,10 +949,11 @@ * Set the status of this FIB */ *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(&fibptr, sizeof(u32)); + fib_adapter_complete(fib, sizeof(u32)); spin_unlock_irqrestore(&dev->fib_lock, flagv); } spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); + kfree(fib); } /* * There are no more AIF's diff -Nru a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c --- a/drivers/scsi/aacraid/dpcsup.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/aacraid/dpcsup.c Fri May 21 19:07:22 2004 @@ -70,12 +70,12 @@ */ while(aac_consumer_get(dev, q, &entry)) { - u32 fast ; - fast = (entry->addr & cpu_to_le32(0x01)); - hwfib = (struct hw_fib *)((char *)dev->hw_fib_va + - ((entry->addr & ~0x01) - dev->hw_fib_pa)); - fib = &dev->fibs[hwfib->header.SenderData]; - + int fast; + u32 index = le32_to_cpu(entry->addr); + fast = index & 0x01; + fib = &dev->fibs[index >> 1]; + hwfib = fib->hw_fib; + aac_consumer_free(dev, q, HostNormRespQueue); /* * Remove this fib from the Outstanding I/O queue. @@ -169,29 +169,44 @@ */ while(aac_consumer_get(dev, q, &entry)) { + struct fib fibctx; struct hw_fib * hw_fib; - hw_fib = (struct hw_fib *)((char *)dev->hw_fib_va + - ((entry->addr & ~0x01) - dev->hw_fib_pa)); - - if (dev->aif_thread) { - aac_list_add_tail(&hw_fib->header.FibLinks, &q->cmdq); + u32 index; + struct fib *fib = &fibctx; + + index = le32_to_cpu(entry->addr) / sizeof(struct hw_fib); + hw_fib = &dev->aif_base_va[index]; + + /* + * Allocate a FIB at all costs. For non queued stuff + * we can just use the stack so we are happy. We need + * a fib object in order to manage the linked lists + */ + if (dev->aif_thread) + if((fib = kmalloc(sizeof(struct fib), GFP_ATOMIC)) == NULL) + fib = &fibctx; + + memset(fib, 0, sizeof(struct fib)); + INIT_LIST_HEAD(&fib->fiblink); + fib->type = FSAFS_NTC_FIB_CONTEXT; + fib->size = sizeof(struct fib); + fib->hw_fib = hw_fib; + fib->data = hw_fib->data; + fib->dev = dev; + + + if (dev->aif_thread && fib != &fibctx) { + list_add_tail(&fib->fiblink, &q->cmdq); aac_consumer_free(dev, q, HostNormCmdQueue); wake_up_interruptible(&q->cmdready); } else { - struct fib fibctx; aac_consumer_free(dev, q, HostNormCmdQueue); spin_unlock_irqrestore(q->lock, flags); - memset(&fibctx, 0, sizeof(struct fib)); - fibctx.type = FSAFS_NTC_FIB_CONTEXT; - fibctx.size = sizeof(struct fib); - fibctx.hw_fib = hw_fib; - fibctx.data = hw_fib->data; - fibctx.dev = dev; /* * Set the status of this FIB */ *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(&fibctx, sizeof(u32)); + fib_adapter_complete(fib, sizeof(u32)); spin_lock_irqsave(q->lock, flags); } } diff -Nru a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c --- a/drivers/scsi/aacraid/sa.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/aacraid/sa.c Fri May 21 19:07:22 2004 @@ -419,6 +419,11 @@ * Start any kernel threads needed */ dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); + if (dev->thread_pid < 0) { + printk(KERN_ERR "aacraid: Unable to create command thread.\n"); + return -1; + } + /* * Tell the adapter that all is configure, and it can start * accepting requests diff -Nru a/drivers/scsi/dc390.h b/drivers/scsi/dc390.h --- a/drivers/scsi/dc390.h Fri May 21 19:07:22 2004 +++ b/drivers/scsi/dc390.h Fri May 21 19:07:22 2004 @@ -19,7 +19,7 @@ #endif #define DC390_BANNER "Tekram DC390/AM53C974" -#define DC390_VERSION "2.0f 2000-12-20" +#define DC390_VERSION "2.1b 2004-04-13" /* We don't have eh_abort_handler, eh_device_reset_handler, * eh_bus_reset_handler, eh_host_reset_handler yet! diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c --- a/drivers/scsi/dpt_i2o.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/dpt_i2o.c Fri May 21 19:07:22 2004 @@ -20,17 +20,21 @@ * (at your option) any later version. * * * ***************************************************************************/ +/*************************************************************************** + * Sat Dec 20 2003 Go Taniguchi + - Support 2.6 kernel and DMA-mapping + - ioctl fix for raid tools + - use schedule_timeout in long long loop + **************************************************************************/ -//#define DEBUG 1 -//#define UARTDELAY 1 +/*#define DEBUG 1 */ +/*#define UARTDELAY 1 */ -// On the real kernel ADDR32 should always be zero for 2.4. GFP_HIGH allocates -// high pages. Keep the macro around because of the broken unmerged ia64 tree +/* On the real kernel ADDR32 should always be zero for 2.4. GFP_HIGH allocates + high pages. Keep the macro around because of the broken unmerged ia64 tree */ #define ADDR32 (0) -#error Please convert me to Documentation/DMA-mapping.txt - #include #include @@ -53,6 +57,7 @@ #include /* for printk */ #include #include +#include #include #include @@ -86,7 +91,7 @@ #elif defined(__alpha__) PROC_ALPHA , #else - (-1),(-1) + (-1),(-1), #endif FT_HBADRVR, 0, OEM_DPT, OS_LINUX, CAP_OVERLAP, DEV_ALL, ADF_ALL_SC5, 0, 0, DPT_VERSION, DPT_REVISION, DPT_SUBREVISION, @@ -227,7 +232,7 @@ /* Active IOPs now in OPERATIONAL state */ PDEBUG("HBA's in OPERATIONAL state\n"); - printk(KERN_INFO"dpti: If you have a lot of devices this could take a few minutes.\n"); + printk("dpti: If you have a lot of devices this could take a few minutes.\n"); for (pHba = hba_chain; pHba; pHba = pHba->next) { printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name); if (adpt_i2o_lct_get(pHba) < 0){ @@ -270,6 +275,7 @@ adpt_hba* pHba = (adpt_hba*) host->hostdata[0]; // adpt_i2o_quiesce_hba(pHba); adpt_i2o_delete_hba(pHba); + scsi_unregister(host); return 0; } @@ -340,6 +346,8 @@ if (rcode != 0) { sprintf(pHba->detail, "Adaptec I2O RAID"); printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode); + if (rcode != -ETIME && rcode != -EINTR) + kfree(buf); } else { memset(pHba->detail, 0, sizeof(pHba->detail)); memcpy(&(pHba->detail), "Vendor: Adaptec ", 16); @@ -348,8 +356,8 @@ memcpy(&(pHba->detail[40]), " FW: ", 4); memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4); pHba->detail[48] = '\0'; /* precautionary */ + kfree(buf); } - kfree(buf); adpt_i2o_status_get(pHba); return ; } @@ -479,7 +487,7 @@ heads = 255; sectors = 63; } - cylinders = capacity / (heads * sectors); + cylinders = sector_div(capacity, heads * sectors); // Special case if CDROM if(sdev->type == 5) { // CDROM @@ -872,6 +880,9 @@ return -EINVAL; } pci_set_master(pDev); + if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) && + pci_set_dma_mask(pDev, 0xffffffffULL)) + return -EINVAL; base_addr0_phys = pci_resource_start(pDev,0); hba_map0_area_size = pci_resource_len(pDev,0); @@ -964,6 +975,7 @@ // Initializing the spinlocks spin_lock_init(&pHba->state_lock); + spin_lock_init(&adpt_post_wait_lock); if(raptorFlag == 0){ printk(KERN_INFO"Adaptec I2O RAID controller %d at %lx size=%x irq=%d\n", @@ -1065,7 +1077,7 @@ { int i; - printk(KERN_INFO"Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); + printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); for (i = 0; i < DPTI_MAX_HBA; i++) { hbas[i] = NULL; } @@ -1153,12 +1165,22 @@ timeout *= HZ; if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){ set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(pHba->host->host_lock); + if(pHba->host) + spin_unlock_irq(pHba->host->host_lock); if (!timeout) schedule(); - else + else{ + timeout = schedule_timeout(timeout); + if (timeout == 0) { + // I/O issued, but cannot get result in + // specified time. Freeing resorces is + // dangerous. + status = -ETIME; + } schedule_timeout(timeout*HZ); - spin_lock_irq(pHba->host->host_lock); + } + if(pHba->host) + spin_lock_irq(pHba->host->host_lock); } spin_lock_irq(&adpt_wq_i2o_post.lock); __remove_wait_queue(&adpt_wq_i2o_post, &wait); @@ -1210,6 +1232,8 @@ printk(KERN_WARNING"dpti%d: Timeout waiting for message frame!\n", pHba->unit); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while(m == EMPTY_QUEUE); msg = (u32*) (pHba->msg_addr_virt + m); @@ -1284,6 +1308,8 @@ printk(KERN_WARNING"Timeout waiting for message!\n"); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while (m == EMPTY_QUEUE); status = (u8*)kmalloc(4, GFP_KERNEL|ADDR32); @@ -1315,6 +1341,8 @@ return -ETIMEDOUT; } rmb(); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } if(*status == 0x01 /*I2O_EXEC_IOP_RESET_IN_PROGRESS*/) { @@ -1331,6 +1359,8 @@ printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while (m == EMPTY_QUEUE); // Flush the offset adpt_send_nop(pHba, m); @@ -1696,15 +1726,20 @@ } do { - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); // This state stops any new commands from enterring the // controller while processing the ioctl // pHba->state |= DPTI_STATE_IOCTL; // We can't set this now - The scsi subsystem sets host_blocked and // the queue empties and stops. We need a way to restart the queue rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER); + if (rcode != 0) + printk("adpt_i2o_passthru: post wait failed %d %p\n", + rcode, reply); // pHba->state &= ~DPTI_STATE_IOCTL; - spin_unlock_irqrestore(pHba->host->host_lock, flags); + if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); } while(rcode == -ETIMEDOUT); if(rcode){ @@ -1765,10 +1800,12 @@ cleanup: - kfree (reply); + if (rcode != -ETIME && rcode != -EINTR) + kfree (reply); while(sg_index) { if(sg_list[--sg_index]) { - kfree((void*)(sg_list[sg_index])); + if (rcode != -ETIME && rcode != -EINTR) + kfree((void*)(sg_list[sg_index])); } } return rcode; @@ -1876,7 +1913,7 @@ int minor; int error = 0; adpt_hba* pHba; - ulong flags; + ulong flags = 0; minor = iminor(inode); if (minor >= DPTI_MAX_HBA){ @@ -1942,9 +1979,11 @@ break; } case I2ORESETCMD: - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); adpt_hba_reset(pHba); - spin_unlock_irqrestore(pHba->host->host_lock, flags); + if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); break; case I2ORESCANCMD: adpt_rescan(pHba); @@ -1957,7 +1996,7 @@ } -static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs) { Scsi_Cmnd* cmd; adpt_hba* pHba = dev_id; @@ -1966,12 +2005,15 @@ u32 status=0; u32 context; ulong flags = 0; + int handled = 0; - if (pHba == NULL ){ + if (pHba == NULL){ printk(KERN_WARNING"adpt_isr: NULL dev_id\n"); - return; + return IRQ_NONE; } - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); + while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) { m = readl(pHba->reply_port); if(m == EMPTY_QUEUE){ @@ -2036,7 +2078,10 @@ wmb(); rmb(); } -out: spin_unlock_irqrestore(pHba->host->host_lock, flags); + handled = 1; +out: if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); + return IRQ_RETVAL(handled); } static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* d) @@ -2111,15 +2156,19 @@ /* Now fill in the SGList and command */ if(cmd->use_sg) { struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer; + int sg_count = pci_map_sg(pHba->pDev, sg, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + + len = 0; - for(i = 0 ; i < cmd->use_sg; i++) { - *mptr++ = direction|0x10000000|sg->length; - len+=sg->length; - *mptr++ = virt_to_bus(sg->address); + for(i = 0 ; i < sg_count; i++) { + *mptr++ = direction|0x10000000|sg_dma_len(sg); + len+=sg_dma_len(sg); + *mptr++ = sg_dma_address(sg); sg++; } /* Make this an end of list */ - mptr[-2] = direction|0xD0000000|(sg-1)->length; + mptr[-2] = direction|0xD0000000|sg_dma_len(sg-1); reqlen = mptr - msg; *lenptr = len; @@ -2133,7 +2182,10 @@ reqlen = 12; } else { *mptr++ = 0xD0000000|direction|cmd->request_bufflen; - *mptr++ = virt_to_bus(cmd->request_buffer); + *mptr++ = pci_map_single(pHba->pDev, + cmd->request_buffer, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); } } @@ -2306,15 +2358,17 @@ static s32 adpt_rescan(adpt_hba* pHba) { s32 rcode; - ulong flags; + ulong flags = 0; - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); if ((rcode=adpt_i2o_lct_get(pHba)) < 0) goto out; if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0) goto out; rcode = 0; -out: spin_unlock_irqrestore(pHba->host->host_lock, flags); +out: if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); return rcode; } @@ -2596,6 +2650,8 @@ printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name); return 2; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } msg = (u32*)(pHba->msg_addr_virt + m); writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]); @@ -2629,6 +2685,8 @@ printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while(m == EMPTY_QUEUE); msg=(u32 *)(pHba->msg_addr_virt+m); @@ -2664,9 +2722,10 @@ rmb(); if(time_after(jiffies,timeout)){ printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name); - kfree((void*)status); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while (1); // If the command was successful, fill the fifo with our reply @@ -2744,6 +2803,8 @@ pHba->name); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while(m==EMPTY_QUEUE); @@ -2770,6 +2831,8 @@ return -ETIMEDOUT; } rmb(); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } // Set up our number of outbound and inbound messages @@ -3095,17 +3158,33 @@ int group, int field, void *buf, int buflen) { u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; - u8 resblk[8+buflen]; /* 8 bytes for header */ + u8 *resblk; + int size; + /* 8 bytes for header */ + resblk = kmalloc(sizeof(u8) * (8+buflen), GFP_KERNEL|ADDR32); + if (resblk == NULL) { + printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name); + return -ENOMEM; + } + if (field == -1) /* whole group */ opblk[4] = -1; size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid, - opblk, sizeof(opblk), resblk, sizeof(resblk)); + opblk, sizeof(opblk), resblk, sizeof(u8)*(8+buflen)); + if (size == -ETIME) { + printk(KERN_WARNING "%s: issue params failed; Timed out.\n", pHba->name); + return -ETIME; + } else if (size == -EINTR) { + printk(KERN_WARNING "%s: issue params failed; Interrupted.\n", pHba->name); + return -EINTR; + } memcpy(buf, resblk+8, buflen); /* cut off header */ + kfree(resblk); if (size < 0) return size; @@ -3139,6 +3218,7 @@ msg[8] = virt_to_bus(resblk); if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) { + printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk); return wait_status; /* -DetailedStatus */ } diff -Nru a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h --- a/drivers/scsi/dpti.h Fri May 21 19:07:22 2004 +++ b/drivers/scsi/dpti.h Fri May 21 19:07:22 2004 @@ -65,7 +65,7 @@ #include "dpt/dpti_i2o.h" #include "dpt/dpti_ioctl.h" -#define DPT_I2O_VERSION "2.4 Build 5" +#define DPT_I2O_VERSION "2.4 Build 5go" #define DPT_VERSION 2 #define DPT_REVISION '4' #define DPT_SUBREVISION '5' @@ -272,7 +272,7 @@ static void adpt_i2o_sys_shutdown(void); static int adpt_init(void); static int adpt_i2o_build_sys_table(void); -static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs); #ifdef REBOOT_NOTIFIER static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p); #endif diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c --- a/drivers/scsi/gdth.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/gdth.c Fri May 21 19:07:22 2004 @@ -4,9 +4,9 @@ * Intel Corporation: Storage RAID Controllers * * * * gdth.c * - * Copyright (C) 1995-03 ICP vortex GmbH, Achim Leubner * - * Copyright (C) 2002-03 Intel Corporation * - * Copyright (C) 2003 Adaptec Inc. * + * Copyright (C) 1995-04 ICP vortex GmbH, Achim Leubner * + * Copyright (C) 2002-04 Intel Corporation * + * Copyright (C) 2003-04 Adaptec Inc. * * * * * * Additions/Fixes: * @@ -27,9 +27,42 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Tested with Linux 1.2.13, ..., 2.2.20, ..., 2.4.22 * + * Linux kernel 2.2.x, 2.4.x, 2.6.x supported * * * * $Log: gdth.c,v $ + * Revision 1.73 2004/03/31 13:33:03 achim + * Special command 0xfd implemented to detect 64-bit DMA support + * + * Revision 1.72 2004/03/17 08:56:04 achim + * 64-bit DMA only enabled if FW >= x.43 + * + * Revision 1.71 2004/03/05 15:51:29 achim + * Screen service: separate message buffer, bugfixes + * + * Revision 1.70 2004/02/27 12:19:07 achim + * Bugfix: Reset bit in config (0xfe) call removed + * + * Revision 1.69 2004/02/20 09:50:24 achim + * Compatibility changes for kernels < 2.4.20 + * Bugfix screen service command size + * pci_set_dma_mask() error handling added + * + * Revision 1.68 2004/02/19 15:46:54 achim + * 64-bit DMA bugfixes + * Drive size bugfix for drives > 1TB + * + * Revision 1.67 2004/01/14 13:11:57 achim + * Tool access over /proc no longer supported + * Bugfixes IOCTLs + * + * Revision 1.66 2003/12/19 15:04:06 achim + * Bugfixes support for drives > 2TB + * + * Revision 1.65 2003/12/15 11:21:56 achim + * 64-bit DMA support added + * Support for drives > 2 TB implemented + * Kernels 2.2.x, 2.4.x, 2.6.x supported + * * Revision 1.64 2003/09/17 08:30:26 achim * EISA/ISA controller scan disabled * Command line switch probe_eisa_isa added @@ -299,10 +332,12 @@ * shared_access:N enable driver reserve/release protocol * probe_eisa_isa:Y scan for EISA/ISA controllers * probe_eisa_isa:N do not scan for EISA/ISA controllers + * force_dma32:Y use only 32 bit DMA mode + * force_dma32:N use 64 bit DMA mode, if supported * * The default values are: "gdth=disable:N,reserve_mode:1,reverse_scan:N, * max_ids:127,rescan:N,virt_ctr:N,hdr_channel:0, - * shared_access:Y,probe_eisa_isa:N". + * shared_access:Y,probe_eisa_isa:N,force_dma32:N". * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y". * * When loading the gdth driver as a module, the same options are available. @@ -313,7 +348,7 @@ * * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0 * max_ids=127 rescan=0 virt_ctr=0 hdr_channel=0 shared_access=0 - * probe_eisa_isa=0" + * probe_eisa_isa=0 force_dma32=0" * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1". */ @@ -330,9 +365,12 @@ * phase: Service/parameter/return code special command */ -/* default: activate /proc and character device IOCTL interface */ -#define GDTH_IOCTL_PROC -#define GDTH_IOCTL_CHRDEV + +/* interrupt coalescing */ +/* #define INT_COAL */ + +/* statistics */ +#define GDTH_STATISTICS #include @@ -353,35 +391,35 @@ #ifdef GDTH_RTC #include #endif -#if LINUX_VERSION_CODE >= 0x020100 #include -#else -#include -#endif #include #include #include #include -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #include -#elif LINUX_VERSION_CODE >= 0x02015F +#else #include #endif - +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include - -#include "scsi.h" -#include "hosts.h" -#if LINUX_VERSION_CODE < 0x020503 +#else +#include #include "sd.h" #endif +#include "scsi.h" +#include "hosts.h" #include "gdth.h" static void gdth_delay(int milliseconds); -static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs); +static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static irqreturn_t gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs); +#else +static void gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs); +#endif static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp); static int gdth_async_event(int hanum); static void gdth_log_event(gdth_evt_data *dvr, char *buffer); @@ -419,31 +457,19 @@ static void gdth_release_event(int hanum); static int gdth_wait(int hanum,int index,ulong32 time); static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, - ulong32 p2,ulong32 p3); + ulong64 p2,ulong64 p3); static int gdth_search_drives(int hanum); static int gdth_analyse_hdrive(int hanum, ushort hdrive); -static void *gdth_mmap(ulong paddr, ulong size); -static void gdth_munmap(void *addr); - static const char *gdth_ctr_name(int hanum); -#ifdef GDTH_IOCTL_CHRDEV static int gdth_open(struct inode *inode, struct file *filep); static int gdth_close(struct inode *inode, struct file *filep); static int gdth_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); -#endif -#if LINUX_VERSION_CODE >= 0x010300 static void gdth_flush(int hanum); -#if LINUX_VERSION_CODE >= 0x020100 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf); -#else -static int halt_called = FALSE; -void gdth_halt(void); -#endif -#endif #ifdef DEBUG_GDTH static unchar DebugState = DEBUG_GDTH; @@ -528,6 +554,9 @@ #ifdef GDTH_STATISTICS static ulong32 max_rq=0, max_index=0, max_sg=0; +#ifdef INT_COAL +static ulong32 max_int_coal=0; +#endif static ulong32 act_ints=0, act_ios=0, act_stats=0, act_rq=0; static struct timer_list gdth_timer; #endif @@ -542,80 +571,12 @@ #define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b)) -#if LINUX_VERSION_CODE < 0x010300 -static void *gdth_mmap(ulong paddr, ulong size) -{ - if (paddr >= high_memory) - return NULL; - else - return (void *)paddr; -} -static void gdth_munmap(void *addr) -{ -} -inline ulong32 virt_to_phys(volatile void *addr) -{ - return (ulong32)addr; -} -inline void *phys_to_virt(ulong32 addr) -{ - return (void *)addr; -} -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt -#define gdth_readb(addr) (*(volatile unchar *)(addr)) -#define gdth_readw(addr) (*(volatile ushort *)(addr)) -#define gdth_readl(addr) (*(volatile ulong32 *)(addr)) -#define gdth_writeb(b,addr) (*(volatile unchar *)(addr) = (b)) -#define gdth_writew(b,addr) (*(volatile ushort *)(addr) = (b)) -#define gdth_writel(b,addr) (*(volatile ulong32 *)(addr) = (b)) -#define memset_io(a,b,c) memset((void *)(a),(b),(c)) -#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) -#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) - -#define PCI_SLOT(devfn) ((devfn >> 3) & 0x1f) - -#elif LINUX_VERSION_CODE < 0x020100 -static int remapped = FALSE; -static void *gdth_mmap(ulong paddr, ulong size) -{ - if ( paddr >= high_memory) { - remapped = TRUE; - return vremap(paddr, size); - } else { - return (void *)paddr; - } -} -static void gdth_munmap(void *addr) -{ - if (remapped) - vfree(addr); - remapped = FALSE; -} -#define gdth_readb(addr) readb((ulong)(addr)) -#define gdth_readw(addr) readw((ulong)(addr)) -#define gdth_readl(addr) (ulong32)readl((ulong)(addr)) -#define gdth_writeb(b,addr) writeb((b),(ulong)(addr)) -#define gdth_writew(b,addr) writew((b),(ulong)(addr)) -#define gdth_writel(b,addr) writel((ulong32)(b),(ulong)(addr)) - -#else -static void *gdth_mmap(ulong paddr, ulong size) -{ - return ioremap(paddr, size); -} -static void gdth_munmap(void *addr) -{ - return iounmap(addr); -} #define gdth_readb(addr) readb((ulong)(addr)) #define gdth_readw(addr) readw((ulong)(addr)) #define gdth_readl(addr) (ulong32)readl((ulong)(addr)) #define gdth_writeb(b,addr) writeb((b),(ulong)(addr)) #define gdth_writew(b,addr) writew((b),(ulong)(addr)) #define gdth_writel(b,addr) writel((ulong32)(b),(ulong)(addr)) -#endif - static unchar gdth_drq_tab[4] = {5,6,7,7}; /* DRQ table */ static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */ @@ -631,9 +592,7 @@ static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */ static int elastidx; static int eoldidx; -#ifdef GDTH_IOCTL_CHRDEV static int major; -#endif #define DIN 1 /* IN data direction */ #define DOU 2 /* OUT data direction */ @@ -648,8 +607,8 @@ DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, - DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, - DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, + DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN,DOU,DUN,DUN,DUN,DUN,DUN, + DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN, DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DOU,DUN,DNO,DUN,DOU,DOU, DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, @@ -659,47 +618,32 @@ }; /* __initfunc, __initdata macros */ -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#define __devinitdata +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #define GDTH_INITFUNC(type, func) type __init func #include -#elif LINUX_VERSION_CODE >= 0x020126 +#else #define GDTH_INITFUNC(type, func) __initfunc(type func) #include -#else -#define GDTH_INITFUNC(type, func) type func -#define __initdata -#define __init #endif -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #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 +#else #define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock) #define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags) #define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags) #define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags) #define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags) -#define GDTH_LOCK_SCSI_DOCMD() spin_lock_irq(&io_request_lock) -#define GDTH_UNLOCK_SCSI_DOCMD() spin_unlock_irq(&io_request_lock) - -#else -#define GDTH_INIT_LOCK_HA(ha) do {} while (0) -#define GDTH_LOCK_HA(ha,flags) do {save_flags(flags); cli();} while (0) -#define GDTH_UNLOCK_HA(ha,flags) do {restore_flags(flags);} while (0) - -#define GDTH_LOCK_SCSI_DONE(flags) do {} while (0) -#define GDTH_UNLOCK_SCSI_DONE(flags) do {} while (0) -#define GDTH_LOCK_SCSI_DOCMD() do {} while (0) -#define GDTH_UNLOCK_SCSI_DOCMD() do {} while (0) #endif /* LILO and modprobe/insmod parameters */ @@ -730,9 +674,10 @@ static int shared_access = 1; /* enable support for EISA and ISA controllers */ static int probe_eisa_isa = 0; +/* 64 bit DMA mode, support for drives > 2 TB, if force_dma32 = 0 */ +static int force_dma32 = 0; #ifdef MODULE -#if LINUX_VERSION_CODE >= 0x02011A /* parameters for modprobe/insmod */ MODULE_PARM(irq, "i"); MODULE_PARM(disable, "i"); @@ -745,41 +690,42 @@ MODULE_PARM(virt_ctr, "i"); MODULE_PARM(shared_access, "i"); MODULE_PARM(probe_eisa_isa, "i"); +MODULE_PARM(force_dma32, "i"); MODULE_AUTHOR("Achim Leubner"); -#endif -#if LINUX_VERSION_CODE >= 0x02040B +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,11) 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, -}; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + .ioctl = gdth_ioctl, + .open = gdth_open, + .release = gdth_close, +#else + ioctl:gdth_ioctl, + open:gdth_open, + release:gdth_close, #endif +}; /* /proc support */ -#if LINUX_VERSION_CODE >= 0x010300 #include -#if LINUX_VERSION_CODE < 0x020322 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) struct proc_dir_entry proc_scsi_gdth = { PROC_SCSI_GDTH, 4, "gdth", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; #endif + #include "gdth_proc.h" #include "gdth_proc.c" -#endif -#if LINUX_VERSION_CODE >= 0x020100 /* notifier block to get a notify on system shutdown/halt/reboot */ static struct notifier_block gdth_notifier = { gdth_halt, NULL, 0 }; -#endif static void gdth_delay(int milliseconds) @@ -787,17 +733,11 @@ if (milliseconds == 0) { udelay(1); } else { -#if LINUX_VERSION_CODE >= 0x020168 mdelay(milliseconds); -#else - int i; - for (i = 0; i < milliseconds; ++i) - udelay(1000); -#endif } } -static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs) +static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs) { *cyls = size /HEADS/SECS; if (*cyls <= MAXCYLS) { @@ -842,9 +782,9 @@ ulong32 id; TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr)); - if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) { + if ((addr = ioremap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) { id = gdth_readl(addr); - gdth_munmap(addr); + iounmap(addr); if (id == GDT2_ID) /* GDT2000 */ return 1; } @@ -866,6 +806,8 @@ gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device); gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, PCI_DEVICE_ID_VORTEX_GDTNEWRX); + gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, + PCI_DEVICE_ID_VORTEX_GDTNEWRX2); gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SRC); gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, @@ -873,11 +815,11 @@ return cnt; } -#if LINUX_VERSION_CODE >= 0x20363 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Vortex only makes RAID controllers. * We do not really want to specify all 550 ids here, so wildcard match. */ -static struct pci_device_id gdthtable[] = { +static struct pci_device_id gdthtable[] __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}, @@ -890,17 +832,12 @@ ushort vendor, ushort device)) { ulong base0, base1, base2; -#if LINUX_VERSION_CODE >= 0x2015C struct pci_dev *pdev; -#else - int error; - ushort idx; -#endif TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n", *cnt, vendor, device)); -#if LINUX_VERSION_CODE >= 0x20363 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pdev = NULL; while ((pdev = pci_find_device(vendor, device, pdev)) != NULL) { @@ -938,7 +875,7 @@ pcistr[*cnt].irq, pcistr[*cnt].dpmem)); (*cnt)++; } -#elif LINUX_VERSION_CODE >= 0x2015C +#else pdev = NULL; while ((pdev = pci_find_device(vendor, device, pdev)) != NULL) { @@ -979,66 +916,6 @@ pcistr[*cnt].irq, pcistr[*cnt].dpmem)); (*cnt)++; } -#else - idx = 0; - while (!pcibios_find_device(vendor, device, idx++, - &pcistr[*cnt].bus,&pcistr[*cnt].device_fn)) { - if (*cnt >= MAXHA) - return; - /* GDT PCI ctr. found, now read resources from config space */ -#if LINUX_VERSION_CODE >= 0x010300 -#define GDTH_BASEP (int *) -#else -#define GDTH_BASEP -#endif - if ((error = pcibios_read_config_dword(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_BASE_ADDRESS_0, - GDTH_BASEP&base0)) || - (error = pcibios_read_config_dword(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_BASE_ADDRESS_1, - GDTH_BASEP&base1)) || - (error = pcibios_read_config_dword(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_BASE_ADDRESS_2, - GDTH_BASEP&base2)) || - (error = pcibios_read_config_word(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_SUBSYSTEM_ID, - &pcistr[*cnt].subdevice_id)) || - (error = pcibios_read_config_byte(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_INTERRUPT_LINE, - &pcistr[*cnt].irq))) { - printk("GDT-PCI: error %d reading configuration space", error); - continue; - } - pcistr[*cnt].vendor_id = vendor; - pcistr[*cnt].device_id = device; - if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ - device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY) - continue; - pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; - } else { /* GDT6110, GDT6120, .. */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base2 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base1 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_IO) - continue; - pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[*cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; - } - TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", - pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn), - pcistr[*cnt].irq, pcistr[*cnt].dpmem)); - (*cnt)++; - } #endif } @@ -1168,6 +1045,8 @@ ha->type = GDT_EISA; ha->stype = id; } + + ha->dma64_support = 0; return 1; } @@ -1181,7 +1060,7 @@ TRACE(("gdth_init_isa() bios adr. %x\n",bios_adr)); - ha->brd = gdth_mmap(bios_adr, sizeof(gdt2_dpram_str)); + ha->brd = ioremap(bios_adr, sizeof(gdt2_dpram_str)); if (ha->brd == NULL) { printk("GDT-ISA: Initialization error (DPMEM remap error)\n"); return 0; @@ -1191,8 +1070,8 @@ /* reset interface area */ memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u)); if (gdth_readl(&dp2_ptr->u) != 0) { - printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); + printk("GDT-ISA: Initialization error (DPMEM write error)\n"); + iounmap(ha->brd); return 0; } @@ -1227,7 +1106,7 @@ while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-ISA: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1237,7 +1116,7 @@ gdth_writeb(0xff, &dp2_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-ISA: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1259,13 +1138,15 @@ while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-ISA: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); } gdth_writeb(0, &dp2_ptr->u.ic.Status); gdth_writeb(0xff, &dp2_ptr->io.irqdel); + + ha->dma64_support = 0; return 1; } @@ -1279,9 +1160,6 @@ unchar prot_ver; ushort command; int i, found = FALSE; -#if LINUX_VERSION_CODE < 0x2015C - int rom_addr; -#endif TRACE(("gdth_init_pci()\n")); @@ -1293,13 +1171,13 @@ ha->stype = (ulong32)pcistr->device_id; ha->subdevice_id = pcistr->subdevice_id; ha->irq = pcistr->irq; -#if LINUX_VERSION_CODE >= 0x20400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ha->pdev = pcistr->pdev; #endif if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str)); + ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1312,8 +1190,8 @@ pcistr->dpmem); found = FALSE; for (i = 0xC8000; i < 0xE8000; i += 0x4000) { - gdth_munmap(ha->brd); - ha->brd = gdth_mmap(i, sizeof(ushort)); + iounmap(ha->brd); + ha->brd = ioremap(i, sizeof(ushort)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1322,15 +1200,10 @@ TRACE2(("init_pci_old() address 0x%x busy\n", i)); continue; } - gdth_munmap(ha->brd); -#if LINUX_VERSION_CODE >= 0x2015C + iounmap(ha->brd); pci_write_config_dword(pcistr->pdev, PCI_BASE_ADDRESS_0, i); -#else - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_BASE_ADDRESS_0, i); -#endif - ha->brd = gdth_mmap(i, sizeof(gdt6_dpram_str)); + ha->brd = ioremap(i, sizeof(gdt6_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1345,14 +1218,14 @@ } if (!found) { printk("GDT-PCI: No free address found!\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } } memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u)); if (gdth_readl(&dp6_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1370,7 +1243,7 @@ while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1380,7 +1253,7 @@ gdth_writeb(0xff, &dp6_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1390,7 +1263,7 @@ /* special command to controller BIOS */ gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]); gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]); - gdth_writel(0x01, &dp6_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[2]); gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]); gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); gdth_writeb(0, &dp6_ptr->io.event); @@ -1399,7 +1272,7 @@ while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1407,14 +1280,16 @@ gdth_writeb(0, &dp6_ptr->u.ic.S_Status); gdth_writeb(0xff, &dp6_ptr->io.irqdel); + ha->dma64_support = 0; + } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */ ha->plx = (gdt6c_plx_regs *)pcistr->io; TRACE2(("init_pci_new() dpmem %lx irq %d\n", pcistr->dpmem,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str)); + ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6c_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } /* check and reset interface area */ @@ -1425,8 +1300,8 @@ pcistr->dpmem); found = FALSE; for (i = 0xC8000; i < 0xE8000; i += 0x4000) { - gdth_munmap(ha->brd); - ha->brd = gdth_mmap(i, sizeof(ushort)); + iounmap(ha->brd); + ha->brd = ioremap(i, sizeof(ushort)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1435,15 +1310,10 @@ TRACE2(("init_pci_plx() address 0x%x busy\n", i)); continue; } - gdth_munmap(ha->brd); -#if LINUX_VERSION_CODE >= 0x2015C + iounmap(ha->brd); pci_write_config_dword(pcistr->pdev, PCI_BASE_ADDRESS_2, i); -#else - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_BASE_ADDRESS_2, i); -#endif - ha->brd = gdth_mmap(i, sizeof(gdt6c_dpram_str)); + ha->brd = ioremap(i, sizeof(gdt6c_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1458,14 +1328,14 @@ } if (!found) { printk("GDT-PCI: No free address found!\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } } memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u)); if (gdth_readl(&dp6c_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1486,7 +1356,7 @@ while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1495,7 +1365,7 @@ gdth_writeb(0, &dp6c_ptr->u.ic.Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1505,7 +1375,7 @@ /* special command to controller BIOS */ gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); - gdth_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[2]); gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); @@ -1516,23 +1386,25 @@ while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); } gdth_writeb(0, &dp6c_ptr->u.ic.S_Status); + ha->dma64_support = 0; + } else { /* MPR */ TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str)); + ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6m_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } /* manipulate config. space to enable DPMEM, start RP controller */ -#if LINUX_VERSION_CODE >= 0x20363 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command); command |= 6; pci_write_config_word(pcistr->pdev, PCI_COMMAND, command); @@ -1543,7 +1415,7 @@ gdth_delay(1); pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, pci_resource_start(pcistr->pdev, 8)); -#elif LINUX_VERSION_CODE >= 0x2015C +#else pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command); command |= 6; pci_write_config_word(pcistr->pdev, PCI_COMMAND, command); @@ -1554,22 +1426,6 @@ gdth_delay(1); pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, pcistr->pdev->rom_address); -#else - pcibios_read_config_word(pcistr->bus, pcistr->device_fn, - PCI_COMMAND, &command); - command |= 6; - pcibios_write_config_word(pcistr->bus, pcistr->device_fn, - PCI_COMMAND, command); - pcibios_read_config_dword(pcistr->bus, pcistr->device_fn, - PCI_ROM_ADDRESS, &rom_addr); - if (rom_addr == 1UL) - rom_addr = 0UL; - i = 0xFEFF0001UL; - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_ROM_ADDRESS, i); - gdth_delay(1); - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_ROM_ADDRESS, rom_addr); #endif /* Ensure that it is safe to access the non HW portions of DPMEM. @@ -1585,8 +1441,8 @@ pcistr->dpmem); found = FALSE; for (i = 0xC8000; i < 0xE8000; i += 0x4000) { - gdth_munmap(ha->brd); - ha->brd = gdth_mmap(i, sizeof(ushort)); + iounmap(ha->brd); + ha->brd = ioremap(i, sizeof(ushort)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1595,15 +1451,10 @@ TRACE2(("init_pci_mpr() address 0x%x busy\n", i)); continue; } - gdth_munmap(ha->brd); -#if LINUX_VERSION_CODE >= 0x2015C + iounmap(ha->brd); pci_write_config_dword(pcistr->pdev, PCI_BASE_ADDRESS_0, i); -#else - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_BASE_ADDRESS_0, i); -#endif - ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str)); + ha->brd = ioremap(i, sizeof(gdt6m_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1618,7 +1469,7 @@ } if (!found) { printk("GDT-PCI: No free address found!\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } } @@ -1639,7 +1490,7 @@ while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1648,7 +1499,7 @@ gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1658,7 +1509,7 @@ /* special command to controller BIOS */ gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[0]); gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[1]); - gdth_writel(0x01, &dp6m_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[2]); gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[3]); gdth_writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx); gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); @@ -1667,12 +1518,32 @@ while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); } gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); + + /* read FW version to detect 64-bit DMA support */ + gdth_writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx); + gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); + retries = INIT_RETRIES; + gdth_delay(20); + while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) { + if (--retries == 0) { + printk("GDT-PCI: Initialization error (DEINIT failed)\n"); + iounmap(ha->brd); + return 0; + } + gdth_delay(1); + } + prot_ver = (unchar)(gdth_readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16); + gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); + if (prot_ver < 0x2b) /* FW < x.43: no 64-bit DMA support */ + ha->dma64_support = 0; + else + ha->dma64_support = 1; } return 1; @@ -1950,7 +1821,7 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, - ulong32 p2,ulong32 p3) + ulong64 p2,ulong64 p3) { register gdth_ha_str *ha; register gdth_cmd_str *cmd_ptr; @@ -1976,23 +1847,35 @@ if (service == CACHESERVICE) { if (opcode == GDT_IOCTL) { cmd_ptr->u.ioctl.subfunc = p1; - cmd_ptr->u.ioctl.channel = p2; + cmd_ptr->u.ioctl.channel = (ulong32)p2; cmd_ptr->u.ioctl.param_size = (ushort)p3; cmd_ptr->u.ioctl.p_param = ha->scratch_phys; } else { - cmd_ptr->u.cache.DeviceNo = (ushort)p1; - cmd_ptr->u.cache.BlockNo = p2; + if (ha->cache_feat & GDT_64BIT) { + cmd_ptr->u.cache64.DeviceNo = (ushort)p1; + cmd_ptr->u.cache64.BlockNo = p2; + } else { + cmd_ptr->u.cache.DeviceNo = (ushort)p1; + cmd_ptr->u.cache.BlockNo = (ulong32)p2; + } } } else if (service == SCSIRAWSERVICE) { - cmd_ptr->u.raw.direction = p1; - cmd_ptr->u.raw.bus = (unchar)p2; - cmd_ptr->u.raw.target = (unchar)p3; - cmd_ptr->u.raw.lun = (unchar)(p3 >> 8); + if (ha->raw_feat & GDT_64BIT) { + cmd_ptr->u.raw64.direction = p1; + cmd_ptr->u.raw64.bus = (unchar)p2; + cmd_ptr->u.raw64.target = (unchar)p3; + cmd_ptr->u.raw64.lun = (unchar)(p3 >> 8); + } else { + cmd_ptr->u.raw.direction = p1; + cmd_ptr->u.raw.bus = (unchar)p2; + cmd_ptr->u.raw.target = (unchar)p3; + cmd_ptr->u.raw.lun = (unchar)(p3 >> 8); + } } else if (service == SCREENSERVICE) { if (opcode == GDT_REALTIME) { *(ulong32 *)&cmd_ptr->u.screen.su.data[0] = p1; - *(ulong32 *)&cmd_ptr->u.screen.su.data[4] = p2; - *(ulong32 *)&cmd_ptr->u.screen.su.data[8] = p3; + *(ulong32 *)&cmd_ptr->u.screen.su.data[4] = (ulong32)p2; + *(ulong32 *)&cmd_ptr->u.screen.su.data[8] = (ulong32)p3; } } ha->cmd_len = sizeof(gdth_cmd_str); @@ -2020,6 +1903,7 @@ { register gdth_ha_str *ha; ushort cdev_cnt, i; + int ok; ulong32 bus_no, drv_cnt, drv_no, j; gdth_getch_str *chn; gdth_drlist_str *drl; @@ -2028,6 +1912,9 @@ gdth_arcdl_str *alst; gdth_alist_str *alst2; gdth_oem_str_ioctl *oemstr; +#ifdef INT_COAL + gdth_perf_modes *pmod; +#endif #ifdef GDTH_RTC unchar rtc[12]; @@ -2036,11 +1923,20 @@ TRACE(("gdth_search_drives() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); + ok = 0; /* initialize controller services, at first: screen service */ - if (!gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0)) { - printk("GDT: Initialization error screen service (code %d)\n", - ha->status); + ha->screen_feat = 0; + if (!force_dma32) { + ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_X_INIT_SCR,0,0,0); + if (ok) + ha->screen_feat = GDT_64BIT; + } + if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) + ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0); + if (!ok) { + printk("GDT-HA %d: Initialization error screen service (code %d)\n", + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n")); @@ -2060,7 +1956,7 @@ for (j = 0; j < 12; ++j) rtc[j] = CMOS_READ(j); } while (rtc[0] != CMOS_READ(0)); - spin_unlock_irqrestore(&rtc_lock, flags); + spin_lock_irqrestore(&rtc_lock, flags); TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0], *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8])); /* 3. send to controller firmware */ @@ -2072,15 +1968,52 @@ gdth_internal_cmd(hanum,CACHESERVICE,GDT_UNFREEZE_IO,0,0,0); /* initialize cache service */ - if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) { - printk("GDT: Initialization error cache service (code %d)\n", - ha->status); + ha->cache_feat = 0; + if (!force_dma32) { + ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INIT_HOST,LINUX_OS,0,0); + if (ok) + ha->cache_feat = GDT_64BIT; + } + if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) + ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0); + if (!ok) { + printk("GDT-HA %d: Initialization error cache service (code %d)\n", + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n")); cdev_cnt = (ushort)ha->info; ha->fw_vers = ha->service; +#ifdef INT_COAL + if (ha->type == GDT_PCIMPR) { + /* set perf. modes */ + pmod = (gdth_perf_modes *)ha->pscratch; + pmod->version = 1; + pmod->st_mode = 1; /* enable one status buffer */ + *((ulong64 *)&pmod->st_buff_addr1) = ha->coal_stat_phys; + pmod->st_buff_indx1 = COALINDEX; + pmod->st_buff_addr2 = 0; + pmod->st_buff_u_addr2 = 0; + pmod->st_buff_indx2 = 0; + pmod->st_buff_size = sizeof(gdth_coal_status) * MAXOFFSETS; + pmod->cmd_mode = 0; // disable all cmd buffers + pmod->cmd_buff_addr1 = 0; + pmod->cmd_buff_u_addr1 = 0; + pmod->cmd_buff_indx1 = 0; + pmod->cmd_buff_addr2 = 0; + pmod->cmd_buff_u_addr2 = 0; + pmod->cmd_buff_indx2 = 0; + pmod->cmd_buff_size = 0; + pmod->reserved1 = 0; + pmod->reserved2 = 0; + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,SET_PERF_MODES, + INVALID_CHANNEL,sizeof(gdth_perf_modes))) { + printk("GDT-HA %d: Interrupt coalescing activated\n", hanum); + } + } +#endif + /* detect number of buses - try new IOCTL */ iocr = (gdth_raw_iochan_str *)ha->pscratch; iocr->hdr.version = 0xffffffff; @@ -2108,8 +2041,8 @@ IO_CHANNEL | INVALID_CHANNEL, sizeof(gdth_getch_str))) { if (bus_no == 0) { - printk("GDT: Error detecting channel count (0x%x)\n", - ha->status); + printk("GDT-HA %d: Error detecting channel count (0x%x)\n", + hanum, ha->status); return 0; } break; @@ -2126,8 +2059,8 @@ /* read cache configuration */ if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO, INVALID_CHANNEL,sizeof(gdth_cinfo_str))) { - printk("GDT: Initialization error cache service (code %d)\n", - ha->status); + printk("GDT-HA %d: Initialization error cache service (code %d)\n", + hanum, ha->status); return 0; } ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar; @@ -2246,9 +2179,17 @@ } /* initialize raw service */ - if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) { - printk("GDT: Initialization error raw service (code %d)\n", - ha->status); + ha->raw_feat = 0; + if (!force_dma32) { + ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_X_INIT_RAW,0,0,0); + if (ok) + ha->raw_feat = GDT_64BIT; + } + if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) + ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0); + if (!ok) { + printk("GDT-HA %d: Initialization error raw service (code %d)\n", + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n")); @@ -2260,7 +2201,7 @@ if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) { TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n", ha->info)); - ha->raw_feat = (ushort)ha->info; + ha->raw_feat |= (ushort)ha->info; } } @@ -2271,7 +2212,7 @@ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) { TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n", ha->info)); - ha->cache_feat = (ushort)ha->info; + ha->cache_feat |= (ushort)ha->info; } } @@ -2291,8 +2232,8 @@ if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0, reserve_list[i+1], reserve_list[i+2] | (reserve_list[i+3] << 8))) { - printk("GDT: Error raw service (RESERVE, code %d)\n", - ha->status); + printk("GDT-HA %d: Error raw service (RESERVE, code %d)\n", + hanum, ha->status); } } } @@ -2305,17 +2246,32 @@ CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL, sizeof(gdth_oem_str_ioctl))) { TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n")); - printk("GDT CTR%d Vendor: %s\n",hanum,oemstr->text.oem_company_name); + printk("GDT-HA %d: Vendor: %s Name: %s\n", + hanum,oemstr->text.oem_company_name,ha->binfo.type_string); /* Save the Host Drive inquiry data */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) strlcpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id, - sizeof(ha->oem_name)); + sizeof(ha->oem_name)); +#else + strncpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,7); + ha->oem_name[7] = '\0'; +#endif } else { /* Old method, based on PCI ID */ TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n")); + printk("GDT-HA %d: Name: %s\n", + hanum,ha->binfo.type_string); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) if (ha->oem_id == OEM_ID_INTEL) strlcpy(ha->oem_name,"Intel ", sizeof(ha->oem_name)); else strlcpy(ha->oem_name,"ICP ", sizeof(ha->oem_name)); +#else + if (ha->oem_id == OEM_ID_INTEL) + strcpy(ha->oem_name,"Intel "); + else + strcpy(ha->oem_name,"ICP "); +#endif } /* scanning for host drives */ @@ -2329,7 +2285,8 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive) { register gdth_ha_str *ha; - int drv_cyls, drv_hds, drv_secs; + ulong32 drv_cyls; + int drv_hds, drv_secs; TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n",hanum,hdrive)); if (hdrive >= MAX_HDRIVES) @@ -2340,7 +2297,7 @@ return 0; ha->hdr[hdrive].present = TRUE; ha->hdr[hdrive].size = ha->info; - + /* evaluate mapping (sectors per head, heads per cylinder) */ ha->hdr[hdrive].size &= ~SECS32; if (ha->info2 == 0) { @@ -2348,15 +2305,22 @@ } else { drv_hds = ha->info2 & 0xff; drv_secs = (ha->info2 >> 8) & 0xff; - drv_cyls = ha->hdr[hdrive].size /drv_hds/drv_secs; + drv_cyls = (ulong32)ha->hdr[hdrive].size / drv_hds / drv_secs; } ha->hdr[hdrive].heads = (unchar)drv_hds; ha->hdr[hdrive].secs = (unchar)drv_secs; /* round size */ ha->hdr[hdrive].size = drv_cyls * drv_hds * drv_secs; + + if (ha->cache_feat & GDT_64BIT) { + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INFO,hdrive,0,0) + && ha->info2 != 0) { + ha->hdr[hdrive].size = ((ulong64)ha->info2 << 32) | ha->info; + } + } TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n", hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs)); - + /* get informations about device */ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,hdrive,0,0)) { TRACE2(("gdth_search_dr() cache drive %d devtype %d\n", @@ -2398,14 +2362,13 @@ GDTH_LOCK_HA(ha, flags); scp->SCp.this_residual = (int)priority; -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; #else b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel; t = scp->target; #endif -#if LINUX_VERSION_CODE >= 0x010300 if (priority >= DEFAULT_PRI) { if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) { @@ -2413,7 +2376,6 @@ scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); } } -#endif if (ha->req_first==NULL) { ha->req_first = scp; /* queue was empty */ @@ -2465,7 +2427,7 @@ 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 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel; t = nscp->device->id; l = nscp->device->lun; @@ -2493,10 +2455,7 @@ firsttime = FALSE; } -#if LINUX_VERSION_CODE >= 0x010300 - if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) -#endif - { + if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) { if (nscp->SCp.phase == -1) { nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */ if (nscp->cmnd[0] == TEST_UNIT_READY) { @@ -2565,16 +2524,11 @@ GDTH_LOCK_HA(ha,flags); } } - } else - -#if LINUX_VERSION_CODE >= 0x010300 - if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) { + } else if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) { if (!(cmd_index=gdth_special_cmd(hanum,nscp))) this_cmd = FALSE; next_cmd = FALSE; - } else -#endif - if (b != ha->virt_bus) { + } else if (b != ha->virt_bus) { if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW || !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) this_cmd = FALSE; @@ -2603,6 +2557,9 @@ case VERIFY: case START_STOP: case MODE_SENSE: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + case SERVICE_ACTION_IN: +#endif TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); @@ -2674,6 +2631,10 @@ case WRITE_6: case READ_10: case WRITE_10: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + case READ_16: + case WRITE_16: +#endif if (ha->hdr[t].media_changed) { /* return UNIT_ATTENTION */ TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n", @@ -2701,8 +2662,8 @@ TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp->cmnd[0], nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); - printk("GDT: Unknown SCSI command 0x%x to cache service !\n", - nscp->cmnd[0]); + printk("GDT-HA %d: Unknown SCSI command 0x%x to cache service !\n", + hanum, nscp->cmnd[0]); nscp->result = DID_ABORT << 16; if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; @@ -2737,11 +2698,11 @@ if (gdth_polling && ha->cmd_cnt > 0) { if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT)) - printk("GDT: Controller %d: Command %d timed out !\n", + printk("GDT-HA %d: Command %d timed out !\n", hanum,cmd_index); } } - + static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, char *buffer,ushort count) { @@ -2757,7 +2718,7 @@ if (scp->use_sg) { sl = (struct scatterlist *)scp->request_buffer; -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE); for (i=0,cpsum=0; i cpcount) cpnow = cpcount - cpsum; cpsum += cpnow; - address = (char *)phys_to_virt(sg_dma_address(sl)); + if (!sl->page) { + printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n", + hanum); + return; + } + address = (char *)(page_address(sl->page) + sl->offset); memcpy(address,buffer,cpnow); if (cpsum == cpcount) break; @@ -2806,7 +2772,7 @@ gdth_modep_data mpd; ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) t = scp->device->id; #else t = scp->target; @@ -2814,6 +2780,9 @@ TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n", scp->cmnd[0],t)); + scp->result = DID_OK << 16; + scp->sense_buffer[0] = 0; + switch (scp->cmnd[0]) { case TEST_UNIT_READY: case VERIFY: @@ -2864,19 +2833,35 @@ case READ_CAPACITY: TRACE2(("Read capacity hdrive %d\n",t)); - rdc.last_block_no = ntohl(ha->hdr[t].size-1); - rdc.block_length = ntohl(SECTOR_SIZE); + if (ha->hdr[t].size > (ulong64)0xffffffff) + rdc.last_block_no = 0xffffffff; + else + rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1); + rdc.block_length = cpu_to_be32(SECTOR_SIZE); gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data)); break; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + case SERVICE_ACTION_IN: + if ((scp->cmnd[1] & 0x1f) == SAI_READ_CAPACITY_16 && + (ha->cache_feat & GDT_64BIT)) { + gdth_rdcap16_data rdc16; + + TRACE2(("Read capacity (16) hdrive %d\n",t)); + rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1); + rdc16.block_length = cpu_to_be32(SECTOR_SIZE); + gdth_copy_internal_data(hanum,scp,(char*)&rdc16,sizeof(gdth_rdcap16_data)); + } else { + scp->result = DID_ABORT << 16; + } + break; +#endif + default: TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0])); break; } - scp->result = DID_OK << 16; - scp->sense_buffer[0] = 0; - if (!scp->SCp.have_data_in) scp->SCp.have_data_in++; else @@ -2890,9 +2875,14 @@ register gdth_ha_str *ha; register gdth_cmd_str *cmdp; struct scatterlist *sl; - ushort i, cnt; - ulong32 no, phys_addr; - int cmd_index, read_write, sgcnt; + ulong32 cnt, blockcnt; + ulong64 no, blockno; + dma_addr_t phys_addr; + int i, cmd_index, read_write, sgcnt, mode64; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + struct page *page; + ulong offset; +#endif ha = HADATA(gdth_ctr_tab[hanum]); cmdp = ha->pccb; @@ -2902,6 +2892,11 @@ if (ha->type==GDT_EISA && ha->cmd_cnt>0) return 0; + mode64 = (ha->cache_feat & GDT_64BIT) ? TRUE : FALSE; + /* test for READ_16, WRITE_16 if !mode64 ? --- + not required, should not occur due to error return on + READ_CAPACITY_16 */ + cmdp->Service = CACHESERVICE; cmdp->RequestBuffer = scp; /* search free command index */ @@ -2929,7 +2924,11 @@ else cmdp->OpCode = GDT_FLUSH; } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 || - scp->cmnd[0] == WRITE_12) { + scp->cmnd[0] == WRITE_12 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + || scp->cmnd[0] == WRITE_16 +#endif + ) { read_write = 1; if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) && (ha->cache_feat & GDT_WR_THROUGH))) @@ -2940,86 +2939,157 @@ read_write = 2; cmdp->OpCode = GDT_READ; } - - cmdp->BoardNode = LOCALBOARD; - cmdp->u.cache.DeviceNo = hdrive; - cmdp->u.cache.BlockNo = 1; - cmdp->u.cache.sg_canz = 0; + + cmdp->BoardNode = LOCALBOARD; + if (mode64) { + cmdp->u.cache64.DeviceNo = hdrive; + cmdp->u.cache64.BlockNo = 1; + cmdp->u.cache64.sg_canz = 0; + } else { + cmdp->u.cache.DeviceNo = hdrive; + cmdp->u.cache.BlockNo = 1; + cmdp->u.cache.sg_canz = 0; + } if (read_write) { - if (scp->cmd_len != 6) { + if (scp->cmd_len == 16) { + memcpy(&no, &scp->cmnd[2], sizeof(ulong64)); + blockno = be64_to_cpu(no); + memcpy(&cnt, &scp->cmnd[10], sizeof(ulong32)); + blockcnt = be32_to_cpu(cnt); + } else if (scp->cmd_len == 10) { memcpy(&no, &scp->cmnd[2], sizeof(ulong32)); - cmdp->u.cache.BlockNo = ntohl(no); + blockno = be32_to_cpu(no); memcpy(&cnt, &scp->cmnd[7], sizeof(ushort)); - cmdp->u.cache.BlockCnt = (ulong32)ntohs(cnt); + blockcnt = be16_to_cpu(cnt); } else { memcpy(&no, &scp->cmnd[0], sizeof(ulong32)); - cmdp->u.cache.BlockNo = ntohl(no) & 0x001fffffUL; - cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4]; + blockno = be32_to_cpu(no) & 0x001fffffUL; + blockcnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4]; + } + if (mode64) { + cmdp->u.cache64.BlockNo = blockno; + cmdp->u.cache64.BlockCnt = blockcnt; + } else { + cmdp->u.cache.BlockNo = (ulong32)blockno; + cmdp->u.cache.BlockCnt = blockcnt; } if (scp->use_sg) { - cmdp->u.cache.DestAddr= 0xffffffff; sl = (struct scatterlist *)scp->request_buffer; sgcnt = scp->use_sg; -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) scp->SCp.Status = GDTH_MAP_SG; scp->SCp.Message = (read_write == 1 ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); - for (i=0; iu.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); - cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl); + if (mode64) { + cmdp->u.cache64.DestAddr= (ulong64)-1; + cmdp->u.cache64.sg_canz = sgcnt; + for (i=0; iu.cache64.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + if (cmdp->u.cache64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) + ha->dma64_cnt++; + else + ha->dma32_cnt++; +#endif + cmdp->u.cache64.sg_lst[i].sg_len = sg_dma_len(sl); + } + } else { + cmdp->u.cache.DestAddr= 0xffffffff; + cmdp->u.cache.sg_canz = sgcnt; + for (i=0; iu.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + ha->dma32_cnt++; +#endif + cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl); + } } #else - for (i=0; iu.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address); - cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length; + if (mode64) { + cmdp->u.cache64.DestAddr= (ulong64)-1; + cmdp->u.cache64.sg_canz = sgcnt; + for (i=0; iu.cache64.sg_lst[i].sg_ptr = virt_to_bus(sl->address); + cmdp->u.cache64.sg_lst[i].sg_len = (ulong32)sl->length; + } + } else { + cmdp->u.cache.DestAddr= 0xffffffff; + cmdp->u.cache.sg_canz = sgcnt; + for (i=0; iu.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address); + cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length; + } } #endif - cmdp->u.cache.sg_canz = (ulong32)i; #ifdef GDTH_STATISTICS - if (max_sg < (ulong32)i) { - max_sg = (ulong32)i; - TRACE3(("GDT: max_sg = %d\n",i)); + if (max_sg < (ulong32)sgcnt) { + max_sg = (ulong32)sgcnt; + TRACE3(("GDT: max_sg = %d\n",max_sg)); } #endif - if (iu.cache.sg_lst[i].sg_len = 0; + } else { -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) scp->SCp.Status = GDTH_MAP_SINGLE; scp->SCp.Message = (read_write == 1 ? - PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - phys_addr = pci_map_single(ha->pdev,scp->request_buffer, - scp->request_bufflen,scp->SCp.Message); + PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); + page = virt_to_page(scp->request_buffer); + offset = (ulong)scp->request_buffer & ~PAGE_MASK; + phys_addr = pci_map_page(ha->pdev,page,offset, + scp->request_bufflen,scp->SCp.Message); scp->SCp.dma_handle = phys_addr; #else phys_addr = virt_to_bus(scp->request_buffer); #endif - if (ha->cache_feat & SCATTER_GATHER) { - cmdp->u.cache.DestAddr = 0xffffffff; - cmdp->u.cache.sg_canz = 1; - cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr; - cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen; - cmdp->u.cache.sg_lst[1].sg_len = 0; + if (mode64) { + if (ha->cache_feat & SCATTER_GATHER) { + cmdp->u.cache64.DestAddr = (ulong64)-1; + cmdp->u.cache64.sg_canz = 1; + cmdp->u.cache64.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.cache64.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.cache64.sg_lst[1].sg_len = 0; + } else { + cmdp->u.cache64.DestAddr = phys_addr; + cmdp->u.cache64.sg_canz= 0; + } } else { - cmdp->u.cache.DestAddr = phys_addr; - cmdp->u.cache.sg_canz= 0; + if (ha->cache_feat & SCATTER_GATHER) { + cmdp->u.cache.DestAddr = 0xffffffff; + cmdp->u.cache.sg_canz = 1; + cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.cache.sg_lst[1].sg_len = 0; + } else { + cmdp->u.cache.DestAddr = phys_addr; + cmdp->u.cache.sg_canz= 0; + } } } } - TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", - cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz, - cmdp->u.cache.sg_lst[0].sg_ptr, - cmdp->u.cache.sg_lst[0].sg_len)); - TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n", - cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt)); - /* evaluate command size, check space */ - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + - (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str); + if (mode64) { + TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.cache64.DestAddr,cmdp->u.cache64.sg_canz, + cmdp->u.cache64.sg_lst[0].sg_ptr, + cmdp->u.cache64.sg_lst[0].sg_len)); + TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n", + cmdp->OpCode,cmdp->u.cache64.BlockNo,cmdp->u.cache64.BlockCnt)); + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) + + (ushort)cmdp->u.cache64.sg_canz * sizeof(gdth_sg64_str); + } else { + TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz, + cmdp->u.cache.sg_lst[0].sg_ptr, + cmdp->u.cache.sg_lst[0].sg_len)); + TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n", + cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt)); + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + + (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str); + } if (ha->cmd_len & 3) ha->cmd_len += (4 - (ha->cmd_len & 3)); @@ -3043,12 +3113,16 @@ register gdth_cmd_str *cmdp; struct scatterlist *sl; ushort i; - ulong32 phys_addr, sense_paddr; - int cmd_index, sgcnt; + dma_addr_t phys_addr, sense_paddr; + int cmd_index, sgcnt, mode64; unchar t,l; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + struct page *page; + ulong offset; +#endif ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) t = scp->device->id; l = scp->device->lun; #else @@ -3062,6 +3136,8 @@ if (ha->type==GDT_EISA && ha->cmd_cnt>0) return 0; + mode64 = (ha->raw_feat & GDT_64BIT) ? TRUE : FALSE; + cmdp->Service = SCSIRAWSERVICE; cmdp->RequestBuffer = scp; /* search free command index */ @@ -3077,95 +3153,176 @@ if (scp->SCp.sent_command != -1) { cmdp->OpCode = scp->SCp.sent_command; /* special raw cmd. */ cmdp->BoardNode = LOCALBOARD; - cmdp->u.raw.direction = (scp->SCp.phase >> 8); - TRACE2(("special raw cmd 0x%x param 0x%x\n", - cmdp->OpCode, cmdp->u.raw.direction)); + if (mode64) { + cmdp->u.raw64.direction = (scp->SCp.phase >> 8); + TRACE2(("special raw cmd 0x%x param 0x%x\n", + cmdp->OpCode, cmdp->u.raw64.direction)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst); + } else { + cmdp->u.raw.direction = (scp->SCp.phase >> 8); + TRACE2(("special raw cmd 0x%x param 0x%x\n", + cmdp->OpCode, cmdp->u.raw.direction)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst); + } - /* evaluate command size */ - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst); } else { -#if LINUX_VERSION_CODE >= 0x020400 - sense_paddr = pci_map_single(ha->pdev,scp->sense_buffer, - 16,PCI_DMA_FROMDEVICE); - scp->SCp.buffer = (struct scatterlist *)sense_paddr; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + page = virt_to_page(scp->sense_buffer); + offset = (ulong)scp->sense_buffer & ~PAGE_MASK; + sense_paddr = pci_map_page(ha->pdev,page,offset, + 16,PCI_DMA_FROMDEVICE); + scp->SCp.buffer = (struct scatterlist *)((ulong32)sense_paddr); + /* high part, if 64bit */ + scp->host_scribble = (char *)(ulong32)((ulong64)sense_paddr >> 32); #else sense_paddr = virt_to_bus(scp->sense_buffer); #endif cmdp->OpCode = GDT_WRITE; /* always */ cmdp->BoardNode = LOCALBOARD; - cmdp->u.raw.reserved = 0; - cmdp->u.raw.mdisc_time = 0; - cmdp->u.raw.mcon_time = 0; - cmdp->u.raw.clen = scp->cmd_len; - cmdp->u.raw.target = t; - cmdp->u.raw.lun = l; - cmdp->u.raw.bus = b; - cmdp->u.raw.priority = 0; - cmdp->u.raw.link_p = 0; - cmdp->u.raw.sdlen = scp->request_bufflen; - cmdp->u.raw.sense_len = 16; - cmdp->u.raw.sense_data = sense_paddr; - cmdp->u.raw.direction = - gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; - memcpy(cmdp->u.raw.cmd,scp->cmnd,12); + if (mode64) { + cmdp->u.raw64.reserved = 0; + cmdp->u.raw64.mdisc_time = 0; + cmdp->u.raw64.mcon_time = 0; + cmdp->u.raw64.clen = scp->cmd_len; + cmdp->u.raw64.target = t; + cmdp->u.raw64.lun = l; + cmdp->u.raw64.bus = b; + cmdp->u.raw64.priority = 0; + cmdp->u.raw64.sdlen = scp->request_bufflen; + cmdp->u.raw64.sense_len = 16; + cmdp->u.raw64.sense_data = sense_paddr; + cmdp->u.raw64.direction = + gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; + memcpy(cmdp->u.raw64.cmd,scp->cmnd,16); + } else { + cmdp->u.raw.reserved = 0; + cmdp->u.raw.mdisc_time = 0; + cmdp->u.raw.mcon_time = 0; + cmdp->u.raw.clen = scp->cmd_len; + cmdp->u.raw.target = t; + cmdp->u.raw.lun = l; + cmdp->u.raw.bus = b; + cmdp->u.raw.priority = 0; + cmdp->u.raw.link_p = 0; + cmdp->u.raw.sdlen = scp->request_bufflen; + cmdp->u.raw.sense_len = 16; + cmdp->u.raw.sense_data = sense_paddr; + cmdp->u.raw.direction = + gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; + memcpy(cmdp->u.raw.cmd,scp->cmnd,12); + } if (scp->use_sg) { - cmdp->u.raw.sdata = 0xffffffff; sl = (struct scatterlist *)scp->request_buffer; sgcnt = scp->use_sg; -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) scp->SCp.Status = GDTH_MAP_SG; scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); - for (i=0; iu.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); - cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl); + if (mode64) { + cmdp->u.raw64.sdata = (ulong64)-1; + cmdp->u.raw64.sg_ranz = sgcnt; + for (i=0; iu.raw64.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + if (cmdp->u.raw64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) + ha->dma64_cnt++; + else + ha->dma32_cnt++; +#endif + cmdp->u.raw64.sg_lst[i].sg_len = sg_dma_len(sl); + } + } else { + cmdp->u.raw.sdata = 0xffffffff; + cmdp->u.raw.sg_ranz = sgcnt; + for (i=0; iu.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + ha->dma32_cnt++; +#endif + cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl); + } } #else - for (i=0; iu.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address); - cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length; + if (mode64) { + cmdp->u.raw64.sdata = (ulong64)-1; + cmdp->u.raw64.sg_ranz = sgcnt; + for (i=0; iu.raw64.sg_lst[i].sg_ptr = virt_to_bus(sl->address); + cmdp->u.raw64.sg_lst[i].sg_len = (ulong32)sl->length; + } + } else { + cmdp->u.raw.sdata = 0xffffffff; + cmdp->u.raw.sg_ranz = sgcnt; + for (i=0; iu.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address); + cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length; + } } #endif - cmdp->u.raw.sg_ranz = (ulong32)i; #ifdef GDTH_STATISTICS - if (max_sg < (ulong32)i) { - max_sg = (ulong32)i; - TRACE3(("GDT: max_sg = %d\n",i)); + if (max_sg < sgcnt) { + max_sg = sgcnt; + TRACE3(("GDT: max_sg = %d\n",sgcnt)); } #endif - if (iu.raw.sg_lst[i].sg_len = 0; + } else { -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) scp->SCp.Status = GDTH_MAP_SINGLE; scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; - phys_addr = pci_map_single(ha->pdev,scp->request_buffer, - scp->request_bufflen,scp->SCp.Message); + page = virt_to_page(scp->request_buffer); + offset = (ulong)scp->request_buffer & ~PAGE_MASK; + phys_addr = pci_map_page(ha->pdev,page,offset, + scp->request_bufflen,scp->SCp.Message); scp->SCp.dma_handle = phys_addr; #else phys_addr = virt_to_bus(scp->request_buffer); #endif - if (ha->raw_feat & SCATTER_GATHER) { - cmdp->u.raw.sdata = 0xffffffff; - cmdp->u.raw.sg_ranz= 1; - cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr; - cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; - cmdp->u.raw.sg_lst[1].sg_len = 0; + if (mode64) { + if (ha->raw_feat & SCATTER_GATHER) { + cmdp->u.raw64.sdata = (ulong64)-1; + cmdp->u.raw64.sg_ranz= 1; + cmdp->u.raw64.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.raw64.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.raw64.sg_lst[1].sg_len = 0; + } else { + cmdp->u.raw64.sdata = phys_addr; + cmdp->u.raw64.sg_ranz= 0; + } } else { - cmdp->u.raw.sdata = phys_addr; - cmdp->u.raw.sg_ranz= 0; + if (ha->raw_feat & SCATTER_GATHER) { + cmdp->u.raw.sdata = 0xffffffff; + cmdp->u.raw.sg_ranz= 1; + cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.raw.sg_lst[1].sg_len = 0; + } else { + cmdp->u.raw.sdata = phys_addr; + cmdp->u.raw.sg_ranz= 0; + } } } - TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", - cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz, - cmdp->u.raw.sg_lst[0].sg_ptr, - cmdp->u.raw.sg_lst[0].sg_len)); - - /* evaluate command size */ - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + - (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str); + if (mode64) { + TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.raw64.sdata,cmdp->u.raw64.sg_ranz, + cmdp->u.raw64.sg_lst[0].sg_ptr, + cmdp->u.raw64.sg_lst[0].sg_len)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) + + (ushort)cmdp->u.raw64.sg_ranz * sizeof(gdth_sg64_str); + } else { + TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz, + cmdp->u.raw.sg_lst[0].sg_ptr, + cmdp->u.raw.sg_lst[0].sg_len)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + + (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str); + } } /* check space */ if (ha->cmd_len & 3) @@ -3215,15 +3372,23 @@ if (cmdp->OpCode == GDT_IOCTL) { TRACE2(("IOCTL\n")); ha->cmd_len = - GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong32); + GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong64); } else if (cmdp->Service == CACHESERVICE) { TRACE2(("cache command %d\n",cmdp->OpCode)); - ha->cmd_len = - GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str); + if (ha->cache_feat & GDT_64BIT) + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) + sizeof(gdth_sg64_str); + else + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str); } else if (cmdp->Service == SCSIRAWSERVICE) { - TRACE2(("raw command %d/%d\n",cmdp->OpCode,cmdp->u.raw.cmd[0])); - ha->cmd_len = - GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str); + TRACE2(("raw command %d\n",cmdp->OpCode)); + if (ha->raw_feat & GDT_64BIT) + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) + sizeof(gdth_sg64_str); + else + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str); } if (ha->cmd_len & 3) @@ -3366,10 +3531,14 @@ /* SCSI interface functions */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) +#else +static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) +#endif { register gdth_ha_str *ha; - gdt6m_dpram_str *dp6m_ptr; + gdt6m_dpram_str *dp6m_ptr = NULL; gdt6_dpram_str *dp6_ptr; gdt2_dpram_str *dp2_ptr; Scsi_Cmnd *scp; @@ -3377,13 +3546,23 @@ unchar IStatus; ushort Service; ulong flags = 0; +#ifdef INT_COAL + int coalesced = FALSE; + int next = FALSE; + gdth_coal_status *pcs = NULL; + int act_int_coal = 0; +#endif TRACE(("gdth_interrupt() IRQ %d\n",irq)); /* if polling and not from gdth_wait() -> return */ if (gdth_polling) { if (!gdth_from_wait) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) return IRQ_HANDLED; +#else + return; +#endif } } @@ -3396,174 +3575,261 @@ /* spurious interrupt */ if (!gdth_polling) GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif } + ha = HADATA(gdth_ctr_tab[hanum]); #ifdef GDTH_STATISTICS ++act_ints; #endif - - ha = HADATA(gdth_ctr_tab[hanum]); - if (ha->type == GDT_EISA) { - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = inw(ha->bmic + MAILBOXREG+8); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = inl(ha->bmic + MAILBOXREG+12); - ha->service = inw(ha->bmic + MAILBOXREG+10); - ha->info2 = inl(ha->bmic + MAILBOXREG+4); - outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */ - outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */ - } else if (ha->type == GDT_ISA) { - dp2_ptr = (gdt2_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = gdth_readw(&dp2_ptr->u.ic.Status); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]); - ha->service = gdth_readw(&dp2_ptr->u.ic.Service); - ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]); - - gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */ - gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index); /* reset command index */ - gdth_writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */ - } else if (ha->type == GDT_PCI) { - dp6_ptr = (gdt6_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = gdth_readw(&dp6_ptr->u.ic.Status); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]); - ha->service = gdth_readw(&dp6_ptr->u.ic.Service); - ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]); - - gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */ - gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index); /* reset command index */ - gdth_writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */ - } else if (ha->type == GDT_PCINEW) { - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = inw(PTR2USHORT(&ha->plx->status)); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else - ha->status = S_OK; - ha->info = inl(PTR2USHORT(&ha->plx->info[0])); - ha->service = inw(PTR2USHORT(&ha->plx->service)); - ha->info2 = inl(PTR2USHORT(&ha->plx->info[1])); - - outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); - outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); - } else if (ha->type == GDT_PCIMPR) { - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = gdth_readw(&dp6m_ptr->i960r.status); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]); - ha->service = gdth_readw(&dp6m_ptr->i960r.service); - ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]); +#ifdef INT_COAL + /* See if the fw is returning coalesced status */ + if (IStatus == COALINDEX) { + /* Coalesced status. Setup the initial status + buffer pointer and flags */ + pcs = ha->coal_stat; + coalesced = TRUE; + next = TRUE; + } - /* event string */ - if (IStatus == ASYNCINDEX) { - if (ha->service != SCREENSERVICE && - (ha->fw_vers & 0xff) >= 0x1a) { - ha->dvr.severity = - gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.severity); - for (i = 0; i < 256; ++i) { - ha->dvr.event_string[i] = gdth_readb - (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]); - if (ha->dvr.event_string[i] == 0) - break; + do { + if (coalesced) { + /* For coalesced requests all status + information is found in the status buffer */ + IStatus = (unchar)(pcs->status & 0xff); + } +#endif + + if (ha->type == GDT_EISA) { + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = inw(ha->bmic + MAILBOXREG+8); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; + ha->info = inl(ha->bmic + MAILBOXREG+12); + ha->service = inw(ha->bmic + MAILBOXREG+10); + ha->info2 = inl(ha->bmic + MAILBOXREG+4); + + outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */ + outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */ + } else if (ha->type == GDT_ISA) { + dp2_ptr = (gdt2_dpram_str *)ha->brd; + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = gdth_readw(&dp2_ptr->u.ic.Status); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; + ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]); + ha->service = gdth_readw(&dp2_ptr->u.ic.Service); + ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]); + + gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */ + gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);/* reset command index */ + gdth_writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */ + } else if (ha->type == GDT_PCI) { + dp6_ptr = (gdt6_dpram_str *)ha->brd; + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = gdth_readw(&dp6_ptr->u.ic.Status); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; + ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]); + ha->service = gdth_readw(&dp6_ptr->u.ic.Service); + ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]); + + gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */ + gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);/* reset command index */ + gdth_writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */ + } else if (ha->type == GDT_PCINEW) { + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = inw(PTR2USHORT(&ha->plx->status)); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else + ha->status = S_OK; + ha->info = inl(PTR2USHORT(&ha->plx->info[0])); + ha->service = inw(PTR2USHORT(&ha->plx->service)); + ha->info2 = inl(PTR2USHORT(&ha->plx->info[1])); + + outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); + outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); + } else if (ha->type == GDT_PCIMPR) { + dp6m_ptr = (gdt6m_dpram_str *)ha->brd; + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; +#ifdef INT_COAL + if (coalesced) + ha->status = pcs->ext_status && 0xffff; + else +#endif + ha->status = gdth_readw(&dp6m_ptr->i960r.status); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; +#ifdef INT_COAL + /* get information */ + if (coalesced) { + ha->info = pcs->info0; + ha->info2 = pcs->info1; + ha->service = (pcs->ext_status >> 16) && 0xffff; + } else +#endif + { + ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]); + ha->service = gdth_readw(&dp6m_ptr->i960r.service); + ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]); + } + /* event string */ + if (IStatus == ASYNCINDEX) { + if (ha->service != SCREENSERVICE && + (ha->fw_vers & 0xff) >= 0x1a) { + ha->dvr.severity = gdth_readb + (&((gdt6m_dpram_str *)ha->brd)->i960r.severity); + for (i = 0; i < 256; ++i) { + ha->dvr.event_string[i] = gdth_readb + (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]); + if (ha->dvr.event_string[i] == 0) + break; + } } } +#ifdef INT_COAL + /* Make sure that non coalesced interrupts get cleared + before being handled by gdth_async_event/gdth_sync_event */ + if (!coalesced) +#endif + { + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); + } + } else { + TRACE2(("gdth_interrupt() unknown controller type\n")); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif } - gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); - } else { - TRACE2(("gdth_interrupt() unknown controller type\n")); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } - TRACE(("gdth_interrupt() index %d stat %d info %d\n", - IStatus,ha->status,ha->info)); + TRACE(("gdth_interrupt() index %d stat %d info %d\n", + IStatus,ha->status,ha->info)); - if (gdth_from_wait) { - wait_hanum = hanum; - wait_index = (int)IStatus; - } + if (gdth_from_wait) { + wait_hanum = hanum; + wait_index = (int)IStatus; + } - if (IStatus == ASYNCINDEX) { - TRACE2(("gdth_interrupt() async. event\n")); - gdth_async_event(hanum); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - gdth_next(hanum); - return IRQ_HANDLED; - } + if (IStatus == ASYNCINDEX) { + TRACE2(("gdth_interrupt() async. event\n")); + gdth_async_event(hanum); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); + gdth_next(hanum); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif + } - if (IStatus == SPEZINDEX) { - TRACE2(("Service unknown or not initialized !\n")); - ha->dvr.size = sizeof(ha->dvr.eu.driver); - ha->dvr.eu.driver.ionode = hanum; - gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } - scp = ha->cmd_tab[IStatus-2].cmnd; - Service = ha->cmd_tab[IStatus-2].service; - ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND; - if (scp == UNUSED_CMND) { - TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus)); - ha->dvr.size = sizeof(ha->dvr.eu.driver); - ha->dvr.eu.driver.ionode = hanum; - ha->dvr.eu.driver.index = IStatus; - gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } - if (scp == INTERNAL_CMND) { - TRACE(("gdth_interrupt() answer to internal command\n")); + if (IStatus == SPEZINDEX) { + TRACE2(("Service unknown or not initialized !\n")); + ha->dvr.size = sizeof(ha->dvr.eu.driver); + ha->dvr.eu.driver.ionode = hanum; + gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif + } + scp = ha->cmd_tab[IStatus-2].cmnd; + Service = ha->cmd_tab[IStatus-2].service; + ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND; + if (scp == UNUSED_CMND) { + TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus)); + ha->dvr.size = sizeof(ha->dvr.eu.driver); + ha->dvr.eu.driver.ionode = hanum; + ha->dvr.eu.driver.index = IStatus; + gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif + } + if (scp == INTERNAL_CMND) { + TRACE(("gdth_interrupt() answer to internal command\n")); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif + } + + TRACE(("gdth_interrupt() sync. status\n")); + rval = gdth_sync_event(hanum,Service,IStatus,scp); if (!gdth_polling) GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } - - TRACE(("gdth_interrupt() sync. status\n")); - rval = gdth_sync_event(hanum,Service,IStatus,scp); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - if (rval == 2) { - gdth_putq(hanum,scp,scp->SCp.this_residual); - } else if (rval == 1) { -#if LINUX_VERSION_CODE >= 0x02053C - GDTH_LOCK_SCSI_DONE(scp->device->host, flags); - scp->scsi_done(scp); - GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags); -#elif LINUX_VERSION_CODE >= 0x020503 - GDTH_LOCK_SCSI_DONE(scp->host, flags); - scp->scsi_done(scp); - GDTH_UNLOCK_SCSI_DONE(scp->host, flags); -#else - GDTH_LOCK_SCSI_DONE(flags); - scp->scsi_done(scp); - GDTH_UNLOCK_SCSI_DONE(flags); + if (rval == 2) { + gdth_putq(hanum,scp,scp->SCp.this_residual); + } else if (rval == 1) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + GDTH_LOCK_SCSI_DONE(scp->device->host, flags); + scp->scsi_done(scp); + GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags); +#else + GDTH_LOCK_SCSI_DONE(flags); + scp->scsi_done(scp); + GDTH_UNLOCK_SCSI_DONE(flags); #endif + } + +#ifdef INT_COAL + if (coalesced) { + /* go to the next status in the status buffer */ + ++pcs; +#ifdef GDTH_STATISTICS + ++act_int_coal; + if (act_int_coal > max_int_coal) { + max_int_coal = act_int_coal; + printk("GDT: max_int_coal = %d\n",(ushort)max_int_coal); + } +#endif + /* see if there is another status */ + if (pcs->status == 0) + /* Stop the coalesce loop */ + next = FALSE; + } + } while (next); + + /* coalescing only for new GDT_PCIMPR controllers available */ + if (ha->type == GDT_PCIMPR && coalesced) { + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); } +#endif + gdth_next(hanum); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) return IRQ_HANDLED; +#endif } static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) @@ -3579,10 +3845,11 @@ service,ha->status)); if (service == SCREENSERVICE) { - msg = (gdth_msg_str *)ha->pscratch; - ha->scratch_busy = FALSE; + msg = ha->pmsg; TRACE(("len: %d, answer: %d, ext: %d, alen: %d\n", msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen)); + if (msg->msg_len > MSGLEN+1) + msg->msg_len = MSGLEN+1; if (msg->msg_len) if (!(msg->msg_answer && msg->msg_ext)) { msg->msg_text[msg->msg_len] = '\0'; @@ -3600,11 +3867,10 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= msg->msg_handle; - cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; - ha->scratch_busy = TRUE; + cmdp->u.screen.su.msg.msg_addr = ha->msg_phys; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) - + sizeof(ulong32); + + sizeof(ulong64); ha->cmd_cnt = 0; gdth_copy_command(hanum); gdth_release_event(hanum); @@ -3635,11 +3901,10 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= msg->msg_handle; - cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; - ha->scratch_busy = TRUE; + cmdp->u.screen.su.msg.msg_addr = ha->msg_phys; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) - + sizeof(ulong32); + + sizeof(ulong64); ha->cmd_cnt = 0; gdth_copy_command(hanum); gdth_release_event(hanum); @@ -3648,7 +3913,7 @@ printk("\n"); } else { -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; #else @@ -3666,16 +3931,20 @@ /* retry */ return 2; } -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) 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); + pci_unmap_page(ha->pdev,scp->SCp.dma_handle, + scp->request_bufflen,scp->SCp.Message); + if (scp->SCp.buffer) { + dma_addr_t addr; + addr = (dma_addr_t)(ulong32)scp->SCp.buffer; + if (scp->host_scribble) + addr += (dma_addr_t)((ulong64)(ulong32)scp->host_scribble << 32); + pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE); + } #endif if (ha->status == S_OK) { scp->SCp.Status = S_OK; @@ -3754,10 +4023,7 @@ scp->sense_buffer[2] = NOT_READY; scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); } -#if LINUX_VERSION_CODE >= 0x010300 - if (scp->done != gdth_scsi_done) -#endif - { + if (scp->done != gdth_scsi_done) { ha->dvr.size = sizeof(ha->dvr.eu.sync); ha->dvr.eu.sync.ionode = hanum; ha->dvr.eu.sync.service = service; @@ -3946,13 +4212,11 @@ static int gdth_async_event(int hanum) { gdth_ha_str *ha; - gdth_msg_str *msg; gdth_cmd_str *cmdp; int cmd_index; ha = HADATA(gdth_ctr_tab[hanum]); cmdp= ha->pccb; - msg = (gdth_msg_str *)ha->pscratch; TRACE2(("gdth_async_event() ha %d serv %d\n", hanum,ha->service)); @@ -3968,11 +4232,10 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= MSG_INV_HANDLE; - cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; - ha->scratch_busy = TRUE; + cmdp->u.screen.su.msg.msg_addr = ha->msg_phys; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) - + sizeof(ulong32); + + sizeof(ulong64); ha->cmd_cnt = 0; gdth_copy_command(hanum); if (ha->type == GDT_EISA) @@ -4192,10 +4455,11 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) { struct Scsi_Host *shp; + gdth_pci_str pcistr[MAXHA]; gdth_ha_str *ha; ulong32 isa_bios; ushort eisa_slot; - int i,hanum,cnt,ctr; + int i,hanum,cnt,ctr,err; unchar b; @@ -4218,11 +4482,11 @@ TRACE(("gdth_detect()\n")); if (disable) { - printk("GDT: Controller driver disabled from command line !\n"); + printk("GDT-HA: Controller driver disabled from command line !\n"); return 0; } - printk("GDT: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR); + printk("GDT-HA: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR); /* initializations */ gdth_polling = TRUE; b = 0; gdth_clear_events(); @@ -4232,6 +4496,7 @@ /* scanning for controllers, at first: ISA controller */ for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) { dma_addr_t scratch_dma_handle; + scratch_dma_handle = 0; if (gdth_ctr_count >= MAXHA) break; @@ -4252,23 +4517,14 @@ printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n", isa_bios,ha->irq,ha->drq); -#if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) -#else - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) -#endif - { + if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) { printk("GDT-ISA: Unable to allocate IRQ\n"); scsi_unregister(shp); continue; } if (request_dma(ha->drq,"gdth")) { printk("GDT-ISA: Unable to allocate DMA channel\n"); -#if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,ha); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -4286,15 +4542,34 @@ ha->pccb = CMDDATA(shp); ha->ccb_phys = 0L; -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ha->pdev = NULL; ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, &scratch_dma_handle); - ha->scratch_phys = (ulong32)scratch_dma_handle; + ha->scratch_phys = scratch_dma_handle; + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + ha->msg_phys = scratch_dma_handle; +#ifdef INT_COAL + ha->coal_stat = (gdth_coal_status *) + pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, &scratch_dma_handle); + ha->coal_stat_phys = scratch_dma_handle; +#endif #else ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); if (ha->pscratch) ha->scratch_phys = virt_to_bus(ha->pscratch); + ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA); + if (ha->pmsg) + ha->msg_phys = virt_to_bus(ha->pmsg); +#ifdef INT_COAL + ha->coal_stat = + scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS, + GFP_ATOMIC | GFP_DMA); + if (ha->coal_stat) + ha->coal_stat_phys = virt_to_bus(ha->coal_stat); +#endif #endif ha->scratch_busy = FALSE; ha->req_first = NULL; @@ -4305,23 +4580,36 @@ ha->cmd_tab[i].cmnd = UNUSED_CMND; ha->scan_mode = rescan ? 0x10 : 0; - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { + if (ha->pscratch == NULL || ha->pmsg == NULL || + !gdth_search_drives(hanum)) { printk("GDT-ISA: Error during device scan\n"); --gdth_ctr_count; --gdth_ctr_vcount; - if (ha->pscratch != NULL) { -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, + ha->coal_stat_phys); +#endif + if (ha->pscratch) pci_free_consistent(ha->pdev, GDTH_SCRATCH, ha->pscratch, ha->scratch_phys); -#else + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); +#else +#ifdef INT_COAL + if (ha->coal_stat) + scsi_init_free((void *)ha->coal_stat, + sizeof(gdth_coal_status) * MAXOFFSETS); +#endif + if (ha->pscratch) scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + if (ha->pmsg) + scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str)); #endif - } -#if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,ha); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -4329,13 +4617,18 @@ hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + shp->highmem_io = 0; +#endif + if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) + shp->max_cmd_len = 16; +#endif shp->max_id = ha->tid_cnt; shp->max_lun = MAXLUN; shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) -#endif - { + if (virt_ctr) { virt_ctr = 1; /* register addit. SCSI channels as virtual controllers */ for (b = 1; b < ha->bus_cnt + 1; ++b) { @@ -4358,6 +4651,7 @@ /* scanning for EISA controllers */ for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) { dma_addr_t scratch_dma_handle; + scratch_dma_handle = 0; if (gdth_ctr_count >= MAXHA) break; @@ -4373,14 +4667,9 @@ } /* controller found and initialized */ printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n", - eisa_slot>>12,ha->irq); + eisa_slot>>12,ha->irq); -#if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) -#else - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) -#endif - { + if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) { printk("GDT-EISA: Unable to allocate IRQ\n"); scsi_unregister(shp); continue; @@ -4399,11 +4688,20 @@ ha->pccb = CMDDATA(shp); ha->ccb_phys = 0L; -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ha->pdev = NULL; ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, &scratch_dma_handle); - ha->scratch_phys = (ulong32) scratch_dma_handle; + ha->scratch_phys = scratch_dma_handle; + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + ha->msg_phys = scratch_dma_handle; +#ifdef INT_COAL + ha->coal_stat = (gdth_coal_status *) + pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, &scratch_dma_handle); + ha->coal_stat_phys = scratch_dma_handle; +#endif ha->ccb_phys = pci_map_single(ha->pdev,ha->pccb, sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); @@ -4411,6 +4709,16 @@ ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); if (ha->pscratch) ha->scratch_phys = virt_to_bus(ha->pscratch); + ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA); + if (ha->pmsg) + ha->msg_phys = virt_to_bus(ha->pmsg); +#ifdef INT_COAL + ha->coal_stat = + scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS, + GFP_ATOMIC | GFP_DMA); + if (ha->coal_stat) + ha->coal_stat_phys = virt_to_bus(ha->coal_stat); +#endif ha->ccb_phys = virt_to_bus(ha->pccb); #endif ha->scratch_busy = FALSE; @@ -4419,28 +4727,42 @@ if (max_ids > 0 && max_ids < ha->tid_cnt) ha->tid_cnt = max_ids; for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; + ha->cmd_tab[i].cmnd = UNUSED_CMND; ha->scan_mode = rescan ? 0x10 : 0; - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { + if (ha->pscratch == NULL || ha->pmsg == NULL || + !gdth_search_drives(hanum)) { printk("GDT-EISA: Error during device scan\n"); --gdth_ctr_count; --gdth_ctr_vcount; - if (ha->pscratch != NULL) { -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, + ha->coal_stat_phys); +#endif + if (ha->pscratch) pci_free_consistent(ha->pdev, GDTH_SCRATCH, ha->pscratch, ha->scratch_phys); + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); + if (ha->ccb_phys) pci_unmap_single(ha->pdev,ha->ccb_phys, - sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); + sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); #else +#ifdef INT_COAL + if (ha->coal_stat) + scsi_init_free((void *)ha->coal_stat, + sizeof(gdth_coal_status) * MAXOFFSETS); +#endif + if (ha->pscratch) scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + if (ha->pmsg) + scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str)); #endif - } -#if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,ha); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -4448,13 +4770,18 @@ hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + shp->highmem_io = 0; +#endif + if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) + shp->max_cmd_len = 16; +#endif shp->max_id = ha->tid_cnt; shp->max_lun = MAXLUN; shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) -#endif - { + if (virt_ctr) { virt_ctr = 1; /* register addit. SCSI channels as virtual controllers */ for (b = 1; b < ha->bus_cnt + 1; ++b) { @@ -4475,124 +4802,173 @@ } /* scanning for PCI controllers */ -#if LINUX_VERSION_CODE < 0x2015C - if (pcibios_present()) -#endif - { - gdth_pci_str pcistr[MAXHA]; + cnt = gdth_search_pci(pcistr); + printk("GDT-HA: Found %d PCI Storage RAID Controllers\n",cnt); + gdth_sort_pci(pcistr,cnt); + for (ctr = 0; ctr < cnt; ++ctr) { + dma_addr_t scratch_dma_handle; + scratch_dma_handle = 0; - cnt = gdth_search_pci(pcistr); - printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt); - gdth_sort_pci(pcistr,cnt); - for (ctr = 0; ctr < cnt; ++ctr) { - dma_addr_t scratch_dma_handle; + if (gdth_ctr_count >= MAXHA) + break; + shp = scsi_register(shtp,sizeof(gdth_ext_str)); + if (shp == NULL) + continue; + + ha = HADATA(shp); + if (!gdth_init_pci(&pcistr[ctr],ha)) { + scsi_unregister(shp); + continue; + } + /* controller found and initialized */ + printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n", + pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); - if (gdth_ctr_count >= MAXHA) - break; - shp = scsi_register(shtp,sizeof(gdth_ext_str)); - if (shp == NULL) - continue; - - ha = HADATA(shp); - if (!gdth_init_pci(&pcistr[ctr],ha)) { - scsi_unregister(shp); - continue; - } - /* controller found and initialized */ - printk("GDT CTR%d: Configuring GDT-PCI HA at %d/%d IRQ %u\n", - ctr,pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); - -#if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq, gdth_interrupt, - SA_INTERRUPT|SA_SHIRQ, "gdth", ha)) -#else - if (request_irq(ha->irq, gdth_interrupt, - SA_INTERRUPT|SA_SHIRQ, "gdth")) -#endif - { - printk("GDT-PCI: Unable to allocate IRQ\n"); - scsi_unregister(shp); - continue; - } - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - hanum = gdth_ctr_count; - gdth_ctr_tab[gdth_ctr_count++] = shp; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum= 0; - - ha->pccb = CMDDATA(shp); - ha->ccb_phys = 0L; -#if LINUX_VERSION_CODE >= 0x020400 - ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, - &scratch_dma_handle); - ha->scratch_phys = (ulong32)scratch_dma_handle; -#else - ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); - if (ha->pscratch) - ha->scratch_phys = virt_to_bus(ha->pscratch); -#endif - ha->scratch_busy = FALSE; - ha->req_first = NULL; - ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES; - if (max_ids > 0 && max_ids < ha->tid_cnt) - ha->tid_cnt = max_ids; - for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; - ha->scan_mode = rescan ? 0x10 : 0; - - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { - printk("GDT-PCI: Error during device scan\n"); - --gdth_ctr_count; - --gdth_ctr_vcount; - if (ha->pscratch != NULL) { -#if LINUX_VERSION_CODE >= 0x020400 - pci_free_consistent(ha->pdev, GDTH_SCRATCH, - ha->pscratch, ha->scratch_phys); -#else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + if (request_irq(ha->irq, gdth_interrupt, + SA_INTERRUPT|SA_SHIRQ, "gdth", ha)) + { + printk("GDT-PCI: Unable to allocate IRQ\n"); + scsi_unregister(shp); + continue; + } + shp->unchecked_isa_dma = 0; + shp->irq = ha->irq; + shp->dma_channel = 0xff; + hanum = gdth_ctr_count; + gdth_ctr_tab[gdth_ctr_count++] = shp; + gdth_ctr_vtab[gdth_ctr_vcount++] = shp; + + NUMDATA(shp)->hanum = (ushort)hanum; + NUMDATA(shp)->busnum= 0; + + ha->pccb = CMDDATA(shp); + ha->ccb_phys = 0L; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, + &scratch_dma_handle); + ha->scratch_phys = scratch_dma_handle; + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + ha->msg_phys = scratch_dma_handle; +#ifdef INT_COAL + ha->coal_stat = (gdth_coal_status *) + pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, &scratch_dma_handle); + ha->coal_stat_phys = scratch_dma_handle; +#endif +#else + ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); + if (ha->pscratch) + ha->scratch_phys = virt_to_bus(ha->pscratch); + ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA); + if (ha->pmsg) + ha->msg_phys = virt_to_bus(ha->pmsg); +#ifdef INT_COAL + ha->coal_stat = + scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS, + GFP_ATOMIC | GFP_DMA); + if (ha->coal_stat) + ha->coal_stat_phys = virt_to_bus(ha->coal_stat); #endif - } -#if LINUX_VERSION_CODE >= 0x010346 - free_irq(ha->irq,ha); -#else - free_irq(ha->irq); #endif - scsi_unregister(shp); - continue; - } + ha->scratch_busy = FALSE; + ha->req_first = NULL; + ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES; + if (max_ids > 0 && max_ids < ha->tid_cnt) + ha->tid_cnt = max_ids; + for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; + ha->scan_mode = rescan ? 0x10 : 0; + + err = FALSE; + if (ha->pscratch == NULL || ha->pmsg == NULL || + !gdth_search_drives(hanum)) { + err = TRUE; + } else { if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 - shp->max_id = ha->tid_cnt; - shp->max_lun = MAXLUN; - shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) -#endif - { - virt_ctr = 1; - /* register addit. SCSI channels as virtual controllers */ - for (b = 1; b < ha->bus_cnt + 1; ++b) { - shp = scsi_register(shtp,sizeof(gdth_num_str)); - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum = b; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + scsi_set_device(shp, &pcistr[ctr].pdev->dev); +#else + scsi_set_pci_device(shp, pcistr[ctr].pdev); +#endif + if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)|| + /* 64-bit DMA only supported from FW >= x.43 */ + (!ha->dma64_support)) { + if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) { + printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum); + err = TRUE; + } + } else { + shp->max_cmd_len = 16; + if (!pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffffffffffffULL)) { + printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum); + } else if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) { + printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum); + err = TRUE; } - } + } +#endif + } - GDTH_INIT_LOCK_HA(ha); - gdth_enable_int(hanum); + if (err) { + printk("GDT-PCI %d: Error during device scan\n", hanum); + --gdth_ctr_count; + --gdth_ctr_vcount; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, + ha->coal_stat_phys); +#endif + if (ha->pscratch) + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); +#else +#ifdef INT_COAL + if (ha->coal_stat) + scsi_init_free((void *)ha->coal_stat, + sizeof(gdth_coal_status) * MAXOFFSETS); +#endif + if (ha->pscratch) + scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + if (ha->pmsg) + scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str)); +#endif + free_irq(ha->irq,ha); + scsi_unregister(shp); + continue; } - } + shp->max_id = ha->tid_cnt; + shp->max_lun = MAXLUN; + shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; + if (virt_ctr) { + virt_ctr = 1; + /* register addit. SCSI channels as virtual controllers */ + for (b = 1; b < ha->bus_cnt + 1; ++b) { + shp = scsi_register(shtp,sizeof(gdth_num_str)); + shp->unchecked_isa_dma = 0; + shp->irq = ha->irq; + shp->dma_channel = 0xff; + gdth_ctr_vtab[gdth_ctr_vcount++] = shp; + NUMDATA(shp)->hanum = (ushort)hanum; + NUMDATA(shp)->busnum = b; + } + } + + + GDTH_INIT_LOCK_HA(ha); + gdth_enable_int(hanum); + } + TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count)); if (gdth_ctr_count > 0) { #ifdef GDTH_STATISTICS @@ -4603,12 +4979,8 @@ 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 } gdth_polling = FALSE; return gdth_ctr_vcount; @@ -4624,30 +4996,47 @@ if (NUMDATA(shp)->busnum == 0) { hanum = NUMDATA(shp)->hanum; ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x010300 - gdth_flush(hanum); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + if (ha->sdev) { + scsi_free_host_dev(ha->sdev); + ha->sdev = NULL; + } #endif + gdth_flush(hanum); if (shp->irq) { -#if LINUX_VERSION_CODE >= 0x010346 free_irq(shp->irq,ha); -#else - free_irq(shp->irq); -#endif } #ifndef __ia64__ if (shp->dma_channel != 0xff) { free_dma(shp->dma_channel); } #endif -#if LINUX_VERSION_CODE >= 0x020400 - pci_free_consistent(ha->pdev, GDTH_SCRATCH, - ha->pscratch, ha->scratch_phys); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, ha->coal_stat_phys); +#endif + if (ha->pscratch) + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); if (ha->ccb_phys) pci_unmap_single(ha->pdev,ha->ccb_phys, sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); #else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); +#ifdef INT_COAL + if (ha->coal_stat) + scsi_init_free((void *)ha->coal_stat, + sizeof(gdth_coal_status) * MAXOFFSETS); +#endif + if (ha->pscratch) + scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + if (ha->pmsg) + scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str)); #endif gdth_ctr_released++; TRACE2(("gdth_release(): HA %d of %d\n", @@ -4657,12 +5046,8 @@ #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 } } @@ -4715,6 +5100,7 @@ return ((const char *)ha->binfo.type_string); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) /* old error handling */ int gdth_abort(Scsi_Cmnd *scp) { @@ -4722,17 +5108,13 @@ return SCSI_ABORT_SNOOZE; } -#if LINUX_VERSION_CODE >= 0x010346 int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags) -#else -int gdth_reset(Scsi_Cmnd *scp) -#endif { TRACE2(("gdth_reset()\n")); return SCSI_RESET_PUNT; } +#endif -#if LINUX_VERSION_CODE >= 0x02015F /* new error handling */ int gdth_eh_abort(Scsi_Cmnd *scp) { @@ -4755,7 +5137,7 @@ unchar b; TRACE2(("gdth_eh_bus_reset()\n")); -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) hanum = NUMDATA(scp->device->host)->hanum; b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; #else @@ -4768,7 +5150,7 @@ GDTH_LOCK_HA(ha, flags); for (i = 0; i < GDTH_MAXCMDS; ++i) { cmnd = ha->cmd_tab[i].cmnd; -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) if (!SPECIAL_SCP(cmnd) && cmnd->device->channel == b) #else if (!SPECIAL_SCP(cmnd) && cmnd->channel == b) @@ -4813,15 +5195,12 @@ TRACE2(("gdth_eh_host_reset()\n")); return FAILED; } -#endif -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 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) +int gdth_bios_param(Disk *disk,kdev_t dev,int *ip) #endif { unchar b, t; @@ -4830,7 +5209,7 @@ struct scsi_device *sd; unsigned capacity; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) sd = sdev; capacity = cap; #else @@ -4872,7 +5251,7 @@ scp->SCp.sent_command = -1; scp->SCp.Status = GDTH_MAP_NONE; scp->SCp.buffer = (struct scatterlist *)NULL; -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) hanum = NUMDATA(scp->device->host)->hanum; #else hanum = NUMDATA(scp->host)->hanum; @@ -4882,19 +5261,28 @@ #endif priority = DEFAULT_PRI; -#if LINUX_VERSION_CODE >= 0x010300 if (scp->done == gdth_scsi_done) priority = scp->SCp.this_residual; -#endif gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6); gdth_putq( hanum, scp, priority ); gdth_next( hanum ); return 0; } -#ifdef GDTH_IOCTL_CHRDEV + static int gdth_open(struct inode *inode, struct file *filep) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_ha_str *ha; + int i; + + for (i = 0; i < gdth_ctr_count; i++) { + ha = HADATA(gdth_ctr_tab[i]); + if (!ha->sdev) + ha->sdev = scsi_get_host_dev(gdth_ctr_tab[i]); + } +#endif + TRACE(("gdth_open()\n")); return 0; } @@ -4907,537 +5295,578 @@ static int ioc_event(unsigned long arg) { - 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]); + gdth_ioctl_event evt; + gdth_ha_str *ha; + ulong flags; - if (evt.erase == 0xff) { - if (evt.event.event_source == ES_TEST) - evt.event.event_data.size=sizeof(evt.event.event_data.eu.test); - else if (evt.event.event_source == ES_DRIVER) - evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver); - else if (evt.event.event_source == ES_SYNC) - evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync); - else - evt.event.event_data.size=sizeof(evt.event.event_data.eu.async); - GDTH_LOCK_HA(ha, flags); - gdth_store_event(ha, evt.event.event_source, evt.event.event_idx, - &evt.event.event_data); - GDTH_UNLOCK_HA(ha, flags); - } else if (evt.erase == 0xfe) { - gdth_clear_events(); - } else if (evt.erase == 0) { - evt.handle = gdth_read_event(ha, evt.handle, &evt.event); - } else { - gdth_readapp_event(ha, evt.erase, &evt.event); - } - if (copy_to_user((char *)arg, &evt, sizeof(gdth_ioctl_event))) - return -EFAULT; - return 0; + if (copy_from_user(&evt, (char *)arg, sizeof(gdth_ioctl_event)) || + evt.ionode >= gdth_ctr_count) + return -EFAULT; + ha = HADATA(gdth_ctr_tab[evt.ionode]); + + if (evt.erase == 0xff) { + if (evt.event.event_source == ES_TEST) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.test); + else if (evt.event.event_source == ES_DRIVER) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver); + else if (evt.event.event_source == ES_SYNC) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync); + else + evt.event.event_data.size=sizeof(evt.event.event_data.eu.async); + GDTH_LOCK_HA(ha, flags); + gdth_store_event(ha, evt.event.event_source, evt.event.event_idx, + &evt.event.event_data); + GDTH_UNLOCK_HA(ha, flags); + } else if (evt.erase == 0xfe) { + gdth_clear_events(); + } else if (evt.erase == 0) { + evt.handle = gdth_read_event(ha, evt.handle, &evt.event); + } else { + gdth_readapp_event(ha, evt.erase, &evt.event); + } + if (copy_to_user((char *)arg, &evt, sizeof(gdth_ioctl_event))) + return -EFAULT; + return 0; } static int ioc_lockdrv(unsigned long arg) { - gdth_ioctl_lockdrv ldrv; - unchar i, j; - ulong flags; - gdth_ha_str *ha; + gdth_ioctl_lockdrv ldrv; + unchar i, j; + ulong flags; + gdth_ha_str *ha; - if (copy_from_user(&ldrv, (char *)arg, sizeof(gdth_ioctl_lockdrv)) || - ldrv.ionode >= gdth_ctr_count) - return -EFAULT; - ha = HADATA(gdth_ctr_tab[ldrv.ionode]); + if (copy_from_user(&ldrv, (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); - } - } - return 0; + for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) { + j = ldrv.drives[i]; + if (j >= MAX_HDRIVES || !ha->hdr[j].present) + continue; + if (ldrv.lock) { + GDTH_LOCK_HA(ha, flags); + ha->hdr[j].lock = 1; + GDTH_UNLOCK_HA(ha, flags); + gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j); + gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j); + } else { + GDTH_LOCK_HA(ha, flags); + ha->hdr[j].lock = 0; + GDTH_UNLOCK_HA(ha, flags); + gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j); + gdth_next(ldrv.ionode); + } + } + return 0; } static int ioc_resetdrv(unsigned long arg, char *cmnd) { - gdth_ioctl_reset res; - gdth_cmd_str cmd; - int hanum; - gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; -#else - Scsi_Cmnd scp; - Scsi_Device sdev; + gdth_ioctl_reset res; + gdth_cmd_str cmd; + int hanum; + gdth_ha_str *ha; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + Scsi_Request *srp; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + Scsi_Cmnd *scp; +#else + Scsi_Cmnd scp; #endif - if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) || - res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES) - return -EFAULT; - hanum = res.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); + if (copy_from_user(&res, (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; + if (!ha->hdr[res.number].present) + return 0; + memset(&cmd, 0, sizeof(gdth_cmd_str)); + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_CLUST_RESET; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = res.number; + else cmd.u.cache.DeviceNo = res.number; -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &cmd, cmnd, 30); - res.status = (ushort)srp->sr_command->SCp.Status; - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &cmd, cmnd, 30); - res.status = (ushort)scp->SCp.Status; - scsi_release_command(scp); - scsi_free_host_dev(sdev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; + gdth_do_req(srp, &cmd, cmnd, 30); + res.status = (ushort)srp->sr_command->SCp.Status; + scsi_release_request(srp); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scp = scsi_allocate_device(ha->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); #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; + memset(&ha->sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + ha->sdev.host = scp.host = gdth_ctr_tab[hanum]; + ha->sdev.id = scp.target = ha->sdev.host->this_id; + scp.device = &ha->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; - return 0; + if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset))) + return -EFAULT; + return 0; } static int ioc_general(unsigned long arg, char *cmnd) { - gdth_ioctl_general gen; - char *buf = NULL; - ulong32 paddr; - int hanum; - gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; + gdth_ioctl_general gen; + char *buf = NULL; + ulong64 paddr; + int hanum; + gdth_ha_str *ha; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + Scsi_Request *srp; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + Scsi_Cmnd *scp; #else - Scsi_Cmnd scp; - Scsi_Device sdev; + Scsi_Cmnd scp; #endif - if (copy_from_user(&gen, (char *)arg, sizeof(gdth_ioctl_general)) || - gen.ionode >= gdth_ctr_count) + 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; - hanum = gen.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); - if (gen.data_len + gen.sense_len != 0) { - if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len, - FALSE, &paddr))) - return -EFAULT; - if (copy_from_user(buf, (char *)arg + sizeof(gdth_ioctl_general), - gen.data_len + gen.sense_len)) { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); - return -EFAULT; - } + if (copy_from_user(buf, (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 (gen.command.OpCode == GDT_IOCTL) { + gen.command.u.ioctl.p_param = paddr; + } else if (gen.command.Service == CACHESERVICE) { + if (ha->cache_feat & GDT_64BIT) { + /* copy elements from 32-bit IOCTL structure */ + gen.command.u.cache64.BlockCnt = gen.command.u.cache.BlockCnt; + gen.command.u.cache64.BlockNo = gen.command.u.cache.BlockNo; + gen.command.u.cache64.DeviceNo = gen.command.u.cache.DeviceNo; + /* addresses */ + if (ha->cache_feat & SCATTER_GATHER) { + gen.command.u.cache64.DestAddr = (ulong64)-1; + gen.command.u.cache64.sg_canz = 1; + gen.command.u.cache64.sg_lst[0].sg_ptr = paddr; + gen.command.u.cache64.sg_lst[0].sg_len = gen.data_len; + gen.command.u.cache64.sg_lst[1].sg_len = 0; + } else { + gen.command.u.cache64.DestAddr = paddr; + gen.command.u.cache64.sg_canz = 0; + } + } else { if (ha->cache_feat & SCATTER_GATHER) { gen.command.u.cache.DestAddr = 0xffffffff; gen.command.u.cache.sg_canz = 1; - gen.command.u.cache.sg_lst[0].sg_ptr = paddr; + gen.command.u.cache.sg_lst[0].sg_ptr = (ulong32)paddr; gen.command.u.cache.sg_lst[0].sg_len = gen.data_len; gen.command.u.cache.sg_lst[1].sg_len = 0; } else { gen.command.u.cache.DestAddr = paddr; gen.command.u.cache.sg_canz = 0; } - } else if (gen.command.Service == SCSIRAWSERVICE) { + } + } else if (gen.command.Service == SCSIRAWSERVICE) { + if (ha->raw_feat & GDT_64BIT) { + /* copy elements from 32-bit IOCTL structure */ + char cmd[16]; + gen.command.u.raw64.sense_len = gen.command.u.raw.sense_len; + gen.command.u.raw64.bus = gen.command.u.raw.bus; + gen.command.u.raw64.lun = gen.command.u.raw.lun; + gen.command.u.raw64.target = gen.command.u.raw.target; + memcpy(cmd, gen.command.u.raw.cmd, 16); + memcpy(gen.command.u.raw64.cmd, cmd, 16); + gen.command.u.raw64.clen = gen.command.u.raw.clen; + gen.command.u.raw64.sdlen = gen.command.u.raw.sdlen; + gen.command.u.raw64.direction = gen.command.u.raw.direction; + /* addresses */ + if (ha->raw_feat & SCATTER_GATHER) { + gen.command.u.raw64.sdata = (ulong64)-1; + gen.command.u.raw64.sg_ranz = 1; + gen.command.u.raw64.sg_lst[0].sg_ptr = paddr; + gen.command.u.raw64.sg_lst[0].sg_len = gen.data_len; + gen.command.u.raw64.sg_lst[1].sg_len = 0; + } else { + gen.command.u.raw64.sdata = paddr; + gen.command.u.raw64.sg_ranz = 0; + } + gen.command.u.raw64.sense_data = paddr + gen.data_len; + } else { if (ha->raw_feat & SCATTER_GATHER) { gen.command.u.raw.sdata = 0xffffffff; gen.command.u.raw.sg_ranz = 1; - gen.command.u.raw.sg_lst[0].sg_ptr = paddr; + gen.command.u.raw.sg_lst[0].sg_ptr = (ulong32)paddr; gen.command.u.raw.sg_lst[0].sg_len = gen.data_len; gen.command.u.raw.sg_lst[1].sg_len = 0; } else { gen.command.u.raw.sdata = paddr; gen.command.u.raw.sg_ranz = 0; } - gen.command.u.raw.sense_data = paddr + gen.data_len; - - } else { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); - return -EFAULT; + gen.command.u.raw.sense_data = (ulong32)paddr + gen.data_len; } + } 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, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &gen.command, cmnd, gen.timeout); - gen.status = srp->sr_command->SCp.Status; - gen.info = srp->sr_command->SCp.Message; - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout); - gen.status = scp->SCp.Status; - gen.info = scp->SCp.Message; - scsi_release_command(scp); - scsi_free_host_dev(sdev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; + gdth_do_req(srp, &gen.command, cmnd, gen.timeout); + gen.status = srp->sr_command->SCp.Status; + gen.info = srp->sr_command->SCp.Message; + scsi_release_request(srp); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scp = scsi_allocate_device(ha->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); #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; + memset(&ha->sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + ha->sdev.host = scp.host = gdth_ctr_tab[hanum]; + ha->sdev.id = scp.target = ha->sdev.host->this_id; + scp.device = &ha->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; - } + 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 0; + 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); + return 0; } static int ioc_hdrlist(unsigned long arg, char *cmnd) { - gdth_ioctl_rescan rsc; - gdth_cmd_str cmd; - gdth_ha_str *ha; - unchar i; - int hanum; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; + gdth_ioctl_rescan rsc; + gdth_cmd_str cmd; + gdth_ha_str *ha; + unchar i; + int hanum; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + Scsi_Request *srp; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + Scsi_Cmnd *scp; #else - Scsi_Cmnd scp; - Scsi_Device sdev; + Scsi_Cmnd scp; #endif - if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) || - rsc.ionode >= gdth_ctr_count) - return -EFAULT; - hanum = rsc.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); + 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]); + memset(&cmd, 0, sizeof(gdth_cmd_str)); -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scp = scsi_allocate_device(ha->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; + memset(&ha->sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + ha->sdev.host = scp.host = gdth_ctr_tab[hanum]; + ha->sdev.id = scp.target = ha->sdev.host->this_id; + scp.device = &ha->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; + 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; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = i; + else 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; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + 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 >= KERNEL_VERSION(2,4,0) + 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); + } + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + scsi_release_request(srp); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scsi_release_command(scp); #endif - if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) - return -EFAULT; - return 0; + if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) + return -EFAULT; + return 0; } static int ioc_rescan(unsigned long arg, char *cmnd) { - gdth_ioctl_rescan rsc; - gdth_cmd_str cmd; - ushort i, status, hdr_cnt; - ulong32 info; - int hanum, cyls, hds, secs; - ulong flags; - gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; + gdth_ioctl_rescan rsc; + gdth_cmd_str cmd; + ushort i, status, hdr_cnt; + ulong32 info; + int hanum, cyls, hds, secs; + ulong flags; + gdth_ha_str *ha; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + Scsi_Request *srp; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + Scsi_Cmnd *scp; #else - Scsi_Cmnd scp; - Scsi_Device sdev; + Scsi_Cmnd scp; #endif - if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) || - rsc.ionode >= gdth_ctr_count) - return -EFAULT; - hanum = rsc.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); + 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]); + memset(&cmd, 0, sizeof(gdth_cmd_str)); -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scp = scsi_allocate_device(ha->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; + memset(&ha->sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + ha->sdev.host = scp.host = gdth_ctr_tab[hanum]; + ha->sdev.id = scp.target = ha->sdev.host->this_id; + scp.device = &ha->sdev; #endif - if (rsc.flag == 0) { - /* old method: re-init. cache service */ - cmd.Service = CACHESERVICE; + if (rsc.flag == 0) { + /* old method: re-init. cache service */ + cmd.Service = CACHESERVICE; + if (ha->cache_feat & GDT_64BIT) { + cmd.OpCode = GDT_X_INIT_HOST; + cmd.u.cache64.DeviceNo = LINUX_OS; + } else { 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; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + 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 >= KERNEL_VERSION(2,4,0) + 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; + 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; + i = 0; + hdr_cnt = (status == S_OK ? (ushort)info : 0); + } else { + i = rsc.hdr_no; + hdr_cnt = i + 1; + } + for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) { + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_INFO; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = i; + else cmd.u.cache.DeviceNo = i; -#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; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + 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 >= KERNEL_VERSION(2,4,0) + 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; + 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; + 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; + + /* extended info, if GDT_64BIT, for drives > 2 TB */ + /* but we need ha->info2, not yet stored in scp->SCp */ - /* devtype, cluster info, R/W attribs */ - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_DEVTYPE; + /* devtype, cluster info, R/W attribs */ + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_DEVTYPE; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = i; + else cmd.u.cache.DeviceNo = i; -#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; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + 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 >= KERNEL_VERSION(2,4,0) + 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; + 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); + 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.Service = CACHESERVICE; + cmd.OpCode = GDT_CLUST_INFO; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = i; + else cmd.u.cache.DeviceNo = i; -#if 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; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + 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 >= KERNEL_VERSION(2,4,0) + 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; + 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; + 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.Service = CACHESERVICE; + cmd.OpCode = GDT_RW_ATTRIBS; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = i; + else 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; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + 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 >= KERNEL_VERSION(2,4,0) + 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; + 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); + 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 >= KERNEL_VERSION(2,6,0) + scsi_release_request(srp); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scsi_release_command(scp); #endif - if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) - return -EFAULT; - return 0; + if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) + return -EFAULT; + 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 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) Scsi_Cmnd *scp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Cmnd *scp; - Scsi_Device *sdev; #else Scsi_Cmnd scp; - Scsi_Device sdev; #endif ulong flags; char cmnd[MAX_COMMAND_SIZE]; @@ -5451,7 +5880,7 @@ { int cnt = gdth_ctr_count; if (put_user(cnt, (int *)arg)) - return -EFAULT; + return -EFAULT; break; } @@ -5459,7 +5888,7 @@ { int ver = (GDTH_VERSION<<8) | GDTH_SUBVERSION; if (put_user(ver, (int *)arg)) - return -EFAULT; + return -EFAULT; break; } @@ -5471,7 +5900,7 @@ osv.subversion = (unchar)(LINUX_VERSION_CODE >> 8); osv.revision = (ushort)(LINUX_VERSION_CODE & 0xff); if (copy_to_user((char *)arg, &osv, sizeof(gdth_ioctl_osvers))) - return -EFAULT; + return -EFAULT; break; } @@ -5507,13 +5936,13 @@ } case GDTIOCTL_GENERAL: - return ioc_general(arg, cmnd); + return ioc_general(arg, cmnd); case GDTIOCTL_EVENT: - return ioc_event(arg); + return ioc_event(arg); case GDTIOCTL_LOCKDRV: - return ioc_lockdrv(arg); + return ioc_lockdrv(arg); case GDTIOCTL_LOCKCHN: { @@ -5549,10 +5978,10 @@ } case GDTIOCTL_RESCAN: - return ioc_rescan(arg, cmnd); + return ioc_rescan(arg, cmnd); case GDTIOCTL_HDRLIST: - return ioc_hdrlist(arg, cmnd); + return ioc_hdrlist(arg, cmnd); case GDTIOCTL_RESET_BUS: { @@ -5563,11 +5992,11 @@ res.ionode >= gdth_ctr_count) return -EFAULT; hanum = res.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); - /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.5.x */ -#if LINUX_VERSION_CODE >= 0x02053C - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_get_command(sdev, GFP_KERNEL); + /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.6.x */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + scp = scsi_get_command(ha->sdev, GFP_KERNEL); if (!scp) return -ENOMEM; scp->cmd_len = 12; @@ -5576,14 +6005,8 @@ 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 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scp = scsi_allocate_device(ha->sdev, 1, FALSE); if (!scp) return -ENOMEM; scp->cmd_len = 12; @@ -5592,18 +6015,15 @@ 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)); +#else + memset(&ha->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; + ha->sdev.host = scp.host = gdth_ctr_tab[hanum]; + ha->sdev.id = scp.target = ha->sdev.host->this_id; + scp.device = &ha->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; @@ -5611,26 +6031,25 @@ } case GDTIOCTL_RESET_DRV: - return ioc_resetdrv(arg, cmnd); + return ioc_resetdrv(arg, cmnd); default: break; } return 0; } -#endif -#if LINUX_VERSION_CODE >= 0x010300 + /* flush routine */ static void gdth_flush(int hanum) { int i; gdth_ha_str *ha; gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) Scsi_Request *srp; Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Cmnd *scp; Scsi_Device *sdev; #else @@ -5643,14 +6062,14 @@ TRACE2(("gdth_flush() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return; srp->sr_cmd_len = 12; srp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); scp = scsi_allocate_device(sdev, 1, FALSE); if (!scp) @@ -5670,42 +6089,44 @@ gdtcmd.BoardNode = LOCALBOARD; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_FLUSH; - gdtcmd.u.cache.DeviceNo = i; - gdtcmd.u.cache.BlockNo = 1; - gdtcmd.u.cache.sg_canz = 0; + if (ha->cache_feat & GDT_64BIT) { + gdtcmd.u.cache64.DeviceNo = i; + gdtcmd.u.cache64.BlockNo = 1; + gdtcmd.u.cache64.sg_canz = 0; + } else { + gdtcmd.u.cache.DeviceNo = i; + gdtcmd.u.cache.BlockNo = 1; + gdtcmd.u.cache.sg_canz = 0; + } TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i)); -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) gdth_do_req(srp, &gdtcmd, cmnd, 30); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); #endif } } -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) scsi_release_request(srp); scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) scsi_release_command(scp); scsi_free_host_dev(sdev); #endif } /* shutdown routine */ -#if LINUX_VERSION_CODE >= 0x020100 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) -#else -void gdth_halt(void) -#endif { int hanum; #ifndef __alpha__ gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) Scsi_Request *srp; Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Cmnd *scp; Scsi_Device *sdev; #else @@ -5715,20 +6136,11 @@ char cmnd[MAX_COMMAND_SIZE]; #endif -#if LINUX_VERSION_CODE >= 0x020100 TRACE2(("gdth_halt() event %d\n",(int)event)); if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) return NOTIFY_DONE; -#else - TRACE2(("gdth_halt()\n")); - if (halt_called) { - TRACE2(("already called\n")); - return; - } - halt_called = TRUE; -#endif - printk("GDT: Flushing all host drives .. "); + printk("GDT-HA: Flushing all host drives .. "); for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { gdth_flush(hanum); @@ -5739,32 +6151,24 @@ gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_RESET; TRACE2(("gdth_halt(): reset controller %d\n", hanum)); -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) { -#if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); return NOTIFY_OK; -#else - return; -#endif } srp->sr_cmd_len = 12; srp->sr_use_sg = 0; gdth_do_req(srp, &gdtcmd, cmnd, 10); scsi_release_request(srp); scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) 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; @@ -5786,15 +6190,12 @@ #ifdef GDTH_STATISTICS del_timer(&gdth_timer); #endif -#if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); return NOTIFY_OK; -#endif } -#endif -#if LINUX_VERSION_CODE < 0x020400 && !defined(MODULE) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) && !defined(MODULE) GDTH_INITFUNC(void, gdth_setup(char *str,int *ints)) { @@ -5805,33 +6206,36 @@ #else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static Scsi_Host_Template driver_template = { -#if LINUX_VERSION_CODE >= 0x02015F - .proc_name = "gdth", -#else - .proc_dir = &proc_scsi_gdth, + .proc_name = "gdth", + .proc_info = gdth_proc_info, + .name = "GDT SCSI Disk Array Controller", + .detect = gdth_detect, + .release = gdth_release, + .info = gdth_info, + .queuecommand = gdth_queuecommand, + .eh_abort_handler = gdth_eh_abort, + .eh_device_reset_handler = gdth_eh_device_reset, + .eh_bus_reset_handler = gdth_eh_bus_reset, + .eh_host_reset_handler = gdth_eh_host_reset, + .bios_param = gdth_bios_param, + .can_queue = GDTH_MAXCMDS, + .this_id = -1, + .sg_tablesize = GDTH_MAXSG, + .cmd_per_lun = GDTH_MAXC_P_L, + .unchecked_isa_dma = 1, + .use_clustering = ENABLE_CLUSTERING, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + .use_new_eh_code = 1, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) + .highmem_io = 1, #endif - .proc_info = gdth_proc_info, - .name = "GDT SCSI Disk Array Controller", - .detect = gdth_detect, - .release = gdth_release, - .info = gdth_info, - .queuecommand = gdth_queuecommand, - .eh_abort_handler = gdth_eh_abort, - .eh_device_reset_handler = gdth_eh_device_reset, - .eh_bus_reset_handler = gdth_eh_bus_reset, - .eh_host_reset_handler = gdth_eh_host_reset, - .bios_param = gdth_bios_param, - .can_queue = GDTH_MAXCMDS, - .this_id = -1, - .sg_tablesize = GDTH_MAXSG, - .cmd_per_lun = GDTH_MAXC_P_L, - .unchecked_isa_dma = 1, - .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE < 0x020501 - .use_new_eh_code = 1, #endif }; +#else +static Scsi_Host_Template driver_template = GDTH; +#endif #include "scsi_module.c" #ifndef MODULE diff -Nru a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h --- a/drivers/scsi/gdth.h Fri May 21 19:07:22 2004 +++ b/drivers/scsi/gdth.h Fri May 21 19:07:22 2004 @@ -10,7 +10,7 @@ * * * - * $Id: gdth.h,v 1.50 2003/09/17 08:29:58 achim Exp $ + * $Id: gdth.h,v 1.57 2004/03/31 11:52:09 achim Exp $ */ #include @@ -26,9 +26,9 @@ /* defines, macros */ /* driver version */ -#define GDTH_VERSION_STR "2.08" -#define GDTH_VERSION 2 -#define GDTH_SUBVERSION 8 +#define GDTH_VERSION_STR "3.04" +#define GDTH_VERSION 3 +#define GDTH_SUBVERSION 4 /* protocol version */ #define PROTOCOL_VERSION 1 @@ -133,7 +133,12 @@ /* new GDT Rx Controller */ #define PCI_DEVICE_ID_VORTEX_GDTNEWRX 0x300 #endif - + +#ifndef PCI_DEVICE_ID_VORTEX_GDTNEWRX2 +/* new(2) GDT Rx Controller */ +#define PCI_DEVICE_ID_VORTEX_GDTNEWRX2 0x301 +#endif + #ifndef PCI_DEVICE_ID_INTEL_SRC /* Intel Storage RAID Controller */ #define PCI_DEVICE_ID_INTEL_SRC 0x600 @@ -146,8 +151,7 @@ /* limits */ #define GDTH_SCRATCH PAGE_SIZE /* 4KB scratch buffer */ -#define GDTH_SCRATCH_ORD 0 /* order 0 means 1 page */ -#define GDTH_MAXCMDS 124 +#define GDTH_MAXCMDS 120 #define GDTH_MAXC_P_L 16 /* max. cmds per lun */ #define GDTH_MAX_RAW 2 /* max. cmds per raw device */ #define MAXOFFSETS 128 @@ -221,6 +225,8 @@ #define GDT_CLUST_RESET 24 /* releases the cluster drives*/ #define GDT_FREEZE_IO 25 /* freezes all IOs */ #define GDT_UNFREEZE_IO 26 /* unfreezes all IOs */ +#define GDT_X_INIT_HOST 29 /* ext. init: 64 bit support */ +#define GDT_X_INFO 30 /* ext. info for drives>2TB */ /* raw service commands */ #define GDT_RESERVE 14 /* reserve dev. to raw serv. */ @@ -230,9 +236,11 @@ #define GDT_RESET_BUS 18 /* reset bus */ #define GDT_SCAN_START 19 /* start device scan */ #define GDT_SCAN_END 20 /* stop device scan */ +#define GDT_X_INIT_RAW 21 /* ext. init: 64 bit support */ /* screen service commands */ #define GDT_REALTIME 3 /* realtime clock to screens. */ +#define GDT_X_INIT_SCR 4 /* ext. init: 64 bit support */ /* IOCTL command defines */ #define SCSI_DR_INFO 0x00 /* SCSI drive info */ @@ -254,6 +262,8 @@ #define CACHE_DRV_INFO 0x07 /* cache drive info */ #define BOARD_FEATURES 0x15 /* controller features */ #define BOARD_INFO 0x28 /* controller info */ +#define SET_PERF_MODES 0x82 /* set mode (coalescing,..) */ +#define GET_PERF_MODES 0x83 /* get mode */ #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 */ @@ -266,6 +276,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_NOFUNC -2 /* unknown function */ #define S_CACHE_RESERV -24 /* cache: reserv. conflict */ /* timeout values */ @@ -307,7 +318,12 @@ #define LOCALBOARD 0 /* board node always 0 */ #define ASYNCINDEX 0 /* cmd index async. event */ #define SPEZINDEX 1 /* cmd index unknown service */ +#define COALINDEX (GDTH_MAXCMDS + 2) + +/* features */ +#define SCATTER_GATHER 1 /* s/g feature */ #define GDT_WR_THROUGH 0x100 /* WRITE_THROUGH supported */ +#define GDT_64BIT 0x200 /* 64bit / drv>2TB support */ #include "gdth_ioctl.h" @@ -322,7 +338,40 @@ char msg_text[MSGLEN+2]; /* the message text */ } PACKED gdth_msg_str; + /* IOCTL data structures */ + +/* Status coalescing buffer for returning multiple requests per interrupt */ +typedef struct { + ulong32 status; + ulong32 ext_status; + ulong32 info0; + ulong32 info1; +} PACKED gdth_coal_status; + +/* performance mode data structure */ +typedef struct { + ulong32 version; /* The version of this IOCTL structure. */ + ulong32 st_mode; /* 0=dis., 1=st_buf_addr1 valid, 2=both */ + ulong32 st_buff_addr1; /* physical address of status buffer 1 */ + ulong32 st_buff_u_addr1; /* reserved for 64 bit addressing */ + ulong32 st_buff_indx1; /* reserved command idx. for this buffer */ + ulong32 st_buff_addr2; /* physical address of status buffer 1 */ + ulong32 st_buff_u_addr2; /* reserved for 64 bit addressing */ + ulong32 st_buff_indx2; /* reserved command idx. for this buffer */ + ulong32 st_buff_size; /* size of each buffer in bytes */ + ulong32 cmd_mode; /* 0 = mode disabled, 1 = cmd_buff_addr1 */ + ulong32 cmd_buff_addr1; /* physical address of cmd buffer 1 */ + ulong32 cmd_buff_u_addr1; /* reserved for 64 bit addressing */ + ulong32 cmd_buff_indx1; /* cmd buf addr1 unique identifier */ + ulong32 cmd_buff_addr2; /* physical address of cmd buffer 1 */ + ulong32 cmd_buff_u_addr2; /* reserved for 64 bit addressing */ + ulong32 cmd_buff_indx2; /* cmd buf addr1 unique identifier */ + ulong32 cmd_buff_size; /* size of each cmd bufer in bytes */ + ulong32 reserved1; + ulong32 reserved2; +} PACKED gdth_perf_modes; + /* SCSI drive info */ typedef struct { unchar vendor[8]; /* vendor string */ @@ -795,9 +844,7 @@ /* PCI resources */ typedef struct { -#if LINUX_VERSION_CODE >= 0x02015C struct pci_dev *pdev; -#endif ushort vendor_id; /* vendor (ICP, Intel, ..) */ ushort device_id; /* device ID (0,..,9) */ ushort subdevice_id; /* sub device ID */ @@ -814,20 +861,28 @@ typedef struct { ushort oem_id; /* OEM */ ushort type; /* controller class */ - ushort raw_feat; /* feat. raw service (s/g,..) */ ulong32 stype; /* subtype (PCI: device ID) */ ushort subdevice_id; /* sub device ID (PCI) */ ushort fw_vers; /* firmware version */ - ushort cache_feat; /* feat. cache serv. (s/g,..) */ + ushort cache_feat; /* feat. cache serv. (s/g,..)*/ + ushort raw_feat; /* feat. raw service (s/g,..)*/ + ushort screen_feat; /* feat. raw service (s/g,..)*/ ushort bmic; /* BMIC address (EISA) */ void *brd; /* DPRAM address */ 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 */ +#ifdef INT_COAL + gdth_coal_status *coal_stat; /* buffer for coalescing int.*/ + ulong64 coal_stat_phys; /* phys. address */ +#endif char *pscratch; /* scratch (DMA) buffer */ - ulong32 scratch_phys; /* phys. address */ + ulong64 scratch_phys; /* phys. address */ unchar scratch_busy; /* in use? */ + unchar dma64_support; /* 64-bit DMA supported? */ + gdth_msg_str *pmsg; /* message buffer */ + ulong64 msg_phys; /* phys. address */ unchar scan_mode; /* current scan mode */ unchar irq; /* IRQ */ unchar drq; /* DRQ (ISA controllers) */ @@ -848,11 +903,11 @@ unchar heads; /* mapping */ unchar secs; ushort devtype; /* further information */ - ulong32 size; /* capacity */ + ulong64 size; /* capacity */ unchar ldr_no; /* log. drive no. */ unchar rw_attribs; /* r/w attributes */ unchar cluster_type; /* cluster properties */ - unchar media_changed; /* Flag:MOUNT/UNMOUNT occurred*/ + unchar media_changed; /* Flag:MOUNT/UNMOUNT occured */ ulong32 start_sec; /* start sector */ } hdr[MAX_LDRIVES]; /* host drives */ struct { @@ -880,13 +935,19 @@ gdth_bfeat_str bfeat; /* controller features */ gdth_binfo_str binfo; /* controller info */ gdth_evt_data dvr; /* event structure */ -#if LINUX_VERSION_CODE >= 0x02015F spinlock_t smp_lock; -#endif -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) struct pci_dev *pdev; #endif char oem_name[8]; +#ifdef GDTH_DMA_STATISTICS + ulong dma32_cnt, dma64_cnt; /* statistics: DMA buffer */ +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + Scsi_Device *sdev; +#else + Scsi_Device sdev; +#endif } gdth_ha_str; /* structure for scsi_register(), SCSI bus != 0 */ @@ -924,6 +985,12 @@ ulong32 block_length; } PACKED gdth_rdcap_data; +/* READ_CAPACITY (16) data format */ +typedef struct { + ulong64 last_block_no; + ulong32 block_length; +} PACKED gdth_rdcap16_data; + /* REQUEST_SENSE data format */ typedef struct { unchar errorcode; @@ -965,42 +1032,48 @@ int gdth_detect(Scsi_Host_Template *); int gdth_release(struct Scsi_Host *); int gdth_queuecommand(Scsi_Cmnd *,void (*done)(Scsi_Cmnd *)); -int gdth_abort(Scsi_Cmnd *); -#if LINUX_VERSION_CODE >= 0x010346 -int gdth_reset(Scsi_Cmnd *, unsigned int reset_flags); -#else -int gdth_reset(Scsi_Cmnd *); -#endif const char *gdth_info(struct Scsi_Host *); -#if LINUX_VERSION_CODE >= 0x020501 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) int gdth_bios_param(struct scsi_device *,struct block_device *,sector_t,int *); int gdth_proc_info(struct Scsi_Host *, char *,char **,off_t,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); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) 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); -#elif LINUX_VERSION_CODE >= 0x02015F +#else 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_abort(Scsi_Cmnd *); +int gdth_reset(Scsi_Cmnd *,unsigned int); +#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 */ } +#endif + 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); -#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); -#else -int gdth_bios_param(Disk *,int,int *); -#endif -#endif +#endif diff -Nru a/drivers/scsi/gdth_ioctl.h b/drivers/scsi/gdth_ioctl.h --- a/drivers/scsi/gdth_ioctl.h Fri May 21 19:07:22 2004 +++ b/drivers/scsi/gdth_ioctl.h Fri May 21 19:07:22 2004 @@ -2,7 +2,7 @@ #define _GDTH_IOCTL_H /* gdth_ioctl.h - * $Id: gdth_ioctl.h,v 1.11 2003/02/27 14:59:03 achim Exp $ + * $Id: gdth_ioctl.h,v 1.14 2004/02/19 15:43:15 achim Exp $ */ /* IOCTLs */ @@ -21,8 +21,8 @@ #define GDTIOCTL_RESCAN (GDTIOCTL_MASK |11) /* rescan host drives */ #define GDTIOCTL_RESET_DRV (GDTIOCTL_MASK |12) /* reset (remote) drv. res. */ -#define GDTIOCTL_MAGIC 0xaffe0004 -#define EVENT_SIZE 294 +#define GDTIOCTL_MAGIC 0xaffe0004 +#define EVENT_SIZE 294 #define GDTH_MAXSG 32 /* max. s/g elements */ #define MAX_LDRIVES 255 /* max. log. drive count */ @@ -35,7 +35,9 @@ /* typedefs */ #ifdef __KERNEL__ typedef u32 ulong32; +typedef u64 ulong64; #endif + #define PACKED __attribute__((packed)) /* scatter/gather element */ @@ -44,6 +46,12 @@ ulong32 sg_len; /* length */ } PACKED gdth_sg_str; +/* scatter/gather element - 64bit addresses */ +typedef struct { + ulong64 sg_ptr; /* address */ + ulong32 sg_len; /* length */ +} PACKED gdth_sg64_str; + /* command structure */ typedef struct { ulong32 BoardNode; /* board node (always 0) */ @@ -59,17 +67,25 @@ gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */ } PACKED cache; /* cache service cmd. str. */ struct { + ushort DeviceNo; /* number of cache drive */ + ulong64 BlockNo; /* block number */ + ulong32 BlockCnt; /* block count */ + ulong64 DestAddr; /* dest. addr. (if s/g: -1) */ + ulong32 sg_canz; /* s/g element count */ + gdth_sg64_str sg_lst[GDTH_MAXSG]; /* s/g list */ + } PACKED cache64; /* cache service cmd. str. */ + struct { ushort param_size; /* size of p_param buffer */ ulong32 subfunc; /* IOCTL function */ ulong32 channel; /* device */ - ulong32 p_param; /* buffer */ + ulong64 p_param; /* buffer */ } PACKED ioctl; /* IOCTL command structure */ struct { ushort reserved; union { struct { ulong32 msg_handle; /* message handle */ - ulong32 msg_addr; /* message buffer address */ + ulong64 msg_addr; /* message buffer address */ } PACKED msg; unchar data[12]; /* buffer for rtc data, ... */ } su; @@ -93,6 +109,24 @@ ulong32 sg_ranz; /* s/g element count */ gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */ } PACKED raw; /* raw service cmd. struct. */ + struct { + ushort reserved; + ulong32 direction; /* data direction */ + ulong32 mdisc_time; /* disc. time (0: no timeout)*/ + ulong32 mcon_time; /* connect time(0: no to.) */ + ulong64 sdata; /* dest. addr. (if s/g: -1) */ + ulong32 sdlen; /* data length (bytes) */ + ulong32 clen; /* SCSI cmd. length(6,..,16) */ + unchar cmd[16]; /* 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 */ + ulong64 sense_data; /* sense data addr. */ + ulong32 sg_ranz; /* s/g element count */ + gdth_sg64_str sg_lst[GDTH_MAXSG]; /* s/g list */ + } PACKED raw64; /* raw service cmd. struct. */ } u; /* additional variables */ unchar Service; /* controller service */ @@ -236,7 +270,6 @@ } gdth_iord_str; #endif -#ifdef GDTH_IOCTL_CHRDEV /* GDTIOCTL_GENERAL */ typedef struct { ushort ionode; /* controller number */ @@ -244,8 +277,8 @@ ulong32 info; /* error info */ ushort status; /* status */ ulong data_len; /* data buffer size */ - ulong sense_len; /* sense buffer size */ - gdth_cmd_str command; /* command */ + ulong sense_len; /* sense buffer size */ + gdth_cmd_str command; /* command */ } gdth_ioctl_general; /* GDTIOCTL_LOCKDRV */ @@ -310,6 +343,5 @@ ushort number; /* bus/host drive number */ ushort status; /* status */ } gdth_ioctl_reset; -#endif #endif diff -Nru a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c --- a/drivers/scsi/gdth_proc.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/gdth_proc.c Fri May 21 19:07:22 2004 @@ -1,56 +1,80 @@ /* gdth_proc.c - * $Id: gdth_proc.c,v 1.37 2003/09/17 08:31:53 achim Exp $ + * $Id: gdth_proc.c,v 1.42 2004/03/05 15:50:20 achim Exp $ */ -#if LINUX_VERSION_CODE >= 0x020407 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) #include #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length, int inout) { int hanum,busnum; - TRACE2(("gdth_proc_info() length %d ha %d offs %d inout %d\n", - length,hostno,(int)offset,inout)); + TRACE2(("gdth_proc_info() length %d offs %d inout %d\n", + length,(int)offset,inout)); hanum = NUMDATA(host)->hanum; busnum= NUMDATA(host)->busnum; if (inout) - return(gdth_set_info(buffer,length,hanum,busnum)); + return(gdth_set_info(buffer,length,host,hanum,busnum)); else - return(gdth_get_info(buffer,start,offset,length,hanum,busnum)); + return(gdth_get_info(buffer,start,offset,length,host,hanum,busnum)); } +#else +int gdth_proc_info(char *buffer,char **start,off_t offset,int length,int hostno, + int inout) +{ + int hanum,busnum,i; + + TRACE2(("gdth_proc_info() length %d offs %d inout %d\n", + length,(int)offset,inout)); + + for (i = 0; i < gdth_ctr_vcount; ++i) { + if (gdth_ctr_vtab[i]->host_no == hostno) + break; + } + if (i == gdth_ctr_vcount) + return(-EINVAL); + + hanum = NUMDATA(gdth_ctr_vtab[i])->hanum; + busnum= NUMDATA(gdth_ctr_vtab[i])->busnum; + + if (inout) + return(gdth_set_info(buffer,length,gdth_ctr_vtab[i],hanum,busnum)); + else + return(gdth_get_info(buffer,start,offset,length, + gdth_ctr_vtab[i],hanum,busnum)); +} +#endif -static int gdth_set_info(char *buffer,int length,int hanum,int busnum) +static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, + int hanum,int busnum) { int ret_val = -EINVAL; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) Scsi_Request *scp; Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Cmnd *scp; Scsi_Device *sdev; #else Scsi_Cmnd scp; Scsi_Device sdev; #endif -#ifdef GDTH_IOCTL_PROC - gdth_iowr_str *piowr; - piowr = (gdth_iowr_str *)buffer; -#endif TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + sdev = scsi_get_host_dev(host); scp = scsi_allocate_request(sdev, GFP_KERNEL); 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]); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + sdev = scsi_get_host_dev(host); scp = scsi_allocate_device(sdev, 1, FALSE); if (!scp) return -ENOMEM; @@ -59,7 +83,7 @@ #else memset(&sdev,0,sizeof(Scsi_Device)); memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; + sdev.host = scp.host = host; sdev.id = scp.target = sdev.host->this_id; scp.device = &sdev; #endif @@ -69,32 +93,21 @@ 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 { - printk("GDT: Wrong signature %x (%x required)!\n", - piowr->magic, GDTIOCTL_MAGIC); - if (piowr->magic > GDTIOCTL_MAGIC) - printk("GDT: Please update your driver.\n"); - else - printk("GDT: Please update your tool.\n"); -#endif } } -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) scsi_release_request(scp); scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) scsi_release_command(scp); scsi_free_host_dev(sdev); #endif return ret_val; } -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp) -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) 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) @@ -105,7 +118,7 @@ gdth_ha_str *ha; gdth_cmd_str gdtcmd; gdth_cpar_str *pcpar; - ulong32 paddr; + ulong64 paddr; char cmnd[MAX_COMMAND_SIZE]; memset(cmnd, 0xff, 12); @@ -139,11 +152,16 @@ found = TRUE; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_FLUSH; - gdtcmd.u.cache.DeviceNo = i; - gdtcmd.u.cache.BlockNo = 1; -#if LINUX_VERSION_CODE >= 0x020503 + if (ha->cache_feat & GDT_64BIT) { + gdtcmd.u.cache64.DeviceNo = i; + gdtcmd.u.cache64.BlockNo = 1; + } else { + gdtcmd.u.cache.DeviceNo = i; + gdtcmd.u.cache.BlockNo = 1; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) gdth_do_req(scp, &gdtcmd, cmnd, 30); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); @@ -199,9 +217,9 @@ gdtcmd.u.ioctl.subfunc = CACHE_CONFIG; gdtcmd.u.ioctl.channel = INVALID_CHANNEL; pcpar->write_back = wb_mode==1 ? 0:1; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) gdth_do_req(scp, &gdtcmd, cmnd, 30); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); @@ -215,562 +233,23 @@ return(-EINVAL); } -#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) -#endif -{ - unchar i, j; - ushort k, hdr_cnt, status; - gdth_ha_str *ha; - gdth_iowr_str *piowr; - gdth_iord_str *piord; - gdth_cmd_str *pcmd; - gdth_evt_str *pevt; - ulong32 *ppadd, add_size, *ppadd2, add_size2, info, paddr; - ulong flags; - gdth_cmd_str gdtcmd; - int drv_cyls, drv_hds, drv_secs; - - char cmnd[MAX_COMMAND_SIZE]; - memset(cmnd, 0xff, 12); - memset(&gdtcmd, 0, sizeof(gdth_cmd_str)); - - TRACE2(("gdth_set_bin_info() ha %d\n",hanum)); - ha = HADATA(gdth_ctr_tab[hanum]); - piowr = (gdth_iowr_str *)buffer; - piord = NULL; - pcmd = NULL; - ppadd = ppadd2 = NULL; - add_size = add_size2 = 0; - - if (length < GDTOFFSOF(gdth_iowr_str,iu)) - return(-EINVAL); - - switch (piowr->ioctl) { - case GDTIOCTL_GENERAL: - if (length < GDTOFFSOF(gdth_iowr_str,iu.general.data[0])) - return(-EINVAL); - pcmd = (gdth_cmd_str *)piowr->iu.general.command; - pcmd->Service = piowr->service; - if (pcmd->OpCode == GDT_IOCTL) { - ppadd = &pcmd->u.ioctl.p_param; - add_size = pcmd->u.ioctl.param_size; - } else if (piowr->service == CACHESERVICE) { - add_size = pcmd->u.cache.BlockCnt * SECTOR_SIZE; - if (ha->cache_feat & SCATTER_GATHER) { - ppadd = &pcmd->u.cache.sg_lst[0].sg_ptr; - pcmd->u.cache.DestAddr = 0xffffffff; - pcmd->u.cache.sg_lst[0].sg_len = add_size; - pcmd->u.cache.sg_canz = 1; - } else { - ppadd = &pcmd->u.cache.DestAddr; - pcmd->u.cache.sg_canz = 0; - } - } else if (piowr->service == SCSIRAWSERVICE) { - add_size = pcmd->u.raw.sdlen; - add_size2 = pcmd->u.raw.sense_len; - if (ha->raw_feat & SCATTER_GATHER) { - ppadd = &pcmd->u.raw.sg_lst[0].sg_ptr; - pcmd->u.raw.sdata = 0xffffffff; - pcmd->u.raw.sg_lst[0].sg_len = add_size; - pcmd->u.raw.sg_ranz = 1; - } else { - ppadd = &pcmd->u.raw.sdata; - pcmd->u.raw.sg_ranz = 0; - } - ppadd2 = &pcmd->u.raw.sense_data; - } else { - return(-EINVAL); - } - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2, - 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 = 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 = paddr + GDTOFFSOF(gdth_iord_str, iu.general.data[0]) + add_size2; - } - - /* do IOCTL */ -#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 - gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout); - piord->status = (scp.SCp.Message<<16)|scp.SCp.Status; -#endif - break; - - case GDTIOCTL_DRVERS: - 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); - piord->status = S_OK; - piord->iu.drvers.version = (GDTH_VERSION<<8) | GDTH_SUBVERSION; - break; - - case GDTIOCTL_CTRTYPE: - 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); - piord->status = S_OK; - if (ha->type == GDT_ISA || ha->type == GDT_EISA) { - piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 0x10); - } else { - if (ha->type != GDT_PCIMPR) { - piord->iu.ctrtype.type = (unchar)((ha->stype<<4) + 6); - } else { - piord->iu.ctrtype.type = - (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe); - if (ha->stype >= 0x300) - piord->iu.ctrtype.ext_type = 0x6000 | ha->subdevice_id; - else - piord->iu.ctrtype.ext_type = 0x6000 | ha->stype; - } - piord->iu.ctrtype.device_id = ha->stype; - piord->iu.ctrtype.sub_device_id = ha->subdevice_id; - } - piord->iu.ctrtype.info = ha->brd_phys; - piord->iu.ctrtype.oem_id = ha->oem_id; - break; - - case GDTIOCTL_CTRCNT: - 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); - piord->status = S_OK; - piord->iu.ctrcnt.count = (ushort)gdth_ctr_count; - break; - - case GDTIOCTL_OSVERS: - 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); - piord->status = S_OK; - piord->iu.osvers.version = (unchar)(LINUX_VERSION_CODE >> 16); - piord->iu.osvers.subversion = (unchar)(LINUX_VERSION_CODE >> 8); - piord->iu.osvers.revision = (ushort)(LINUX_VERSION_CODE & 0xff); - break; - - case GDTIOCTL_LOCKDRV: - 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) { - j = piowr->iu.lockdrv.drives[i]; - if (j >= MAX_HDRIVES || !ha->hdr[j].present) - continue; - if (piowr->iu.lockdrv.lock) { - GDTH_LOCK_HA(ha, flags); - ha->hdr[j].lock = 1; - GDTH_UNLOCK_HA(ha, flags); - gdth_wait_completion( hanum, ha->bus_cnt, j ); - gdth_stop_timeout( hanum, ha->bus_cnt, j ); - } else { - GDTH_LOCK_HA(ha, flags); - ha->hdr[j].lock = 0; - GDTH_UNLOCK_HA(ha, flags); - gdth_start_timeout( hanum, ha->bus_cnt, j ); - gdth_next( hanum ); - } - } - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - break; - - case GDTIOCTL_LOCKCHN: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - i = piowr->iu.lockchn.channel; - if (i < ha->bus_cnt) { - if (piowr->iu.lockchn.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( hanum, i, j ); - gdth_stop_timeout( hanum, 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( hanum, i, j ); - gdth_next( hanum ); - } - } - } - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - break; - - case GDTIOCTL_EVENT: - 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) { - pevt = (gdth_evt_str *)piowr->iu.event.evt; - if (pevt->event_source == ES_TEST) - pevt->event_data.size = sizeof(pevt->event_data.eu.test); - else if (pevt->event_source == ES_DRIVER) - pevt->event_data.size = sizeof(pevt->event_data.eu.driver); - else if (pevt->event_source == ES_SYNC) - pevt->event_data.size = sizeof(pevt->event_data.eu.sync); - else { - pevt->event_data.size = sizeof(pevt->event_data.eu.async); - gdth_log_event(&pevt->event_data, NULL); - } - GDTH_LOCK_HA(ha, flags); - gdth_store_event(ha, pevt->event_source, pevt->event_idx, - &pevt->event_data); - GDTH_UNLOCK_HA(ha, flags); - } else if (piowr->iu.event.erase == 0xfe) { - gdth_clear_events(); - } else if (piowr->iu.event.erase == 0) { - piord->iu.event.handle = - gdth_read_event(ha,piowr->iu.event.handle, - (gdth_evt_str *)piord->iu.event.evt); - } else { - piord->iu.event.handle = piowr->iu.event.handle; - gdth_readapp_event(ha, (unchar)piowr->iu.event.erase, - (gdth_evt_str *)piord->iu.event.evt); - } - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - break; - - case GDTIOCTL_SCSI: -#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->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; -#else - 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; -#endif -#endif - break; - - case GDTIOCTL_RESET_BUS: - 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 >= 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; - else - piord->status = S_GENERR; -#elif LINUX_VERSION_CODE >= 0x02015F - 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; - else - piord->status = S_GENERR; -#else - piord->status = S_OK; -#endif - break; - - case GDTIOCTL_HDRLIST: - 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); - piord->status = S_OK; - for (i = 0; i < MAX_HDRIVES; ++i) { - if (ha->hdr[i].present) { - piord->iu.hdr_list[i].bus = ha->virt_bus; - piord->iu.hdr_list[i].target = i; - piord->iu.hdr_list[i].lun = 0; - piord->iu.hdr_list[i].cluster_type = ha->hdr[i].cluster_type; - if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) { - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_CLUST_INFO; - gdtcmd.u.cache.DeviceNo = i; -#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 = - (unchar)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status == S_OK) - piord->iu.hdr_list[i].cluster_type = - (unchar)scp.SCp.Message; -#endif - } - } else { - piord->iu.hdr_list[i].bus = 0xff; - } - } - break; - - case GDTIOCTL_RESCAN: - 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); - piord->status = S_OK; - if (piowr->iu.rescan.flag == 0) { - /* old method: scan all host drives - re-initialize cache service to get host drive count - */ - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_INIT; - gdtcmd.u.cache.DeviceNo = LINUX_OS; -#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; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - if (status != S_OK) - break; - k = 0; - hdr_cnt = (ushort)info; - } else { - k = piowr->iu.rescan.hdr_no; - hdr_cnt = k + 1; - } - if (hdr_cnt > MAX_HDRIVES) - hdr_cnt = MAX_HDRIVES; - /* scanning for host drives */ - for (; k < hdr_cnt; ++k) { - /* info about host drive */ - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_INFO; - gdtcmd.u.cache.DeviceNo = k; -#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; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - piord->iu.hdr_list[k].bus = ha->virt_bus; - piord->iu.hdr_list[k].target = k; - piord->iu.hdr_list[k].lun = 0; - if (status != S_OK) { - ha->hdr[k].present = FALSE; - } else { - ha->hdr[k].present = TRUE; - ha->hdr[k].size = info; - /* evaluate mapping (sectors per head, heads per cylinder) */ - ha->hdr[k].size &= ~SECS32; - gdth_eval_mapping(ha->hdr[k].size,&drv_cyls,&drv_hds,&drv_secs); - ha->hdr[k].heads = (unchar)drv_hds; - ha->hdr[k].secs = (unchar)drv_secs; - /* round size */ - ha->hdr[k].size = drv_cyls * drv_hds * drv_secs; - } - GDTH_UNLOCK_HA(ha, flags); - if (status != S_OK) - continue; /* next host drive */ - - /* devtype, cluster info, R/W attributes */ - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_DEVTYPE; - gdtcmd.u.cache.DeviceNo = k; -#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; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[k].devtype = 0; - if (status == S_OK) - ha->hdr[k].devtype = (ushort)info; - GDTH_UNLOCK_HA(ha, flags); - - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_CLUST_INFO; - gdtcmd.u.cache.DeviceNo = k; -#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; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[k].cluster_type = 0; - if (status == S_OK && !shared_access) - ha->hdr[k].cluster_type = (ushort)info; - GDTH_UNLOCK_HA(ha, flags); - piord->iu.hdr_list[k].cluster_type = ha->hdr[k].cluster_type; - - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_RW_ATTRIBS; - gdtcmd.u.cache.DeviceNo = k; -#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; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[k].rw_attribs = 0; - if (status == S_OK) - ha->hdr[k].rw_attribs = (ushort)info; - GDTH_UNLOCK_HA(ha, flags); - } - break; - - case GDTIOCTL_RESET_DRV: - 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); - piord->status = S_OK; - i = piowr->iu.scsi.target; - if (ha->hdr[i].present) { - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_CLUST_RESET; - gdtcmd.u.cache.DeviceNo = i; -#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 - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - piord->status = (scp.SCp.Message<<16)|scp.SCp.Status; -#endif - } - break; - - default: - return(-EINVAL); - } - return length; -} -#endif - -static int gdth_get_info(char *buffer,char **start,off_t offset, - int length,int hanum,int busnum) +static int gdth_get_info(char *buffer,char **start,off_t offset,int length, + struct Scsi_Host *host,int hanum,int busnum) { int size = 0,len = 0; off_t begin = 0,pos = 0; gdth_ha_str *ha; int id, i, j, k, sec, flag; int no_mdrv = 0, drv_no, is_mirr; - ulong32 cnt, paddr; + ulong32 cnt; + ulong64 paddr; gdth_cmd_str gdtcmd; gdth_evt_str estr; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) Scsi_Request *scp; Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Cmnd *scp; Scsi_Device *sdev; #else @@ -795,15 +274,15 @@ TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum)); ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + sdev = scsi_get_host_dev(host); scp = scsi_allocate_request(sdev, GFP_KERNEL); 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]); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + sdev = scsi_get_host_dev(host); scp = scsi_allocate_device(sdev, 1, FALSE); if (!scp) return -ENOMEM; @@ -812,485 +291,415 @@ #else memset(&sdev,0,sizeof(Scsi_Device)); memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; + sdev.host = scp.host = host; 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 */ - size = sprintf(buffer+len,"Driver Parameters:\n"); - len += size; pos = begin + len; - if (reserve_list[0] == 0xff) - strcpy(hrec, "--"); - else { - sprintf(hrec, "%d", reserve_list[0]); - for (i = 1; i < MAX_RES_ARGS; i++) { - if (reserve_list[i] == 0xff) - break; - sprintf(hrec,"%s,%d", hrec, reserve_list[i]); - } + + + /* request is i.e. "cat /proc/scsi/gdth/0" */ + /* format: %-15s\t%-10s\t%-15s\t%s */ + /* driver parameters */ + size = sprintf(buffer+len,"Driver Parameters:\n"); + len += size; pos = begin + len; + if (reserve_list[0] == 0xff) + strcpy(hrec, "--"); + else { + sprintf(hrec, "%d", reserve_list[0]); + for (i = 1; i < MAX_RES_ARGS; i++) { + if (reserve_list[i] == 0xff) + break; + sprintf(hrec,"%s,%d", hrec, reserve_list[i]); } - size = sprintf(buffer+len, - " reserve_mode: \t%d \treserve_list: \t%s\n", - reserve_mode, hrec); - len += size; pos = begin + len; - size = sprintf(buffer+len, - " max_ids: \t%-3d \thdr_channel: \t%d\n", - max_ids, hdr_channel); - len += size; pos = begin + len; + } + size = sprintf(buffer+len, + " reserve_mode: \t%d \treserve_list: \t%s\n", + reserve_mode, hrec); + len += size; pos = begin + len; + size = sprintf(buffer+len, + " max_ids: \t%-3d \thdr_channel: \t%d\n", + max_ids, hdr_channel); + len += size; pos = begin + len; + + /* controller information */ + size = sprintf(buffer+len,"\nDisk Array Controller Information:\n"); + len += size; pos = begin + len; + if (virt_ctr) + sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum); + else + strcpy(hrec, ha->binfo.type_string); + size = sprintf(buffer+len, + " Number: \t%d \tName: \t%s\n", + hanum, hrec); + len += size; pos = begin + len; + + if (ha->more_proc) + sprintf(hrec, "%d.%02d.%02d-%c%03X", + (unchar)(ha->binfo.upd_fw_ver>>24), + (unchar)(ha->binfo.upd_fw_ver>>16), + (unchar)(ha->binfo.upd_fw_ver), + ha->bfeat.raid ? 'R':'N', + ha->binfo.upd_revision); + else + sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8), + (unchar)(ha->cpar.version)); - /* controller information */ - size = sprintf(buffer+len,"\nDisk Array Controller Information:\n"); - len += size; pos = begin + len; - if (virt_ctr) - sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum); - else - strcpy(hrec, ha->binfo.type_string); + size = sprintf(buffer+len, + " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n", + GDTH_VERSION_STR, hrec); + len += size; pos = begin + len; + + if (ha->more_proc) { + /* more information: 1. about controller */ size = sprintf(buffer+len, - " Number: \t%d \tName: \t%s\n", - hanum, hrec); + " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n", + ha->binfo.ser_no, ha->binfo.memsize / 1024); len += size; pos = begin + len; + } - if (ha->more_proc) - sprintf(hrec, "%d.%02d.%02d-%c%03X", - (unchar)(ha->binfo.upd_fw_ver>>24), - (unchar)(ha->binfo.upd_fw_ver>>16), - (unchar)(ha->binfo.upd_fw_ver), - ha->bfeat.raid ? 'R':'N', - ha->binfo.upd_revision); - else - sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8), - (unchar)(ha->cpar.version)); +#ifdef GDTH_DMA_STATISTICS + /* controller statistics */ + size = sprintf(buffer+len,"\nController Statistics:\n"); + len += size; pos = begin + len; + size = sprintf(buffer+len, + " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n", + ha->dma32_cnt, ha->dma64_cnt); + len += size; pos = begin + len; +#endif - size = sprintf(buffer+len, - " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n", - GDTH_VERSION_STR, hrec); + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto stop_output; + + if (ha->more_proc) { + /* more information: 2. about physical devices */ + size = sprintf(buffer+len,"\nPhysical Devices:"); len += size; pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) + flag = FALSE; + + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); + if (!buf) goto stop_output; + for (i = 0; i < ha->bus_cnt; ++i) { + /* 2.a statistics (and retries/reassigns) */ + TRACE2(("pdr_statistics() chn %d\n",i)); + pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4); + gdtcmd.Service = CACHESERVICE; + gdtcmd.OpCode = GDT_IOCTL; + 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; + pds->bid = ha->raw[i].local_no; + pds->first = 0; + pds->entries = ha->raw[i].pdev_cnt; + cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) / + sizeof(pds->list[0]); + if (pds->entries > cnt) + pds->entries = cnt; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status != S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &gdtcmd, cmnd, 30); + if (scp->SCp.Status != S_OK) +#else + gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); + if (scp.SCp.Status != S_OK) +#endif + { + pds->count = 0; + } - if (ha->more_proc) { - /* more information: 1. about controller */ - size = sprintf(buffer+len, - " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n", - ha->binfo.ser_no, ha->binfo.memsize / 1024); - len += size; pos = begin + len; - - /* 2. about physical devices */ - size = sprintf(buffer+len,"\nPhysical Devices:"); - len += size; pos = begin + len; - flag = FALSE; - - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); - if (!buf) - goto stop_output; - for (i = 0; i < ha->bus_cnt; ++i) { - /* 2.a statistics (and retries/reassigns) */ - TRACE2(("pdr_statistics() chn %d\n",i)); - pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4); + /* other IOCTLs must fit into area GDTH_SCRATCH/4 */ + for (j = 0; j < ha->raw[i].pdev_cnt; ++j) { + /* 2.b drive info */ + TRACE2(("scsi_drv_info() chn %d dev %d\n", + i, ha->raw[i].id_list[j])); + pdi = (gdth_diskinfo_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; - 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; - pds->bid = ha->raw[i].local_no; - pds->first = 0; - pds->entries = ha->raw[i].pdev_cnt; - cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) / - sizeof(pds->list[0]); - if (pds->entries > cnt) - pds->entries = cnt; -#if LINUX_VERSION_CODE >= 0x020503 + 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 >= KERNEL_VERSION(2,6,0) gdth_do_req(scp, &gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status != S_OK) -#elif LINUX_VERSION_CODE >= 0x020322 + if (scp->sr_command->SCp.Status == S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - if (scp->SCp.Status != S_OK) + if (scp->SCp.Status == S_OK) #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status != S_OK) + if (scp.SCp.Status == S_OK) #endif - { - pds->count = 0; + { + strncpy(hrec,pdi->vendor,8); + strncpy(hrec+8,pdi->product,16); + strncpy(hrec+24,pdi->revision,4); + hrec[28] = 0; + size = sprintf(buffer+len, + "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n", + 'A'+i,pdi->target_id,pdi->lun,hrec); + len += size; pos = begin + len; + flag = TRUE; + pdi->no_ldrive &= 0xffff; + if (pdi->no_ldrive == 0xffff) + strcpy(hrec,"--"); + else + sprintf(hrec,"%d",pdi->no_ldrive); + size = sprintf(buffer+len, + " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n", + pdi->blkcnt/(1024*1024/pdi->blksize), + hrec); + len += size; pos = begin + len; + } else { + pdi->devtype = 0xff; } - - /* other IOCTLs must fit into area GDTH_SCRATCH/4 */ - for (j = 0; j < ha->raw[i].pdev_cnt; ++j) { - /* 2.b drive info */ - TRACE2(("scsi_drv_info() chn %d dev %d\n", - i, ha->raw[i].id_list[j])); - pdi = (gdth_diskinfo_str *)buf; - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_IOCTL; - 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 >= 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 - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status == S_OK) -#endif - { - strncpy(hrec,pdi->vendor,8); - strncpy(hrec+8,pdi->product,16); - strncpy(hrec+24,pdi->revision,4); - hrec[28] = 0; - size = sprintf(buffer+len, - "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n", - 'A'+i,pdi->target_id,pdi->lun,hrec); - len += size; pos = begin + len; - flag = TRUE; - pdi->no_ldrive &= 0xffff; - if (pdi->no_ldrive == 0xffff) - strcpy(hrec,"--"); - else - sprintf(hrec,"%d",pdi->no_ldrive); - size = sprintf(buffer+len, - " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n", - pdi->blkcnt/(1024*1024/pdi->blksize), - hrec); - len += size; pos = begin + len; - } else { - pdi->devtype = 0xff; - } - if (pdi->devtype == 0) { - /* search retries/reassigns */ - for (k = 0; k < pds->count; ++k) { - if (pds->list[k].tid == pdi->target_id && - pds->list[k].lun == pdi->lun) { - size = sprintf(buffer+len, - " Retries: \t%-6d \tReassigns: \t%d\n", - pds->list[k].retries, - pds->list[k].reassigns); - len += size; pos = begin + len; - break; - } - } - /* 2.c grown defects */ - TRACE2(("scsi_drv_defcnt() chn %d dev %d\n", - i, ha->raw[i].id_list[j])); - pdef = (gdth_defcnt_str *)buf; - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_IOCTL; - 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 >= 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 - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status == S_OK) -#endif - { + if (pdi->devtype == 0) { + /* search retries/reassigns */ + for (k = 0; k < pds->count; ++k) { + if (pds->list[k].tid == pdi->target_id && + pds->list[k].lun == pdi->lun) { size = sprintf(buffer+len, - " Grown Defects:\t%d\n", - pdef->sddc_cnt); + " Retries: \t%-6d \tReassigns: \t%d\n", + pds->list[k].retries, + pds->list[k].reassigns); len += size; pos = begin + len; + break; } } - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - } - } - gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); - - if (!flag) { - size = sprintf(buffer+len, "\n --\n"); - len += size; pos = begin + len; - } - - /* 3. about logical drives */ - size = sprintf(buffer+len,"\nLogical Drives:"); - len += size; pos = begin + len; - flag = FALSE; - - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); - if (!buf) - goto stop_output; - for (i = 0; i < MAX_LDRIVES; ++i) { - if (!ha->hdr[i].is_logdrv) - continue; - drv_no = i; - j = k = 0; - is_mirr = FALSE; - do { - /* 3.a log. drive info */ - TRACE2(("cache_drv_info() drive no %d\n",drv_no)); - pcdi = (gdth_cdrinfo_str *)buf; + /* 2.c grown defects */ + TRACE2(("scsi_drv_defcnt() chn %d dev %d\n", + i, ha->raw[i].id_list[j])); + pdef = (gdth_defcnt_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; 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 >= 0x020503 + 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 >= KERNEL_VERSION(2,6,0) gdth_do_req(scp, &gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status != S_OK) -#elif LINUX_VERSION_CODE >= 0x020322 + if (scp->sr_command->SCp.Status == S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - if (scp->SCp.Status != S_OK) + if (scp->SCp.Status == S_OK) #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status != S_OK) + if (scp.SCp.Status == S_OK) #endif { - break; - } - pcdi->ld_dtype >>= 16; - j++; - if (pcdi->ld_dtype > 2) { - strcpy(hrec, "missing"); - } else if (pcdi->ld_error & 1) { - strcpy(hrec, "fault"); - } else if (pcdi->ld_error & 2) { - strcpy(hrec, "invalid"); - k++; j--; - } else { - strcpy(hrec, "ok"); - } - - if (drv_no == i) { - size = sprintf(buffer+len, - "\n Number: \t%-2d \tStatus: \t%s\n", - drv_no, hrec); - len += size; pos = begin + len; - flag = TRUE; - no_mdrv = pcdi->cd_ldcnt; - if (no_mdrv > 1 || pcdi->ld_slave != -1) { - is_mirr = TRUE; - strcpy(hrec, "RAID-1"); - } else if (pcdi->ld_dtype == 0) { - strcpy(hrec, "Disk"); - } else if (pcdi->ld_dtype == 1) { - strcpy(hrec, "RAID-0"); - } else if (pcdi->ld_dtype == 2) { - strcpy(hrec, "Chain"); - } else { - strcpy(hrec, "???"); - } - size = sprintf(buffer+len, - " Capacity [MB]:\t%-6d \tType: \t%s\n", - pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize), - hrec); - len += size; pos = begin + len; - } else { size = sprintf(buffer+len, - " Slave Number: \t%-2d \tStatus: \t%s\n", - drv_no & 0x7fff, hrec); + " Grown Defects:\t%d\n", + pdef->sddc_cnt); len += size; pos = begin + len; } - drv_no = pcdi->ld_slave; - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - } while (drv_no != -1); - - if (is_mirr) { - size = sprintf(buffer+len, - " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n", - no_mdrv - j - k, k); - len += size; pos = begin + len; } - - if (!ha->hdr[i].is_arraydrv) - strcpy(hrec, "--"); - else - sprintf(hrec, "%d", ha->hdr[i].master_no); - size = sprintf(buffer+len, - " To Array Drv.:\t%s\n", hrec); - len += size; pos = begin + len; if (pos < offset) { len = 0; begin = pos; } if (pos > offset + length) goto stop_output; - } - gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); - - if (!flag) { - size = sprintf(buffer+len, "\n --\n"); - len += size; pos = begin + len; - } + } + } + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); - /* 4. about array drives */ - size = sprintf(buffer+len,"\nArray Drives:"); + if (!flag) { + size = sprintf(buffer+len, "\n --\n"); len += size; pos = begin + len; - flag = FALSE; + } - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); - if (!buf) - goto stop_output; - for (i = 0; i < MAX_LDRIVES; ++i) { - if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master)) - continue; - /* 4.a array drive info */ - TRACE2(("array_info() drive no %d\n",i)); - pai = (gdth_arrayinf_str *)buf; + /* 3. about logical drives */ + size = sprintf(buffer+len,"\nLogical Drives:"); + len += size; pos = begin + len; + flag = FALSE; + + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); + if (!buf) + goto stop_output; + for (i = 0; i < MAX_LDRIVES; ++i) { + if (!ha->hdr[i].is_logdrv) + continue; + drv_no = i; + j = k = 0; + is_mirr = FALSE; + do { + /* 3.a log. drive info */ + TRACE2(("cache_drv_info() drive no %d\n",drv_no)); + pcdi = (gdth_cdrinfo_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; 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 >= 0x020503 + 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 >= KERNEL_VERSION(2,6,0) gdth_do_req(scp, &gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status == S_OK) -#elif LINUX_VERSION_CODE >= 0x020322 + if (scp->sr_command->SCp.Status != S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - if (scp->SCp.Status == S_OK) + if (scp->SCp.Status != S_OK) #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status == S_OK) + if (scp.SCp.Status != S_OK) #endif { - if (pai->ai_state == 0) - strcpy(hrec, "idle"); - else if (pai->ai_state == 2) - strcpy(hrec, "build"); - else if (pai->ai_state == 4) - strcpy(hrec, "ready"); - else if (pai->ai_state == 6) - strcpy(hrec, "fail"); - else if (pai->ai_state == 8 || pai->ai_state == 10) - strcpy(hrec, "rebuild"); - else - strcpy(hrec, "error"); - if (pai->ai_ext_state & 0x10) - strcat(hrec, "/expand"); - else if (pai->ai_ext_state & 0x1) - strcat(hrec, "/patch"); + break; + } + pcdi->ld_dtype >>= 16; + j++; + if (pcdi->ld_dtype > 2) { + strcpy(hrec, "missing"); + } else if (pcdi->ld_error & 1) { + strcpy(hrec, "fault"); + } else if (pcdi->ld_error & 2) { + strcpy(hrec, "invalid"); + k++; j--; + } else { + strcpy(hrec, "ok"); + } + + if (drv_no == i) { size = sprintf(buffer+len, "\n Number: \t%-2d \tStatus: \t%s\n", - i,hrec); + drv_no, hrec); len += size; pos = begin + len; flag = TRUE; - - if (pai->ai_type == 0) + no_mdrv = pcdi->cd_ldcnt; + if (no_mdrv > 1 || pcdi->ld_slave != -1) { + is_mirr = TRUE; + strcpy(hrec, "RAID-1"); + } else if (pcdi->ld_dtype == 0) { + strcpy(hrec, "Disk"); + } else if (pcdi->ld_dtype == 1) { strcpy(hrec, "RAID-0"); - else if (pai->ai_type == 4) - strcpy(hrec, "RAID-4"); - else if (pai->ai_type == 5) - strcpy(hrec, "RAID-5"); - else - strcpy(hrec, "RAID-10"); + } else if (pcdi->ld_dtype == 2) { + strcpy(hrec, "Chain"); + } else { + strcpy(hrec, "???"); + } size = sprintf(buffer+len, " Capacity [MB]:\t%-6d \tType: \t%s\n", - pai->ai_size/(1024*1024/pai->ai_secsize), + pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize), hrec); len += size; pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; + } else { + size = sprintf(buffer+len, + " Slave Number: \t%-2d \tStatus: \t%s\n", + drv_no & 0x7fff, hrec); + len += size; pos = begin + len; } - } - gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); - - if (!flag) { - size = sprintf(buffer+len, "\n --\n"); + drv_no = pcdi->ld_slave; + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto stop_output; + } while (drv_no != -1); + + if (is_mirr) { + size = sprintf(buffer+len, + " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n", + no_mdrv - j - k, k); len += size; pos = begin + len; } - - /* 5. about host drives */ - size = sprintf(buffer+len,"\nHost Drives:"); + + if (!ha->hdr[i].is_arraydrv) + strcpy(hrec, "--"); + else + sprintf(hrec, "%d", ha->hdr[i].master_no); + size = sprintf(buffer+len, + " To Array Drv.:\t%s\n", hrec); len += size; pos = begin + len; - flag = FALSE; - - buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr); - if (!buf) + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) goto stop_output; - for (i = 0; i < MAX_LDRIVES; ++i) { - if (!ha->hdr[i].is_logdrv || - (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master)) - continue; - /* 5.a get host drive list */ - TRACE2(("host_get() drv_no %d\n",i)); - phg = (gdth_hget_str *)buf; - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_IOCTL; - 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 >= 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) + } + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); + + if (!flag) { + size = sprintf(buffer+len, "\n --\n"); + len += size; pos = begin + len; + } + + /* 4. about array drives */ + size = sprintf(buffer+len,"\nArray Drives:"); + len += size; pos = begin + len; + flag = FALSE; + + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); + if (!buf) + goto stop_output; + for (i = 0; i < MAX_LDRIVES; ++i) { + if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master)) + continue; + /* 4.a array drive info */ + TRACE2(("array_info() drive no %d\n",i)); + pai = (gdth_arrayinf_str *)buf; + gdtcmd.Service = CACHESERVICE; + gdtcmd.OpCode = GDT_IOCTL; + 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 >= KERNEL_VERSION(2,6,0) + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status == S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &gdtcmd, cmnd, 30); + if (scp->SCp.Status == S_OK) #else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status != S_OK) + gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); + if (scp.SCp.Status == S_OK) #endif - { - ha->hdr[i].ldr_no = i; - ha->hdr[i].rw_attribs = 0; - ha->hdr[i].start_sec = 0; - } else { - for (j = 0; j < phg->entries; ++j) { - k = phg->entry[j].host_drive; - if (k >= MAX_LDRIVES) - continue; - ha->hdr[k].ldr_no = phg->entry[j].log_drive; - ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs; - ha->hdr[k].start_sec = phg->entry[j].start_sec; - } - } - } - gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr); - - for (i = 0; i < MAX_HDRIVES; ++i) { - if (!(ha->hdr[i].present)) - continue; - + { + if (pai->ai_state == 0) + strcpy(hrec, "idle"); + else if (pai->ai_state == 2) + strcpy(hrec, "build"); + else if (pai->ai_state == 4) + strcpy(hrec, "ready"); + else if (pai->ai_state == 6) + strcpy(hrec, "fail"); + else if (pai->ai_state == 8 || pai->ai_state == 10) + strcpy(hrec, "rebuild"); + else + strcpy(hrec, "error"); + if (pai->ai_ext_state & 0x10) + strcat(hrec, "/expand"); + else if (pai->ai_ext_state & 0x1) + strcat(hrec, "/patch"); size = sprintf(buffer+len, - "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n", - i, ha->hdr[i].ldr_no); + "\n Number: \t%-2d \tStatus: \t%s\n", + i,hrec); len += size; pos = begin + len; flag = TRUE; + if (pai->ai_type == 0) + strcpy(hrec, "RAID-0"); + else if (pai->ai_type == 4) + strcpy(hrec, "RAID-4"); + else if (pai->ai_type == 5) + strcpy(hrec, "RAID-5"); + else + strcpy(hrec, "RAID-10"); size = sprintf(buffer+len, - " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n", - ha->hdr[i].size/2048, ha->hdr[i].start_sec); + " Capacity [MB]:\t%-6d \tType: \t%s\n", + pai->ai_size/(1024*1024/pai->ai_secsize), + hrec); len += size; pos = begin + len; if (pos < offset) { len = 0; @@ -1299,60 +708,125 @@ if (pos > offset + length) goto stop_output; } + } + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); - if (!flag) { - size = sprintf(buffer+len, "\n --\n"); - len += size; pos = begin + len; - } + if (!flag) { + size = sprintf(buffer+len, "\n --\n"); + len += size; pos = begin + len; } - /* controller events */ - size = sprintf(buffer+len,"\nController Events:\n"); + /* 5. about host drives */ + size = sprintf(buffer+len,"\nHost Drives:"); len += size; pos = begin + len; + flag = FALSE; - for (id = -1;;) { - id = gdth_read_event(ha, id, &estr); - if (estr.event_source == 0) - break; - if (estr.event_data.eu.driver.ionode == hanum && - estr.event_source == ES_ASYNC) { - gdth_log_event(&estr.event_data, hrec); - do_gettimeofday(&tv); - sec = (int)(tv.tv_sec - estr.first_stamp); - if (sec < 0) sec = 0; - size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n", - sec/3600, sec%3600/60, sec%60, hrec); - len += size; pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; + buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr); + if (!buf) + goto stop_output; + for (i = 0; i < MAX_LDRIVES; ++i) { + if (!ha->hdr[i].is_logdrv || + (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master)) + continue; + /* 5.a get host drive list */ + TRACE2(("host_get() drv_no %d\n",i)); + phg = (gdth_hget_str *)buf; + gdtcmd.Service = CACHESERVICE; + gdtcmd.OpCode = GDT_IOCTL; + 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 >= KERNEL_VERSION(2,6,0) + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status != S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &gdtcmd, cmnd, 30); + if (scp->SCp.Status != S_OK) +#else + gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); + if (scp.SCp.Status != S_OK) +#endif + { + ha->hdr[i].ldr_no = i; + ha->hdr[i].rw_attribs = 0; + ha->hdr[i].start_sec = 0; + } else { + for (j = 0; j < phg->entries; ++j) { + k = phg->entry[j].host_drive; + if (k >= MAX_LDRIVES) + continue; + ha->hdr[k].ldr_no = phg->entry[j].log_drive; + ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs; + ha->hdr[k].start_sec = phg->entry[j].start_sec; } - if (pos > offset + length) - goto stop_output; } - if (id == -1) - break; } -#ifdef GDTH_IOCTL_PROC - } else { - gdth_iord_str *piord; + gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr); - /* 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, GDTH_SCRATCH, ha->pscratch, paddr); - len = length; + for (i = 0; i < MAX_HDRIVES; ++i) { + if (!(ha->hdr[i].present)) + continue; + + size = sprintf(buffer+len, + "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n", + i, ha->hdr[i].ldr_no); + len += size; pos = begin + len; + flag = TRUE; + + size = sprintf(buffer+len, + " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n", + (ulong32)(ha->hdr[i].size/2048), ha->hdr[i].start_sec); + len += size; pos = begin + len; + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto stop_output; + } + + if (!flag) { + size = sprintf(buffer+len, "\n --\n"); + len += size; pos = begin + len; + } + } + + /* controller events */ + size = sprintf(buffer+len,"\nController Events:\n"); + len += size; pos = begin + len; + + for (id = -1;;) { + id = gdth_read_event(ha, id, &estr); + if (estr.event_source == 0) + break; + if (estr.event_data.eu.driver.ionode == hanum && + estr.event_source == ES_ASYNC) { + gdth_log_event(&estr.event_data, hrec); + do_gettimeofday(&tv); + sec = (int)(tv.tv_sec - estr.first_stamp); + if (sec < 0) sec = 0; + size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n", + sec/3600, sec%3600/60, sec%60, hrec); + len += size; pos = begin + len; + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto stop_output; + } + if (id == -1) + break; } -#endif stop_output: -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) scsi_release_request(scp); scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) scsi_release_command(scp); scsi_free_host_dev(sdev); #endif @@ -1365,7 +839,8 @@ return(len); } -#if LINUX_VERSION_CODE >= 0x020503 + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static void gdth_do_req(Scsi_Request *scp, gdth_cmd_str *gdtcmd, char *cmnd, int timeout) { @@ -1389,9 +864,9 @@ char *cmnd, int timeout) { unsigned bufflen; -#if LINUX_VERSION_CODE >= 0x020407 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) DECLARE_COMPLETION(wait); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) DECLARE_MUTEX_LOCKED(sem); #else struct semaphore sem = MUTEX_LOCKED; @@ -1405,19 +880,19 @@ scp->SCp.this_residual = DEFAULT_PRI; bufflen = 0; } -#if LINUX_VERSION_CODE >= 0x020407 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) 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); #else scp->request.sem = &sem; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); #else - GDTH_LOCK_SCSI_DOCMD(); + spin_lock_irq(&io_request_lock); scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); - GDTH_UNLOCK_SCSI_DOCMD(); + spin_unlock_irq(&io_request_lock); #endif down(&sem); #endif @@ -1428,11 +903,11 @@ { TRACE2(("gdth_scsi_done()\n")); -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) scp->request->rq_status = RQ_SCSI_DONE; if (scp->request->waiting != NULL) complete(scp->request->waiting); -#elif LINUX_VERSION_CODE >= 0x020407 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) scp->request.rq_status = RQ_SCSI_DONE; if (scp->request.waiting != NULL) complete(scp->request.waiting); @@ -1444,7 +919,7 @@ } static char *gdth_ioctl_alloc(int hanum, int size, int scratch, - ulong32 *paddr) + ulong64 *paddr) { gdth_ha_str *ha; ulong flags; @@ -1463,11 +938,11 @@ } else if (scratch) { ret_val = NULL; } else { -#if LINUX_VERSION_CODE >= 0x020400 - dma_addr_t dma_addr; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + dma_addr_t dma_addr; ret_val = pci_alloc_consistent(ha->pdev, size, &dma_addr); - *paddr = (ulong32)dma_addr; + *paddr = dma_addr; #else ret_val = scsi_init_malloc(size, GFP_ATOMIC | GFP_DMA); if (ret_val) @@ -1479,7 +954,7 @@ return ret_val; } -static void gdth_ioctl_free(int hanum, int size, char *buf, ulong32 paddr) +static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr) { gdth_ha_str *ha; ulong flags; @@ -1490,7 +965,7 @@ if (buf == ha->pscratch) { ha->scratch_busy = FALSE; } else { -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_free_consistent(ha->pdev, size, buf, paddr); #else scsi_init_free((void *)buf, size); @@ -1533,7 +1008,7 @@ for (i = 0; i < GDTH_MAXCMDS; ++i) { scp = ha->cmd_tab[i].cmnd; -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; #else @@ -1546,14 +1021,10 @@ GDTH_UNLOCK_HA(ha, flags); while (!scp->SCp.have_data_in) barrier(); -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 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); @@ -1576,7 +1047,7 @@ GDTH_LOCK_HA(ha, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; #else @@ -1602,7 +1073,7 @@ GDTH_LOCK_HA(ha, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; #else @@ -1624,7 +1095,6 @@ oldto = scp->timeout_per_command; scp->timeout_per_command = timeout; -#if LINUX_VERSION_CODE >= 0x02014B if (timeout == 0) { del_timer(&scp->eh_timeout); scp->eh_timeout.data = (unsigned long) NULL; @@ -1636,17 +1106,6 @@ scp->eh_timeout.expires = jiffies + timeout; add_timer(&scp->eh_timeout); } -#else - if (timeout > 0) { - if (timer_table[SCSI_TIMER].expires == 0) { - timer_table[SCSI_TIMER].expires = jiffies + timeout; - timer_active |= 1 << SCSI_TIMER; - } else { - if (jiffies + timeout < timer_table[SCSI_TIMER].expires) - timer_table[SCSI_TIMER].expires = jiffies + timeout; - } - } -#endif return oldto; } diff -Nru a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h --- a/drivers/scsi/gdth_proc.h Fri May 21 19:07:22 2004 +++ b/drivers/scsi/gdth_proc.h Fri May 21 19:07:22 2004 @@ -2,42 +2,31 @@ #define _GDTH_PROC_H /* gdth_proc.h - * $Id: gdth_proc.h,v 1.14 2003/08/27 11:37:35 achim Exp $ + * $Id: gdth_proc.h,v 1.16 2004/01/14 13:09:01 achim Exp $ */ -static int gdth_set_info(char *buffer,int length,int hanum,int busnum); -static int gdth_get_info(char *buffer,char **start,off_t offset, - int length,int hanum,int busnum); +static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, + int hanum,int busnum); +static int gdth_get_info(char *buffer,char **start,off_t offset,int length, + struct Scsi_Host *host,int hanum,int busnum); -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 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 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) 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 #endif 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 + ulong64 *paddr); +static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr); 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); diff -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c --- a/drivers/scsi/nsp32.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/nsp32.c Fri May 21 19:07:22 2004 @@ -38,7 +38,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c --- a/drivers/scsi/qlogicfas408.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/qlogicfas408.c Fri May 21 19:07:22 2004 @@ -538,7 +538,7 @@ * Return info string */ -char *qlogicfas408_info(struct Scsi_Host *host) +const char *qlogicfas408_info(struct Scsi_Host *host) { struct qlogicfas408_priv *priv = get_priv_by_host(host); return priv->qinfo; diff -Nru a/drivers/scsi/qlogicfas408.h b/drivers/scsi/qlogicfas408.h --- a/drivers/scsi/qlogicfas408.h Fri May 21 19:07:22 2004 +++ b/drivers/scsi/qlogicfas408.h Fri May 21 19:07:22 2004 @@ -111,7 +111,7 @@ int qlogicfas408_bus_reset(Scsi_Cmnd * cmd); int qlogicfas408_host_reset(Scsi_Cmnd * cmd); int qlogicfas408_device_reset(Scsi_Cmnd * cmd); -char *qlogicfas408_info(struct Scsi_Host *host); +const char *qlogicfas408_info(struct Scsi_Host *host); int qlogicfas408_get_chip_type(int qbase, int int_type); void qlogicfas408_setup(int qbase, int id, int int_type); int qlogicfas408_detect(int qbase, int int_type); diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/scsi_lib.c Fri May 21 19:07:22 2004 @@ -1610,7 +1610,9 @@ case SDEV_CANCEL: switch (oldstate) { + case SDEV_CREATED: case SDEV_RUNNING: + case SDEV_OFFLINE: break; default: goto illegal; @@ -1619,9 +1621,7 @@ case SDEV_DEL: switch (oldstate) { - case SDEV_CREATED: case SDEV_CANCEL: - case SDEV_OFFLINE: break; default: goto illegal; diff -Nru a/drivers/scsi/scsi_logging.h b/drivers/scsi/scsi_logging.h --- a/drivers/scsi/scsi_logging.h Fri May 21 19:07:22 2004 +++ b/drivers/scsi/scsi_logging.h Fri May 21 19:07:22 2004 @@ -46,7 +46,7 @@ #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) \ { \ - if ((SCSI_LOG_LEVEL(SHIFT, BITS)) > (LEVEL)) \ + if (unlikely((SCSI_LOG_LEVEL(SHIFT, BITS)) > (LEVEL))) \ (CMD); \ } #else diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/scsi_scan.c Fri May 21 19:07:22 2004 @@ -80,7 +80,6 @@ MODULE_PARM_DESC(max_luns, "last scsi LUN (should be between 1 and 2^32-1)"); -#ifdef CONFIG_SCSI_REPORT_LUNS /* * max_scsi_report_luns: the maximum number of LUNS that will be * returned from the REPORT LUNS command. 8 times this value must @@ -88,13 +87,19 @@ * in practice, the maximum number of LUNs suppored by any device * is about 16k. */ -static unsigned int max_scsi_report_luns = 128; +static unsigned int max_scsi_report_luns = 511; module_param_named(max_report_luns, max_scsi_report_luns, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(max_report_luns, "REPORT LUNS maximum number of LUNS received (should be" " between 1 and 16384)"); -#endif + +static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ+3; + +module_param_named(inq_timeout, scsi_inq_timeout, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(inq_timeout, + "Timeout (in seconds) waiting for devices to answer INQUIRY." + " Default is 5. Some non-compliant devices need more."); /** * scsi_unlock_floptical - unlock device via a special MODE SENSE command @@ -212,6 +217,11 @@ INIT_LIST_HEAD(&sdev->starved_entry); spin_lock_init(&sdev->list_lock); + + /* if the device needs this changing, it may do so in the + * slave_configure function */ + sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED; + /* * Some low level driver could use device->type */ @@ -346,7 +356,7 @@ memset(inq_result, 0, 36); scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, 36, - SCSI_TIMEOUT + 4 * HZ, 3); + HZ/2 + HZ*scsi_inq_timeout, 3); SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: 1st INQUIRY %s with" " code 0x%x\n", sreq->sr_result ? @@ -400,7 +410,7 @@ memset(inq_result, 0, possible_inq_resp_len); scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, - possible_inq_resp_len, SCSI_TIMEOUT + 4 * HZ, 3); + possible_inq_resp_len, (1+scsi_inq_timeout)*(HZ/2), 3); SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: 2nd INQUIRY" " %s with code 0x%x\n", sreq->sr_result ? "failed" : "successful", sreq->sr_result)); @@ -628,10 +638,6 @@ spin_unlock_irqrestore(sdev->host->host_lock, flags); } - /* if the device needs this changing, it may do so in the detect - * function */ - sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED; - sdev->use_10_for_rw = 1; if (*bflags & BLIST_MS_SKIP_PAGE_08) @@ -863,7 +869,6 @@ return; } -#ifdef CONFIG_SCSI_REPORT_LUNS /** * scsilun_to_int: convert a scsi_lun to an int * @scsilun: struct scsi_lun to be converted. @@ -924,9 +929,14 @@ u8 *data; /* - * Only support SCSI-3 and up devices. - */ - if (sdev->scsi_level < SCSI_3) + * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set. + * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does + * support more than 8 LUNs. + */ + if ((bflags & BLIST_NOREPORTLUN) || + sdev->scsi_level < SCSI_2 || + (sdev->scsi_level < SCSI_3 && + (!(bflags & BLIST_REPORTLUN2) || sdev->host->max_lun <= 8)) ) return 1; if (bflags & BLIST_NOLUN) return 0; @@ -1090,9 +1100,6 @@ printk(ALLOC_FAILURE_MSG, __FUNCTION__); return 0; } -#else -# define scsi_report_lun_scan(sdev, blags, rescan) (1) -#endif /* CONFIG_SCSI_REPORT_LUNS */ struct scsi_device *scsi_add_device(struct Scsi_Host *shost, uint channel, uint id, uint lun) diff -Nru a/drivers/scsi/scsiiom.c b/drivers/scsi/scsiiom.c --- a/drivers/scsi/scsiiom.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/scsiiom.c Fri May 21 19:07:22 2004 @@ -227,7 +227,7 @@ #if DMA_INT UCHAR dstatus; #endif - DC390_AFLAGS DC390_IFLAGS; //DC390_DFLAGS + DC390_IFLAGS; pACB = (PACB)dev_id; for (pACB2 = dc390_pACB_start; (pACB2 && pACB2 != pACB); pACB2 = pACB2->pNextACB); @@ -237,26 +237,21 @@ return IRQ_NONE; } - //DC390_LOCK_DRV; - sstatus = DC390_read8 (Scsi_Status); if( !(sstatus & INTERRUPT) ) - { /*DC390_UNLOCK_DRV;*/ return IRQ_NONE; }; + return IRQ_NONE; DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus)); #if DMA_INT DC390_LOCK_IO(pACB->pScsiHost); - DC390_LOCK_ACB; dstatus = dc390_dma_intr (pACB); - DC390_UNLOCK_ACB; DC390_UNLOCK_IO(pACB->pScsiHost); DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus)); if (! (dstatus & SCSI_INTERRUPT)) { DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n")); - //DC390_UNLOCK_DRV; return IRQ_NONE; }; #else @@ -266,8 +261,6 @@ #endif DC390_LOCK_IO(pACB->pScsiHost); - DC390_LOCK_ACB; - //DC390_UNLOCK_DRV_NI; /* Allow _other_ CPUs to process IRQ (useful for shared IRQs) */ istate = DC390_read8 (Intern_State); istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */ @@ -339,10 +332,7 @@ } unlock: - //DC390_LOCK_DRV_NI; - DC390_UNLOCK_ACB; DC390_UNLOCK_IO(pACB->pScsiHost); - //DC390_UNLOCK_DRV; /* Restore initial flags */ return IRQ_HANDLED; } @@ -521,7 +511,7 @@ { DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ - } + } } static void @@ -740,9 +730,9 @@ psgl = pSRB->pSegmentList; //dc390_pci_sync(pSRB); - while (pSRB->TotalXferredLen + (ULONG) psgl->length < pSRB->Saved_Ptr) + while (pSRB->TotalXferredLen + (ULONG) sg_dma_len(psgl) < pSRB->Saved_Ptr) { - pSRB->TotalXferredLen += (ULONG) psgl->length; + pSRB->TotalXferredLen += (ULONG) sg_dma_len(psgl); pSRB->SGIndex++; if( pSRB->SGIndex < pSRB->SGcount ) { @@ -762,7 +752,7 @@ } else if(pcmd->request_buffer) { //dc390_pci_sync(pSRB); - pSRB->Segmentx.length = pcmd->request_bufflen - pSRB->Saved_Ptr; + sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen - pSRB->Saved_Ptr; pSRB->SGcount = 1; pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; } else { @@ -885,6 +875,8 @@ if (pDCB) printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN); else printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n"); + + pSRB->pSRBDCB = pDCB; dc390_EnableMsgOut_Abort (pACB, pSRB); if (pDCB) pDCB->DCBFlag |= ABORT_DEV; return; @@ -1150,7 +1142,6 @@ pSRB = psrb; } pDCB->pGoingSRB = 0; - dc390_Query_to_Waiting (pACB); dc390_Waiting_process (pACB); } else @@ -1466,7 +1457,7 @@ ptr2 = pSRB->pSegmentList; for( i=pSRB->SGIndex; i < bval; i++) { - swlval += ptr2->length; + swlval += sg_dma_len(ptr2); ptr2++; } REMOVABLEDEBUG(printk(KERN_INFO "XferredLen=%08x,NotXferLen=%08x\n",\ @@ -1619,20 +1610,15 @@ pACB->scan_devices = 0; }; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,30) pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen; -#endif if (!DCB_removed) dc390_Going_remove (pDCB, pSRB); /* Add to free list */ dc390_Free_insert (pACB, pSRB); DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid)); - DC390_UNLOCK_ACB_NI; pcmd->scsi_done (pcmd); - DC390_LOCK_ACB_NI; - dc390_Query_to_Waiting (pACB); dc390_Waiting_process (pACB); return; } @@ -1668,9 +1654,7 @@ /* ReleaseSRB( pDCB, pSRB ); */ DEBUG0(printk (KERN_DEBUG "DC390: DoingSRB_Done: done pid %li\n", pcmd->pid)); - DC390_UNLOCK_ACB_NI; pcmd->scsi_done( pcmd ); - DC390_LOCK_ACB_NI; #endif psrb = psrb2; } @@ -1679,7 +1663,6 @@ pdcb->TagMask = 0; pdcb = pdcb->pNextDCB; } while( pdcb != pDCB ); - dc390_Query_to_Waiting (pACB); } diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c --- a/drivers/scsi/sg.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/sg.c Fri May 21 19:07:22 2004 @@ -7,7 +7,7 @@ * Original driver (sg.c): * Copyright (C) 1992 Lawrence Foard * Version 2 and 3 extensions to driver: - * Copyright (C) 1998 - 2002 Douglas Gilbert + * Copyright (C) 1998 - 2004 Douglas Gilbert * * Modified 19-JAN-1998 Richard Gooch Devfs support * @@ -17,27 +17,18 @@ * any later version. * */ -#include -static int sg_version_num = 30530; /* 2 digits for each component */ + +static int sg_version_num = 30531; /* 2 digits for each component */ +#define SG_VERSION_STR "3.5.31" + /* * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First * the kernel/module needs to be built with CONFIG_SCSI_LOGGING * (otherwise the macros compile to empty statements). - * Then before running the program to be debugged enter: - * # echo "scsi log timeout 7" > /proc/scsi/scsi - * This will send copious output to the console and the log which - * is usually /var/log/messages. To turn off debugging enter: - * # echo "scsi log timeout 0" > /proc/scsi/scsi - * The 'timeout' token was chosen because it is relatively unused. - * The token 'hlcomplete' should be used but that triggers too - * much output from the sd device driver. To dump the current - * state of the SCSI mid level data structures enter: - * # echo "scsi dump 1" > /proc/scsi/scsi - * To dump the state of sg's data structures use: - * # cat /proc/scsi/sg/debug * */ +#include #include #include @@ -69,7 +60,7 @@ #ifdef CONFIG_SCSI_PROC_FS #include -static char *sg_version_str = "3.5.30 [20040124]"; +static char *sg_version_date = "20040513"; static int sg_proc_init(void); static void sg_proc_cleanup(void); @@ -110,7 +101,7 @@ #define SG_SECTOR_SZ 512 #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1) -#define SG_DEV_ARR_LUMP 6 /* amount to over allocate sg_dev_arr by */ +#define SG_DEV_ARR_LUMP 32 /* amount to over allocate sg_dev_arr by */ static int sg_add(struct class_device *); static void sg_remove(struct class_device *); @@ -1333,85 +1324,44 @@ static int sg_sysfs_valid = 0; -static int -sg_add(struct class_device *cl_dev) +static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) { - struct scsi_device *scsidp = to_scsi_device(cl_dev->dev); - struct gendisk *disk; - Sg_device *sdp = NULL; + Sg_device *sdp; unsigned long iflags; - struct cdev * cdev = NULL; + void *old_sg_dev_arr = NULL; int k, error; - disk = alloc_disk(1); - if (!disk) + sdp = vmalloc(sizeof(Sg_device)); + if (!sdp) return -ENOMEM; - cdev = cdev_alloc(); - if (! cdev) - return -ENOMEM; write_lock_irqsave(&sg_dev_arr_lock, iflags); - if (sg_nr_dev >= sg_dev_max) { /* try to resize */ + if (unlikely(sg_nr_dev >= sg_dev_max)) { /* try to resize */ Sg_device **tmp_da; int tmp_dev_max = sg_nr_dev + SG_DEV_ARR_LUMP; - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - tmp_da = (Sg_device **)vmalloc( - tmp_dev_max * sizeof(Sg_device *)); - if (NULL == tmp_da) { - printk(KERN_ERR - "sg_add: device array cannot be resized\n"); - error = -ENOMEM; - goto out; - } + + tmp_da = vmalloc(tmp_dev_max * sizeof(Sg_device *)); + if (unlikely(!tmp_da)) + goto expand_failed; + write_lock_irqsave(&sg_dev_arr_lock, iflags); - memset(tmp_da, 0, tmp_dev_max * sizeof (Sg_device *)); - memcpy(tmp_da, sg_dev_arr, - sg_dev_max * sizeof (Sg_device *)); - vfree((char *) sg_dev_arr); + memset(tmp_da, 0, tmp_dev_max * sizeof(Sg_device *)); + memcpy(tmp_da, sg_dev_arr, sg_dev_max * sizeof(Sg_device *)); + old_sg_dev_arr = sg_dev_arr; sg_dev_arr = tmp_da; sg_dev_max = tmp_dev_max; } -find_empty_slot: for (k = 0; k < sg_dev_max; k++) if (!sg_dev_arr[k]) break; - if (k >= SG_MAX_DEVS) { - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - printk(KERN_WARNING - "Unable to attach sg device <%d, %d, %d, %d>" - " type=%d, minor number exceeds %d\n", - scsidp->host->host_no, scsidp->channel, scsidp->id, - scsidp->lun, scsidp->type, SG_MAX_DEVS - 1); - if (NULL != sdp) - vfree((char *) sdp); - error = -ENODEV; - goto out; - } - if (k < sg_dev_max) { - if (NULL == sdp) { - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - sdp = (Sg_device *)vmalloc(sizeof(Sg_device)); - write_lock_irqsave(&sg_dev_arr_lock, iflags); - if (!sg_dev_arr[k]) - goto find_empty_slot; - } - } else - sdp = NULL; - if (NULL == sdp) { - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - printk(KERN_ERR "sg_add: Sg_device cannot be allocated\n"); - error = -ENOMEM; - goto out; - } + if (unlikely(k >= SG_MAX_DEVS)) + goto overflow; - SCSI_LOG_TIMEOUT(3, printk("sg_add: dev=%d \n", k)); memset(sdp, 0, sizeof(*sdp)); + SCSI_LOG_TIMEOUT(3, printk("sg_alloc: dev=%d \n", k)); sprintf(disk->disk_name, "sg%d", k); - cdev->owner = THIS_MODULE; - cdev->ops = &sg_fops; - disk->major = SCSI_GENERIC_MAJOR; disk->first_minor = k; sdp->disk = disk; sdp->device = scsidp; @@ -1421,6 +1371,55 @@ sg_nr_dev++; sg_dev_arr[k] = sdp; write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + error = k; + + out: + if (error < 0) + vfree(sdp); + vfree(old_sg_dev_arr); + return error; + + expand_failed: + printk(KERN_ERR "sg_alloc: device array cannot be resized\n"); + error = -ENOMEM; + goto out; + + overflow: + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + printk(KERN_WARNING + "Unable to attach sg device <%d, %d, %d, %d> type=%d, minor " + "number exceeds %d\n", scsidp->host->host_no, scsidp->channel, + scsidp->id, scsidp->lun, scsidp->type, SG_MAX_DEVS - 1); + error = -ENODEV; + goto out; +} + +static int +sg_add(struct class_device *cl_dev) +{ + struct scsi_device *scsidp = to_scsi_device(cl_dev->dev); + struct gendisk *disk; + Sg_device *sdp = NULL; + struct cdev * cdev = NULL; + int error, k; + + disk = alloc_disk(1); + if (!disk) + return -ENOMEM; + disk->major = SCSI_GENERIC_MAJOR; + + error = -ENOMEM; + cdev = cdev_alloc(); + if (!cdev) + goto out; + cdev->owner = THIS_MODULE; + cdev->ops = &sg_fops; + + error = sg_alloc(disk, scsidp); + if (error < 0) + goto out; + k = error; + sdp = sg_dev_arr[k]; devfs_mk_cdev(MKDEV(SCSI_GENERIC_MAJOR, k), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, @@ -1543,6 +1542,7 @@ MODULE_AUTHOR("Douglas Gilbert"); MODULE_DESCRIPTION("SCSI generic (sg) driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(SG_VERSION_STR); MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd"); MODULE_PARM_DESC(allow_dio, "allow direct I/O (default: 0 (disallow))"); @@ -2844,7 +2844,8 @@ static int sg_proc_seq_show_version(struct seq_file *s, void *v) { - seq_printf(s, "%d\t%s\n", sg_version_num, sg_version_str); + seq_printf(s, "%d\t%s [%s]\n", sg_version_num, SG_VERSION_STR, + sg_version_date); return 0; } diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/st.c Fri May 21 19:07:22 2004 @@ -486,7 +486,7 @@ tape_name(STp), forward ? "forward" : "backward")); SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, - STp->timeout, MAX_RETRIES, TRUE); + STp->device->timeout, MAX_RETRIES, TRUE); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -544,7 +544,7 @@ cmd[4] = blks; SRpnt = st_do_scsi(NULL, STp, cmd, transfer, SCSI_DATA_WRITE, - STp->timeout, MAX_WRITE_RETRIES, TRUE); + STp->device->timeout, MAX_WRITE_RETRIES, TRUE); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -867,7 +867,7 @@ memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE); cmd[0] = READ_BLOCK_LIMITS; - SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, SCSI_DATA_READ, STp->timeout, + SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, SCSI_DATA_READ, STp->device->timeout, MAX_READY_RETRIES, TRUE); if (!SRpnt) { retval = (STp->buffer)->syscall_result; @@ -894,7 +894,7 @@ cmd[0] = MODE_SENSE; cmd[4] = 12; - SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, SCSI_DATA_READ, STp->timeout, + SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, SCSI_DATA_READ, STp->device->timeout, MAX_READY_RETRIES, TRUE); if (!SRpnt) { retval = (STp->buffer)->syscall_result; @@ -1116,7 +1116,7 @@ cmd[4] = 1 + STp->two_fm; SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, - STp->timeout, MAX_WRITE_RETRIES, TRUE); + STp->device->timeout, MAX_WRITE_RETRIES, TRUE); if (!SRpnt) { result = (STp->buffer)->syscall_result; goto out; @@ -1509,7 +1509,7 @@ cmd[4] = blks; SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE, - STp->timeout, MAX_WRITE_RETRIES, !async_write); + STp->device->timeout, MAX_WRITE_RETRIES, !async_write); if (!SRpnt) { retval = STbp->syscall_result; goto out; @@ -1679,7 +1679,7 @@ SRpnt = *aSRpnt; SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, SCSI_DATA_READ, - STp->timeout, MAX_RETRIES, TRUE); + STp->device->timeout, MAX_RETRIES, TRUE); release_buffering(STp); *aSRpnt = SRpnt; if (!SRpnt) @@ -2081,7 +2081,7 @@ DEBC( printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name, (value & ~MT_ST_SET_LONG_TIMEOUT))); } else { - STp->timeout = value * HZ; + STp->device->timeout = value * HZ; DEBC( printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n", name, value) ); } @@ -2189,7 +2189,7 @@ cmd[4] = 255; SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, - STp->timeout, 0, TRUE); + STp->device->timeout, 0, TRUE); if (SRpnt == NULL) return (STp->buffer)->syscall_result; @@ -2220,7 +2220,7 @@ (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR; SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, - (slow ? STp->long_timeout : STp->timeout), 0, TRUE); + (slow ? STp->long_timeout : STp->device->timeout), 0, TRUE); if (SRpnt == NULL) return (STp->buffer)->syscall_result; @@ -2332,7 +2332,7 @@ } if (STp->immediate) { cmd[1] = 1; /* Don't wait for completion */ - timeout = STp->timeout; + timeout = STp->device->timeout; } else timeout = STp->long_timeout; @@ -2512,7 +2512,7 @@ cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; - timeout = STp->timeout; + timeout = STp->device->timeout; DEBC( if (cmd_in == MTWEOF) printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name, @@ -2530,7 +2530,7 @@ cmd[0] = REZERO_UNIT; if (STp->immediate) { cmd[1] = 1; /* Don't wait for completion */ - timeout = STp->timeout; + timeout = STp->device->timeout; } DEBC(printk(ST_DEB_MSG "%s: Rewinding tape.\n", name)); fileno = blkno = at_sm = 0; @@ -2543,7 +2543,7 @@ cmd[0] = START_STOP; if (STp->immediate) { cmd[1] = 1; /* Don't wait for completion */ - timeout = STp->timeout; + timeout = STp->device->timeout; } cmd[4] = 3; DEBC(printk(ST_DEB_MSG "%s: Retensioning tape.\n", name)); @@ -2576,7 +2576,7 @@ cmd[1] = (arg ? 1 : 0); /* Long erase with non-zero argument */ if (STp->immediate) { cmd[1] |= 2; /* Don't wait for completion */ - timeout = STp->timeout; + timeout = STp->device->timeout; } else timeout = STp->long_timeout * 8; @@ -2628,7 +2628,7 @@ (STp->buffer)->b_data[9] = (ltmp >> 16); (STp->buffer)->b_data[10] = (ltmp >> 8); (STp->buffer)->b_data[11] = ltmp; - timeout = STp->timeout; + timeout = STp->device->timeout; DEBC( if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) printk(ST_DEB_MSG @@ -2809,7 +2809,7 @@ if (!logical && !STp->scsi2_logical) scmd[1] = 1; } - SRpnt = st_do_scsi(NULL, STp, scmd, 20, SCSI_DATA_READ, STp->timeout, + SRpnt = st_do_scsi(NULL, STp, scmd, 20, SCSI_DATA_READ, STp->device->timeout, MAX_READY_RETRIES, TRUE); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -2911,7 +2911,7 @@ } if (STp->immediate) { scmd[1] |= 1; /* Don't wait for completion */ - timeout = STp->timeout; + timeout = STp->device->timeout; } SRpnt = st_do_scsi(NULL, STp, scmd, 0, SCSI_DATA_NONE, @@ -3408,11 +3408,17 @@ goto out; } up(&STp->lock); - i = scsi_cmd_ioctl(STp->disk, cmd_in, arg); - if (i != -ENOTTY) - return i; - else - return scsi_ioctl(STp->device, cmd_in, (void *) arg); + switch (cmd_in) { + case SCSI_IOCTL_GET_IDLUN: + case SCSI_IOCTL_GET_BUS_NUMBER: + break; + default: + i = scsi_cmd_ioctl(STp->disk, cmd_in, arg); + if (i != -ENOTTY) + return i; + break; + } + return scsi_ioctl(STp->device, cmd_in, (void *) arg); out: up(&STp->lock); @@ -3832,7 +3838,7 @@ tpnt->partition = 0; tpnt->new_partition = 0; tpnt->nbr_partitions = 0; - tpnt->timeout = ST_TIMEOUT; + tpnt->device->timeout = ST_TIMEOUT; tpnt->long_timeout = ST_LONG_TIMEOUT; tpnt->try_dio = try_direct_io && !SDp->host->unchecked_isa_dma; diff -Nru a/drivers/scsi/st.h b/drivers/scsi/st.h --- a/drivers/scsi/st.h Fri May 21 19:07:22 2004 +++ b/drivers/scsi/st.h Fri May 21 19:07:22 2004 @@ -100,7 +100,6 @@ unsigned char c_algo; /* compression algorithm */ unsigned char pos_unknown; /* after reset position unknown */ int tape_type; - int timeout; /* timeout for normal commands */ int long_timeout; /* timeout for commands known to take long time */ unsigned long max_pfn; /* the maximum page number reachable by the HBA */ diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c --- a/drivers/scsi/tmscsim.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/tmscsim.c Fri May 21 19:07:22 2004 @@ -168,6 +168,10 @@ * 2.1a 03/11/29 GL, KG Initial fixing for 2.6. Convert to * * use the current PCI-mapping API, update * * command-queuing. * + * 2.1b 04/04/13 GL Fix for 64-bit platforms * + * 2.1b1 04/01/31 GL (applied 05.04) Remove internal * + * command-queuing. * + * 2.1b2 04/02/01 CH (applied 05.04) Fix error-handling * ***********************************************************************/ /* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */ @@ -260,16 +264,10 @@ * undef : traditional save_flags; cli; restore_flags; */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30) -# include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) -# include -#else -# include -#endif -#endif +#include +#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,99) && defined(MODULE) +#if defined(MODULE) static struct pci_device_id tmscsim_pci_tbl[] = { { .vendor = PCI_VENDOR_ID_AMD, @@ -283,9 +281,7 @@ #endif #define USE_SPINLOCKS 1 -#define NEW_PCI 1 -#define DC390_AFLAGS #define DC390_IFLAGS unsigned long iflags #define DC390_DFLAGS unsigned long dflags spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED; @@ -295,11 +291,6 @@ #define DC390_UNLOCK_DRV spin_unlock_irqrestore (&dc390_drvlock, dflags) #define DC390_LOCK_DRV_NI spin_lock (&dc390_drvlock) #define DC390_UNLOCK_DRV_NI spin_unlock (&dc390_drvlock) -#define DC390_LOCK_ACB /* DC390_LOCK_IO */ -#define DC390_UNLOCK_ACB /* DC390_UNLOCK_IO */ -#define DC390_LOCK_ACB_NI /* spin_lock (&(pACB->lock)) */ -#define DC390_UNLOCK_ACB_NI /* spin_unlock (&(pACB->lock)) */ -#define DC390_LOCKA_INIT /* DC390_LOCKA_INIT */ /* These macros are used for uniform access to 2.0.x and 2.1.x PCI config space*/ @@ -361,10 +352,6 @@ static int DC390_release(struct Scsi_Host *host); static int dc390_shutdown (struct Scsi_Host *host); - -//static PSHT dc390_pSHT_start = NULL; -//static PSH dc390_pSH_start = NULL; -//static PSH dc390_pSH_current = NULL; static PACB dc390_pACB_start= NULL; static PACB dc390_pACB_current = NULL; static ULONG dc390_lastabortedpid = 0; @@ -374,12 +361,9 @@ /* Startup values, to be overriden on the commandline */ int tmscsim[] = {-2, -2, -2, -2, -2, -2}; -# if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30) +#if defined(MODULE) MODULE_PARM(tmscsim, "1-6i"); MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)"); -# endif - -#if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30) MODULE_AUTHOR("C.L. Huang / Kurt Garloff"); MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters"); MODULE_LICENSE("GPL"); @@ -448,13 +432,6 @@ UCHAR dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20}; UCHAR dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20}; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,30) -struct proc_dir_entry DC390_proc_scsi_tmscsim ={ - PROC_SCSI_DC390T, 7 ,"tmscsim", - S_IFDIR | S_IRUGO | S_IXUGO, 2 - }; -#endif - /*********************************************************************** * Functions for access to DC390 EEPROM * and some to emulate it @@ -549,7 +526,6 @@ /* Override defaults on cmdline: * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped) */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13) int __init dc390_setup (char *str) { int ints[8]; @@ -570,24 +546,6 @@ __setup("tmscsim=", dc390_setup); #endif -#else -void __init dc390_setup (char *str, int *ints) -{ - int i, im; - im = ints[0]; - if (im > 6) - { - printk (KERN_NOTICE "DC390: ignore extra params!\n"); - im = 6; - } - for (i = 0; i < im; i++) - tmscsim[i] = ints[i+1]; - /* dc390_checkparams (); */ -} -#endif - - - static void __init dc390_EEpromOutDI( PDEVDECL, PUCHAR regval, UCHAR Carry ) { UCHAR bval; @@ -751,37 +709,6 @@ return q; } #endif - - -/* Append to Query List */ -static void dc390_Query_append( PSCSICMD cmd, PACB pACB ) -{ - dc390_cmd_scp_t *cmdq = (dc390_cmd_scp_t *)&cmd->SCp; - - DEBUG0(printk ("DC390: Append cmd %li to Query\n", cmd->pid)); - - list_add_tail(&cmdq->list, &pACB->cmdq); - pACB->QueryCnt++; - pACB->CmdOutOfSRB++; -} - - -/* Return next cmd from Query list */ -static PSCSICMD dc390_Query_get ( PACB pACB ) -{ - PSCSICMD pcmd; - dc390_cmd_scp_t *cmdq; - if (list_empty(&pACB->cmdq)) - return NULL; - - pcmd = (PSCSICMD) list_entry(pACB->cmdq.next, struct scsi_cmnd_list, scp.list); - DEBUG0(printk ("DC390: Get cmd %li from Query\n", pcmd->pid)); - cmdq = (dc390_cmd_scp_t *)&pcmd->SCp; - list_del(&cmdq->list); - pACB->QueryCnt--; - return pcmd; -} - /* Return next free SRB */ static __inline__ PSRB dc390_Free_get ( PACB pACB ) @@ -891,16 +818,6 @@ dc390_Going_append (pDCB, pSRB); } -/* 2.0 timer compatibility */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,30) - static inline int timer_pending(struct timer_list * timer) - { - return timer->prev != NULL; - } - #define time_after(a,b) ((long)(b) - (long)(a) < 0) - #define time_before(a,b) time_after(b,a) -#endif - void DC390_waiting_timed_out (unsigned long ptr); /* Sets the timer to wake us up */ static void dc390_waiting_timer (PACB pACB, unsigned long to) @@ -958,12 +875,9 @@ { PACB pACB = (PACB)ptr; DC390_IFLAGS; - DC390_AFLAGS; DEBUG0(printk ("DC390: Debug: Waiting queue woken up by timer!\n")); DC390_LOCK_IO(pACB->pScsiHost); - DC390_LOCK_ACB; dc390_Waiting_process (pACB); - DC390_UNLOCK_ACB; DC390_UNLOCK_IO(pACB->pScsiHost); } @@ -1022,7 +936,7 @@ pci_map_page(pdev, virt_to_page(pcmd->sense_buffer), (unsigned long)pcmd->sense_buffer & ~PAGE_MASK, sizeof(pcmd->sense_buffer), DMA_FROM_DEVICE); - pSRB->Segmentx.length = sizeof(pcmd->sense_buffer); + sg_dma_len(&pSRB->Segmentx) = sizeof(pcmd->sense_buffer); pSRB->SGcount = 1; pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __FUNCTION__, pcmd->sense_buffer, cmdp->saved_dma_handle)); @@ -1043,7 +957,7 @@ (unsigned long)pcmd->request_buffer & ~PAGE_MASK, pcmd->request_bufflen, scsi_to_pci_dma_dir(pcmd->sc_data_direction)); /* TODO: error handling */ - pSRB->Segmentx.length = pcmd->request_bufflen; + sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen; pSRB->SGcount = 1; pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; DEBUG1(printk("%s(): Mapped request buffer %p at %x\n", __FUNCTION__, pcmd->request_buffer, cmdp->saved_dma_handle)); @@ -1113,37 +1027,6 @@ /* KG: deferred PCI mapping to dc390_StartSCSI */ } -/* Put cmnd from Query to Waiting list and send next Waiting cmnd */ -static void dc390_Query_to_Waiting (PACB pACB) -{ - Scsi_Cmnd *pcmd; - PSRB pSRB; - PDCB pDCB; - - if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) - return; - - while (pACB->QueryCnt) - { - pSRB = dc390_Free_get ( pACB ); - if (!pSRB) return; - pcmd = dc390_Query_get ( pACB ); - if (!pcmd) { dc390_Free_insert (pACB, pSRB); return; } /* should not happen */ - pDCB = dc390_findDCB (pACB, pcmd->device->id, pcmd->device->lun); - if (!pDCB) - { - dc390_Free_insert (pACB, pSRB); - printk (KERN_ERR "DC390: Command in queue to non-existing device!\n"); - pcmd->result = MK_RES(DRIVER_ERROR,DID_ERROR,0,0); - DC390_UNLOCK_ACB_NI; - pcmd->done (pcmd); - DC390_LOCK_ACB_NI; - } - dc390_BuildSRB (pcmd, pDCB, pSRB); - dc390_Waiting_append ( pDCB, pSRB ); - } -} - /*********************************************************************** * Function : static int DC390_queue_command (Scsi_Cmnd *cmd, * void (*done)(Scsi_Cmnd *)) @@ -1168,19 +1051,12 @@ PDCB pDCB; PSRB pSRB; PACB pACB = (PACB) cmd->device->host->hostdata; - DC390_AFLAGS; - DEBUG0(/* if(pACB->scan_devices) */ \ printk(KERN_INFO "DC390: Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li), buffer=%p\n",\ cmd->cmnd[0],cmd->device->id,cmd->device->lun,cmd->pid, cmd->buffer)); - DC390_LOCK_ACB; - - /* Assume BAD_TARGET; will be cleared later */ - cmd->result = DID_BAD_TARGET << 16; - - /* TODO: Change the policy: Alway accept TEST_UNIT_READY or INQUIRY + /* TODO: Change the policy: Always accept TEST_UNIT_READY or INQUIRY * commands and alloc a DCB for the device if not yet there. DCB will * be removed in dc390_SRBdone if SEL_TIMEOUT */ @@ -1190,17 +1066,6 @@ else if( (pACB->scan_devices) && (cmd->cmnd[0] == READ_6) ) pACB->scan_devices = 0; - if ( ( cmd->device->id >= pACB->pScsiHost->max_id ) || - (cmd->device->lun >= pACB->pScsiHost->max_lun) ) - { -/* printk ("DC390: Ignore target %d lun %d\n", - cmd->device->id, cmd->device->lun); */ - DC390_UNLOCK_ACB; - //return (1); - done (cmd); - return (0); - } - if( (pACB->scan_devices || cmd->cmnd[0] == TEST_UNIT_READY || cmd->cmnd[0] == INQUIRY) && !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun)) ) { @@ -1211,14 +1076,7 @@ { printk (KERN_ERR "DC390: kmalloc for DCB failed, target %02x lun %02x\n", cmd->device->id, cmd->device->lun); - DC390_UNLOCK_ACB; - printk ("DC390: No DCB in queue_command!\n"); -#ifdef USE_NEW_EH - return (1); -#else - done (cmd); - return (0); -#endif + goto fail; } } @@ -1226,10 +1084,7 @@ { printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n", cmd->device->id, cmd->device->lun); - DC390_UNLOCK_ACB; - //return (1); - done (cmd); - return (0); + goto fail; } else { @@ -1238,60 +1093,34 @@ { /* should never happen */ printk (KERN_ERR "DC390: no DCB failed, target %02x lun %02x\n", cmd->device->id, cmd->device->lun); - DC390_UNLOCK_ACB; - printk ("DC390: No DCB in queuecommand (2)!\n"); -#ifdef USE_NEW_EH - return (1); -#else - done (cmd); - return (0); -#endif + goto fail; } } pACB->Cmds++; cmd->scsi_done = done; cmd->result = 0; - - dc390_Query_to_Waiting (pACB); - if( pACB->QueryCnt ) /* Unsent commands ? */ - { - DEBUG0(printk ("DC390: QueryCnt != 0\n")); - dc390_Query_append ( cmd, pACB ); - dc390_Waiting_process (pACB); - } - else if (pDCB->pWaitingSRB) - { - pSRB = dc390_Free_get ( pACB ); - DEBUG0(if (!pSRB) printk ("DC390: No free SRB but Waiting\n"); else printk ("DC390: Free SRB w/ Waiting\n")); - if (!pSRB) dc390_Query_append (cmd, pACB); - else - { - dc390_BuildSRB (cmd, pDCB, pSRB); - dc390_Waiting_append (pDCB, pSRB); - } - dc390_Waiting_process (pACB); - } - else - { - pSRB = dc390_Free_get ( pACB ); - DEBUG0(if (!pSRB) printk ("DC390: No free SRB w/o Waiting\n"); else printk ("DC390: Free SRB w/o Waiting\n")); - if (!pSRB) - { - dc390_Query_append (cmd, pACB); - dc390_Waiting_process (pACB); - } - else - { - dc390_BuildSRB (cmd, pDCB, pSRB); - dc390_SendSRB (pACB, pSRB); - } - } + pSRB = dc390_Free_get(pACB); + if (!pSRB) + goto requeue; + + dc390_BuildSRB(cmd, pDCB, pSRB); + if (pDCB->pWaitingSRB) { + dc390_Waiting_append(pDCB, pSRB); + dc390_Waiting_process(pACB); + } else + dc390_SendSRB(pACB, pSRB); - DC390_UNLOCK_ACB; DEBUG1(printk (KERN_DEBUG " ... command (pid %li) queued successfully.\n", cmd->pid)); return(0); + + requeue: + return 1; + fail: + cmd->result = DID_BAD_TARGET << 16; + done(cmd); + return 0; } /* We ignore mapping problems, as we expect everybody to respect @@ -1491,28 +1320,10 @@ int status; //ULONG sbac; PACB pACB = (PACB) cmd->device->host->hostdata; - DC390_AFLAGS; - - DC390_LOCK_ACB; printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n", cmd->pid, cmd->device->id, cmd->device->lun); - /* First scan Query list */ - if( pACB->QueryCnt ) - { - struct scsi_cmnd_list *t, *pcmd_l; - list_for_each_entry_safe(pcmd_l, t, &pACB->cmdq, scp.list) - if( (struct scsi_cmnd*)pcmd_l == cmd ) - { - /* Found: Dequeue */ - list_del(&pcmd_l->scp.list); - pACB->QueryCnt--; - status = SCSI_ABORT_SUCCESS; - goto ABO_X; - } - } - pDCB = dc390_findDCB (pACB, cmd->device->id, cmd->device->lun); if( !pDCB ) goto NOT_RUN; @@ -1625,7 +1436,6 @@ } #endif dc390_lastabortedpid = cmd->pid; - DC390_UNLOCK_ACB; //do_DC390_Interrupt (pACB->IRQLevel, 0, 0); #ifndef USE_NEW_EH if (status == SCSI_ABORT_SUCCESS) cmd->scsi_done(cmd); @@ -1712,11 +1522,9 @@ { UCHAR bval; PACB pACB = (PACB) cmd->device->host->hostdata; - DC390_AFLAGS; printk(KERN_INFO "DC390: RESET ... "); - DC390_LOCK_ACB; if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer); bval = DC390_read8 (CtrlReg1); bval |= DIS_INT_ON_SCSI_RST; @@ -1745,7 +1553,6 @@ dc390_Waiting_process( pACB ); printk("done\n"); - DC390_UNLOCK_ACB; return( SCSI_RESET_SUCCESS ); } @@ -1767,7 +1574,7 @@ PDCB pDCB, pDCB2; pDCB = kmalloc (sizeof(DC390_DCB), GFP_ATOMIC); - DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): %p\n" \ + DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): %p\n", \ id, lun, pDCB)); *ppDCB = pDCB; @@ -1869,25 +1676,6 @@ pDCB->CtrlR1 |= PARITY_ERR_REPO; } - -/*********************************************************************** - * Function : static void dc390_updateDCBs () - * - * Purpose : Set the configuration dependent DCB params for all DCBs - ***********************************************************************/ - -static void dc390_updateDCBs (PACB pACB) -{ - int i; - PDCB pDCB = pACB->pLinkDCB; - for (i = 0; i < pACB->DCBCnt; i++) - { - dc390_updateDCB (pACB, pDCB); - pDCB = pDCB->pNextDCB; - } -} - - /*********************************************************************** * Function : static void dc390_initSRB() * @@ -1931,7 +1719,6 @@ { PACB pACB; UCHAR i; - DC390_AFLAGS; psh->can_queue = MAX_CMD_QUEUE; psh->cmd_per_lun = MAX_CMD_PER_LUN; @@ -1939,11 +1726,7 @@ psh->io_port = io_port; psh->n_io_port = 0x80; psh->irq = Irq; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,50) psh->base = io_port; -#else - psh->base = (char*)io_port; -#endif psh->unique_id = io_port; psh->dma_channel = -1; psh->last_reset = jiffies; @@ -1970,8 +1753,6 @@ pACB->pActiveDCB = NULL; pACB->pFreeSRB = pACB->SRB_array; pACB->SRBCount = MAX_SRB_CNT; - pACB->QueryCnt = 0; - INIT_LIST_HEAD(&pACB->cmdq); pACB->AdapterIndex = index; pACB->status = 0; psh->this_id = dc390_eepromBuf[index][EE_ADAPT_SCSI_ID]; @@ -2099,8 +1880,7 @@ { PSH psh; PACB pACB; - DC390_AFLAGS; - + if (dc390_CheckEEpromCheckSum (PDEV, index)) { int speed; @@ -2126,21 +1906,6 @@ scsi_set_device(psh, &pdev->dev); pACB = (PACB) psh->hostdata; - DC390_LOCKA_INIT; - DC390_LOCK_ACB; - -#if 0 - if( !dc390_pSH_start ) - { - dc390_pSH_start = psh; - dc390_pSH_current = psh; - } - else - { - dc390_pSH_current->next = psh; - dc390_pSH_current = psh; - } -#endif DEBUG0(printk(KERN_INFO "DC390: pSH = %8x, Index %02i\n", (UINT) psh, index)); @@ -2154,59 +1919,15 @@ (UINT) pACB, (UINT) pACB->DCBmap, (UINT) pACB->SRB_array)); DEBUG0(printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",\ sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) )); - - DC390_UNLOCK_ACB; return (0); } else { - //dc390_pSH_start = NULL; scsi_unregister( psh ); - DC390_UNLOCK_ACB; return( -1 ); } } - -/*********************************************************************** - * Function : int DC390_detect(Scsi_Host_Template *psht) - * - * Purpose : detects and initializes AMD53C974 SCSI chips - * that were autoprobed, overridden on the LILO command line, - * or specified at compile time. - * - * Inputs : psht - template for this SCSI adapter - * - * Returns : number of host adapters detected - * - ***********************************************************************/ - -#ifndef NEW_PCI -/* Acc. to PCI 2.1 spec it's up to the driver to enable Bus mastering: - * We use pci_set_master () for 2.1.x and this func for 2.0.x: */ -static void __init dc390_set_master (PDEVDECL) -{ - USHORT cmd; - UCHAR lat; - - PCI_READ_CONFIG_WORD (PDEV, PCI_COMMAND, &cmd); - - if (! (cmd & PCI_COMMAND_MASTER)) { - printk("PCI: Enabling bus mastering for device %02x:%02x\n", - PCI_BUS_DEV); - cmd |= PCI_COMMAND_MASTER; - PCI_WRITE_CONFIG_WORD(PDEV, PCI_COMMAND, cmd); - } - PCI_READ_CONFIG_BYTE (PDEV, PCI_LATENCY_TIMER, &lat); - if (lat < 16 /* || lat == 255 */) { - printk("PCI: Setting latency timer of device %02x:%02x from %i to 64\n", - PCI_BUS_DEV, lat); - PCI_WRITE_CONFIG_BYTE(PDEV, PCI_LATENCY_TIMER, 64); - } - -} -#endif /* ! NEW_PCI */ - static void __init dc390_set_pci_cfg (PDEVDECL) { USHORT cmd; @@ -2215,7 +1936,6 @@ PCI_WRITE_CONFIG_WORD (PDEV, PCI_COMMAND, cmd); PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)); } - int __init DC390_detect (Scsi_Host_Template *psht) { @@ -2223,16 +1943,18 @@ UCHAR irq; ULONG io_port; - //dc390_pSHT_start = psht; dc390_pACB_start = NULL; if ( PCI_PRESENT ) while (PCI_FIND_DEVICE (PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974)) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,30) if (pci_enable_device (pdev)) continue; -#endif + + if (pci_set_dma_mask(pdev, 0xffffffff)) { + printk(KERN_ERR "DC390(%i): No suitable DMA available.\n", dc390_adapterCnt); + continue; + } PCI_GET_IO_AND_IRQ; DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq)); @@ -2247,495 +1969,12 @@ printk (KERN_ERR "DC390: No PCI BIOS found!\n"); if (dc390_adapterCnt) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) psht->proc_name = "tmscsim"; -#else - psht->proc_dir = &DC390_proc_scsi_tmscsim; -#endif + printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt); return( dc390_adapterCnt ); } - -/*********************************************************************** - * Functions: dc390_inquiry(), dc390_inquiry_done() - * - * Purpose: When changing speed etc., we have to issue an INQUIRY - * command to make sure, we agree upon the nego parameters - * with the device - ***********************************************************************/ - -static void dc390_inquiry_done (Scsi_Cmnd* cmd) -{ - printk (KERN_INFO "DC390: INQUIRY (ID %02x LUN %02x) returned %08x\n", - cmd->device->id, cmd->device->lun, cmd->result); - if (cmd->result) - { - PACB pACB = (PACB)cmd->device->host->hostdata; - PDCB pDCB = dc390_findDCB (pACB, cmd->device->id, cmd->device->lun); - printk ("DC390: Unsetting DsCn, Sync and TagQ!\n"); - if (pDCB) - { - pDCB->DevMode &= ~(SYNC_NEGO_ | TAG_QUEUEING_ | EN_DISCONNECT_ ); - dc390_updateDCB (pACB, pDCB); - } - } - kfree (cmd); -} - -void dc390_inquiry (PACB pACB, PDCB pDCB) -{ - char* buffer; - Scsi_Cmnd* cmd; - cmd = kmalloc (sizeof(Scsi_Cmnd) + 256, GFP_ATOMIC); - if (!cmd) { printk ("DC390: kmalloc failed in inquiry!\n"); return; } - buffer = (char*)cmd + sizeof(Scsi_Cmnd); - - memset (cmd, 0, sizeof(Scsi_Cmnd) + 256); - cmd->cmnd[0] = INQUIRY; - cmd->cmnd[1] = (pDCB->TargetLUN << 5) & 0xe0; - cmd->cmnd[4] = 0xff; - - cmd->cmd_len = 6; cmd->old_cmd_len = 6; -/* TODO FIXME */ -/* cmd->host = pACB->pScsiHost; */ - cmd->device->id = pDCB->TargetID; - cmd->device->lun = pDCB->TargetLUN; - cmd->serial_number = 1; - cmd->pid = 390; - cmd->bufflen = 128; - cmd->buffer = buffer; - cmd->request_bufflen = 128; - cmd->request_buffer = &buffer[128]; - cmd->done = dc390_inquiry_done; - cmd->scsi_done = dc390_inquiry_done; - cmd->timeout_per_command = HZ; - - cmd->request->rq_status = RQ_SCSI_BUSY; - - pDCB->SyncMode &= ~SYNC_NEGO_DONE; - printk (KERN_INFO "DC390: Queue INQUIRY command to dev ID %02x LUN %02x\n", - pDCB->TargetID, pDCB->TargetLUN); - DC390_queue_command (cmd, dc390_inquiry_done); -} - -/*********************************************************************** - * Functions: dc390_sendstart(), dc390_sendstart_done() - * - * Purpose: When changing speed etc., we have to issue an INQUIRY - * command to make sure, we agree upon the nego parameters - * with the device - ***********************************************************************/ - -static void dc390_sendstart_done (Scsi_Cmnd* cmd) -{ - printk (KERN_INFO "DC390: SENDSTART (ID %02x LUN %02x) returned %08x\n", - cmd->device->id, cmd->device->lun, cmd->result); - kfree (cmd); -} - -void dc390_sendstart (PACB pACB, PDCB pDCB) -{ - char* buffer; - Scsi_Cmnd* cmd; - cmd = kmalloc (sizeof(Scsi_Cmnd) + 256, GFP_ATOMIC); - if (!cmd) { printk ("DC390: kmalloc failed in sendstart!\n"); return; } - buffer = (char*)cmd + sizeof(Scsi_Cmnd); - - memset (cmd, 0, sizeof(Scsi_Cmnd) + 256); - cmd->cmnd[0] = 0x1b; /* START_STOP_UNIT */ - cmd->cmnd[1] = (pDCB->TargetLUN << 5) & 0xe0; - cmd->cmnd[4] = 0x01; /* START */ - - cmd->cmd_len = 6; cmd->old_cmd_len = 6; -/* TODO FIXME */ -/* cmd->host = pACB->pScsiHost; */ - cmd->device->id = pDCB->TargetID; - cmd->device->lun = pDCB->TargetLUN; - cmd->serial_number = 1; - cmd->pid = 310; - cmd->bufflen = 128; - cmd->buffer = buffer; - cmd->request_bufflen = 128; - cmd->request_buffer = &buffer[128]; - cmd->done = dc390_sendstart_done; - cmd->scsi_done = dc390_sendstart_done; - cmd->timeout_per_command = 5*HZ; - - cmd->request->rq_status = RQ_SCSI_BUSY; - - pDCB->SyncMode &= ~SYNC_NEGO_DONE; - printk (KERN_INFO "DC390: Queue SEND_START command to dev ID %02x LUN %02x\n", - pDCB->TargetID, pDCB->TargetLUN); - DC390_queue_command (cmd, dc390_sendstart_done); -} - -/******************************************************************** - * Function: dc390_set_info() - * - * Purpose: Change adapter config - * - * Strings are parsed similar to the output of tmscsim_proc_info () - * '-' means no change - *******************************************************************/ - -static int dc390_scanf (char** buffer, char** pos, char** p0, int* var) -{ - *p0 = *pos; - *var = simple_strtoul (*p0, pos, 10); - if (*p0 == *pos) return -1; - *pos = strsep (buffer, " \t\n:=,;."); - return 0; -} - -#define SCANF(buffer, pos, p0, var, min, max) \ -if (dc390_scanf (&buffer, &pos, &p0, &var)) goto einv; \ -else if (varmax) goto einv2 - -static int dc390_yesno (char** buffer, char** pos, char* var, char bmask) -{ - switch (**pos) - { - case 'Y': *var |= bmask; break; - case 'N': *var &= ~bmask; break; - case '-': break; - default: return -1; - } - *pos = strsep (buffer, " \t\n:=,;"); - return 0; -} - -#define YESNO(buffer, pos, var, bmask) \ - if (dc390_yesno (&buffer, &pos, &var, bmask)) goto einv; \ - else dc390_updateDCB (pACB, pDCB); \ - if (!pos) goto ok - -static int dc390_search (char** buffer, char** pos, char** p0, char* var, char* txt, int max, int scale, char* ign) -{ - int dum; - if (! memcmp (*pos, txt, strlen(txt))) - { - *p0 = strsep (buffer, " \t\n:=,;"); - if (!*p0) return -1; - dum = simple_strtoul (*p0, pos, 10); - if (*p0 == *pos) return -1; - if (dum >= 0 && dum <= max) - { *var = (dum * 100) / scale; } - else return -2; - *pos = strsep (buffer, " \t\n:=,;"); - if (*ign && *pos && strlen(*pos) >= strlen(ign) && - !(memcmp (*pos, ign, strlen(ign)))) - *pos = strsep (buffer, " \t\n:=,;"); - - } - return 0; -} - -#define SEARCH(buffer, pos, p0, var, txt, max) \ -if (dc390_search (&buffer, &pos, &p0, (PUCHAR)(&var), txt, max, 100, "")) goto einv2; \ -else if (!p1) goto ok2 - -#define SEARCH2(buffer, pos, p0, var, txt, max, scale) \ -if (dc390_search (&buffer, &pos, &p0, &var, txt, max, scale, "")) goto einv2; \ -else if (!p1) goto ok2 - -#define SEARCH3(buffer, pos, p0, var, txt, max, scale, ign) \ -if (dc390_search (&buffer, &pos, &p0, &var, txt, max, scale, ign)) goto einv2; \ -else if (!p1) goto ok2 - - -#ifdef DC390_PARSEDEBUG -static char _prstr[256]; -char* prstr (char* p, char* e) -{ - char* c = _prstr; - while (p < e) - if (*p == 0) { *c++ = ':'; p++; } - else if (*p == 10) { *c++ = '\\'; *c++ = 'n'; p++; } - else *c++ = *p++; - *c = 0; - return _prstr; -} -#endif - -int dc390_set_info (char *buffer, int length, PACB pACB) -{ - char *pos = buffer, *p0 = buffer; - char needs_inquiry = 0; - int dum = 0; - char dev; - PDCB pDCB = pACB->pLinkDCB; - DC390_IFLAGS; - DC390_AFLAGS; - pos[length] = 0; - - DC390_LOCK_IO(pACB->pScsiHost); - DC390_LOCK_ACB; - /* UPPERCASE */ - /* Don't use kernel toupper, because of 2.0.x bug: ctmp unexported */ - while (*pos) - { if (*pos >='a' && *pos <= 'z') *pos = *pos + 'A' - 'a'; pos++; } - - /* Remove WS */ - pos = strsep (&buffer, " \t:\n=,;"); - if (!*pos) goto ok; - - next: - if (!memcmp (pos, "RESET", 5)) goto reset; - else if (!memcmp (pos, "INQUIRY", 7)) goto inquiry; - else if (!memcmp (pos, "REMOVE", 6)) goto remove; - else if (!memcmp (pos, "ADD", 3)) goto add; - else if (!memcmp (pos, "START", 5)) goto start; - else if (!memcmp (pos, "DUMP", 4)) goto dump; - - if (isdigit (*pos)) - { - /* Device config line */ - int dev, id, lun; char* pdec; - char olddevmode; - - SCANF (buffer, pos, p0, dev, 0, pACB->DCBCnt-1); - if (*pos) { SCANF (buffer, pos, p0, id, 0, 7); } else goto einv; - if (*pos) { SCANF (buffer, pos, p0, lun, 0, 7); } else goto einv; - if (!*pos) goto einv; - - PARSEDEBUG(printk (KERN_INFO "DC390: config line %i %i %i:\"%s\"\n", dev, id, lun, prstr (pos, &buffer[length]))); - pDCB = pACB->pLinkDCB; - for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB; - /* Sanity Check */ - if (pDCB->TargetID != id || pDCB->TargetLUN != lun) - { - printk (KERN_ERR "DC390: no such device: Idx=%02i ID=%02i LUN=%02i\n", - dev, id, lun); - goto einv2; - } - - if (pDCB->pWaitingSRB || pDCB->pGoingSRB) - { - printk ("DC390: Cannot change dev (%i-%i) cfg: Pending requests\n", - pDCB->TargetID, pDCB->TargetLUN); - goto einv; - } - - olddevmode = pDCB->DevMode; - YESNO (buffer, pos, pDCB->DevMode, PARITY_CHK_); - needs_inquiry++; - YESNO (buffer, pos, pDCB->DevMode, SYNC_NEGO_); - if ((olddevmode & SYNC_NEGO_) == (pDCB->DevMode & SYNC_NEGO_)) needs_inquiry--; - needs_inquiry++; - YESNO (buffer, pos, pDCB->DevMode, EN_DISCONNECT_); - if ((olddevmode & EN_DISCONNECT_) == (pDCB->DevMode & EN_DISCONNECT_)) needs_inquiry--; - YESNO (buffer, pos, pDCB->DevMode, SEND_START_); - needs_inquiry++; - YESNO (buffer, pos, pDCB->DevMode, TAG_QUEUEING_); - if ((olddevmode & TAG_QUEUEING_) == (pDCB->DevMode & TAG_QUEUEING_)) needs_inquiry--; - - dc390_updateDCB (pACB, pDCB); - if (!*pos) goto ok; - - olddevmode = pDCB->NegoPeriod; - /* Look for decimal point (Speed) */ - pdec = pos; - while (pdec++ < &buffer[length]) if (*pdec == '.') break; - /* NegoPeriod */ - if (*pos != '-') - { - SCANF (buffer, pos, p0, dum, 72, 800); - pDCB->NegoPeriod = dum >> 2; - if (pDCB->NegoPeriod != olddevmode) needs_inquiry++; - if (!pos) goto ok; - if (memcmp (pos, "NS", 2) == 0) pos = strsep (&pos, " \t\n:=,;."); - } - else pos = strsep (&pos, " \t\n:=,;."); - if (!*pos) goto ok; - - /* Sync Speed in MHz */ - if (*pos != '-') - { - SCANF (buffer, pos, p0, dum, 1, 13); - pDCB->NegoPeriod = (1000/dum) >> 2; - if (pDCB->NegoPeriod != olddevmode && !pos) needs_inquiry++; - if (!*pos) goto ok; - /* decimal */ - if (pos-1 == pdec) - { - int dumold = dum; - dum = simple_strtoul (pos, &p0, 10) * 10; - for (; p0-pos > 1; p0--) dum /= 10; - pDCB->NegoPeriod = (100000/(100*dumold + dum)) >> 2; - if (pDCB->NegoPeriod < 19) pDCB->NegoPeriod = 19; - pos = strsep (&pos, " \t\n:=,;"); - if (!*pos) goto ok; - } - if (*pos == 'M') pos = strsep (&pos, " \t\n:=,;"); - if (pDCB->NegoPeriod != olddevmode) needs_inquiry++; - } - else pos = strsep (&pos, " \t\n:=,;"); - /* dc390_updateDCB (pACB, pDCB); */ - if (!*pos) goto ok; - - olddevmode = pDCB->SyncOffset; - /* SyncOffs */ - if (*pos != '-') - { - SCANF (buffer, pos, p0, dum, 0, 0x0f); - pDCB->SyncOffset = dum; - if (pDCB->SyncOffset > olddevmode) needs_inquiry++; - } - else pos = strsep (&pos, " \t\n:=,;"); - if (!*pos) goto ok; - dc390_updateDCB (pACB, pDCB); - - //olddevmode = pDCB->MaxCommand; - /* MaxCommand (Tags) */ - if (*pos != '-') - { - SCANF (buffer, pos, p0, dum, 1, 32 /*pACB->TagMaxNum*/); - if (pDCB->SyncMode & EN_TAG_QUEUEING) - pDCB->MaxCommand = dum; - else printk (KERN_INFO "DC390: Can't set MaxCmd larger than one without Tag Queueing!\n"); - } - else pos = strsep (&pos, " \t\n:=,;"); - - } - else - { - char* p1 = pos; UCHAR dum, newadaptid; - PARSEDEBUG(printk (KERN_INFO "DC390: chg adapt cfg \"%s\"\n", prstr (pos, &buffer[length]))); - dum = GLITCH_TO_NS (pACB->glitch_cfg); - /* Adapter setting */ - SEARCH (buffer, pos, p0, pACB->pScsiHost->max_id, "MAXID", 8); - SEARCH (buffer, pos, p0, pACB->pScsiHost->max_lun, "MAXLUN", 8); - SEARCH (buffer, pos, p0, newadaptid, "ADAPTERID", 7); - SEARCH (buffer, pos, p0, pACB->TagMaxNum, "TAGMAXNUM", 32); - SEARCH (buffer, pos, p0, pACB->ACBFlag, "ACBFLAG", 255); - SEARCH3 (buffer, pos, p0, dum, "GLITCHEATER", 40, 1000, "NS"); - SEARCH3 (buffer, pos, p0, pACB->sel_timeout, "SELTIMEOUT", 400, 163, "MS"); - SEARCH3 (buffer, pos, p0, dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY], "DELAYRESET", 180, 100, "S"); - ok2: - pACB->glitch_cfg = NS_TO_GLITCH (dum); - if (pACB->sel_timeout < 60) pACB->sel_timeout = 60; - DC390_write8 (Scsi_TimeOut, pACB->sel_timeout); - if (newadaptid != pACB->pScsiHost->this_id) - { - pACB->pScsiHost->this_id = newadaptid; - dc390_ResetDevParam (pACB); - } - //dum = 0; while (1 << dum <= pACB->TagMaxNum) dum ++; - //pACB->TagMaxNum &= (1 << --dum); - dc390_updateDCBs (pACB); - // All devs should be INQUIRED now - if (pos == p1) goto einv; - } - if (*pos) goto next; - - ok: - DC390_UNLOCK_ACB; - if (needs_inquiry) - { dc390_updateDCB (pACB, pDCB); dc390_inquiry (pACB, pDCB); } - DC390_UNLOCK_IO(pACB->pScsiHost); - return (length); - - einv2: - pos = p0; - einv: - DC390_UNLOCK_ACB; - DC390_UNLOCK_IO(pACB->pScsiHost); - printk (KERN_WARNING "DC390: parse error near \"%s\"\n", (pos? pos: "NULL")); - return (-EINVAL); - - reset: - { - Scsi_Cmnd cmd; - /* TODO FIXME */ - /* cmd.host = pACB->pScsiHost; */ - printk (KERN_WARNING "DC390: Driver reset requested!\n"); - DC390_UNLOCK_ACB; - DC390_reset (&cmd); - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - dump: - { - dc390_dumpinfo (pACB, 0, 0); - DC390_UNLOCK_ACB; - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - inquiry: - { - pos = strsep (&pos, " \t\n.:;="); if (!*pos) goto einv; - dev = simple_strtoul (pos, &p0, 10); - if (dev >= pACB->DCBCnt) goto einv_dev; - for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB; - printk (KERN_NOTICE " DC390: Issue INQUIRY command to Dev(Idx) %i SCSI ID %i LUN %i\n", - dev, pDCB->TargetID, pDCB->TargetLUN); - DC390_UNLOCK_ACB; - dc390_inquiry (pACB, pDCB); - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - remove: - { - pos = strsep (&pos, " \t\n.:;="); if (!*pos) goto einv; - dev = simple_strtoul (pos, &p0, 10); - if (dev >= pACB->DCBCnt) goto einv_dev; - for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB; - printk (KERN_NOTICE " DC390: Remove DCB for Dev(Idx) %i SCSI ID %i LUN %i\n", - dev, pDCB->TargetID, pDCB->TargetLUN); - /* TO DO: We should make sure no pending commands are left */ - dc390_remove_dev (pACB, pDCB); - DC390_UNLOCK_ACB; - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - add: - { - int id, lun; - pos = strsep (&pos, " \t\n.:;="); - if (*pos) { SCANF (buffer, pos, p0, id, 0, 7); } else goto einv; - if (*pos) { SCANF (buffer, pos, p0, lun, 0, 7); } else goto einv; - pDCB = dc390_findDCB (pACB, id, lun); - if (pDCB) { printk ("DC390: ADD: Device already existing\n"); goto einv; } - dc390_initDCB (pACB, &pDCB, id, lun); - DC390_UNLOCK_ACB; - dc390_inquiry (pACB, pDCB); - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - start: - { - int id, lun; - pos = strsep (&pos, " \t\n.:;="); - if (*pos) { SCANF (buffer, pos, p0, id, 0, 7); } else goto einv; - if (*pos) { SCANF (buffer, pos, p0, lun, 0, 7); } else goto einv; - pDCB = dc390_findDCB (pACB, id, lun); - if (pDCB) printk ("DC390: SendStart: Device already existing ...\n"); - else dc390_initDCB (pACB, &pDCB, id, lun); - DC390_UNLOCK_ACB; - dc390_sendstart (pACB, pDCB); - dc390_inquiry (pACB, pDCB); - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - einv_dev: - printk (KERN_WARNING "DC390: Ignore cmnd to invalid Dev(Idx) %i. Valid range: 0 - %i.\n", - dev, pACB->DCBCnt - 1); - DC390_UNLOCK_ACB; - DC390_UNLOCK_IO(pACB->pScsiHost); - return (-EINVAL); -} - -#undef SEARCH -#undef YESNO -#undef SCANF - /******************************************************************** * Function: DC390_proc_info(char* buffer, char **start, * off_t offset, int length, int hostno, int inout) @@ -2768,10 +2007,8 @@ { int dev, spd, spd1; char *pos = buffer; - struct scsi_cmnd_list *cl; PACB pACB; PDCB pDCB; - DC390_AFLAGS; pACB = dc390_pACB_start; @@ -2785,13 +2022,11 @@ if (pACB == (PACB)-1) return(-ESRCH); if(inout) /* Has data been written to the file ? */ - return dc390_set_info(buffer, length, pACB); + return -ENOSYS; SPRINTF("Tekram DC390/AM53C974 PCI SCSI Host Adapter, "); SPRINTF("Driver Version %s\n", DC390_VERSION); - DC390_LOCK_ACB; - SPRINTF("SCSI Host Nr %i, ", shpnt->host_no); SPRINTF("%s Adapter Nr %i\n", dc390_adapname, pACB->AdapterIndex); SPRINTF("IOPortBase 0x%04x, ", pACB->IOPortBase); @@ -2839,9 +2074,6 @@ SPRINTF (" %02i\n", pDCB->MaxCommand); pDCB = pDCB->pNextDCB; } - SPRINTF ("Commands in Queues: Query: %li:", pACB->QueryCnt); - list_for_each_entry(cl, &pACB->cmdq, scp.list) - SPRINTF (" %li", ((struct scsi_cmnd*)cl)->pid); if (timer_pending(&pACB->Waiting_Timer)) SPRINTF ("Waiting queue timer running\n"); else SPRINTF ("\n"); pDCB = pACB->pLinkDCB; @@ -2876,8 +2108,6 @@ SPRINTF("\n"); #endif - - DC390_UNLOCK_ACB; *start = buffer + offset; if (pos - buffer < offset) @@ -2940,11 +2170,10 @@ int DC390_release (struct Scsi_Host *host) { - DC390_AFLAGS DC390_IFLAGS; + DC390_IFLAGS; PACB pACB = (PACB)(host->hostdata); DC390_LOCK_IO(host); - DC390_LOCK_ACB; /* TO DO: We should check for outstanding commands first. */ dc390_shutdown (host); @@ -2957,7 +2186,6 @@ release_region(host->io_port,host->n_io_port); dc390_freeDCBs (host); - DC390_UNLOCK_ACB; DC390_UNLOCK_IO(host); scsi_unregister(host); return( 1 ); diff -Nru a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h --- a/drivers/scsi/tmscsim.h Fri May 21 19:07:22 2004 +++ b/drivers/scsi/tmscsim.h Fri May 21 19:07:22 2004 @@ -214,16 +214,12 @@ PSRB pTmpSRB; /* 0x2c: */ -ULONG QueryCnt; -struct list_head cmdq; - -/* 0x38: */ UCHAR msgin123[4]; UCHAR DCBmap[MAX_SCSI_ID]; UCHAR Connected; UCHAR pad; -/* 0x3c: */ +/* 0x30: */ #if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(CONFIG_SMP) || DEBUG_SPINLOCKS > 0) spinlock_t lock; #endif @@ -234,20 +230,20 @@ UCHAR Ignore_IRQ; /* Not used */ PDEVDECL1; /* Pointer to PCI cfg. space */ -/* 0x4c/0x48: */ +/* 0x40/0x3c: */ ULONG Cmds; UINT SelLost; UINT SelConn; UINT CmdInQ; UINT CmdOutOfSRB; -/* 0x60/0x5c: */ +/* 0x54/0x50: */ struct timer_list Waiting_Timer; -/* 0x74/0x70: */ +/* 0x68/0x64: */ DC390_SRB TmpSRB; -/* 0xd8/0xd4: */ +/* 0xcc/0xc8: */ DC390_SRB SRB_array[MAX_SRB_CNT]; /* 50 SRBs */ -/* 0xfb0/0xfac: */ +/* 0xfa4/0xfa0: */ }; typedef struct _ACB DC390_ACB, *PACB; @@ -406,15 +402,8 @@ * SISC query queue */ typedef struct { - struct list_head list; dma_addr_t saved_dma_handle; } dc390_cmd_scp_t; - -struct scsi_cmnd_list -{ - char dummy[offsetof(struct scsi_cmnd, SCp)]; - dc390_cmd_scp_t scp; -}; /* ** Inquiry Data format diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c --- a/drivers/scsi/wd7000.c Fri May 21 19:07:22 2004 +++ b/drivers/scsi/wd7000.c Fri May 21 19:07:22 2004 @@ -165,6 +165,7 @@ * Removed now obsolete wd7000.h */ +#include #include #include #include @@ -846,7 +847,7 @@ static inline Scb *alloc_scbs(struct Scsi_Host *host, int needed) { register Scb *scb, *p = NULL; - register unsigned long flags; + unsigned long flags; register unsigned long timeout = jiffies + WAITnexttimeout; register unsigned long now; int i; @@ -898,7 +899,7 @@ static inline void free_scb(Scb * scb) { - register unsigned long flags; + unsigned long flags; spin_lock_irqsave(&scbpool_lock, flags); @@ -936,7 +937,7 @@ */ { register int i, ogmb; - register unsigned long flags; + unsigned long flags; unchar start_ogmb; Mailbox *ogmbs = host->mb.ogmb; int *next_ogmb = &(host->next_ogmb); diff -Nru a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h --- a/include/scsi/scsi_devinfo.h Fri May 21 19:07:22 2004 +++ b/include/scsi/scsi_devinfo.h Fri May 21 19:07:22 2004 @@ -4,7 +4,8 @@ * Flags for SCSI devices that need special treatment */ #define BLIST_NOLUN 0x001 /* Only scan LUN 0 */ -#define BLIST_FORCELUN 0x002 /* Known to have LUNs, force scanning */ +#define BLIST_FORCELUN 0x002 /* Known to have LUNs, force scanning, + deprecated: Use max_luns=N */ #define BLIST_BORKEN 0x004 /* Flag for broken handshaking */ #define BLIST_KEY 0x008 /* unlock by special command */ #define BLIST_SINGLELUN 0x010 /* Do not use LUNs in parallel */ @@ -20,4 +21,7 @@ #define BLIST_MS_SKIP_PAGE_3F 0x4000 /* do not send ms page 0x3f */ #define BLIST_USE_10_BYTE_MS 0x8000 /* use 10 byte ms before 6 byte ms */ #define BLIST_MS_192_BYTES_FOR_3F 0x10000 /* 192 byte ms page 0x3f request */ +#define BLIST_REPORTLUN2 0x20000 /* try REPORT_LUNS even for SCSI-2 devs + (if HBA supports more than 8 LUNs) */ +#define BLIST_NOREPORTLUN 0x40000 /* don't try REPORT_LUNS scan (SCSI-3 devs) */ #endif