^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Linux driver for *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * ICP vortex GmbH: GDT PCI Disk Array Controllers *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Intel Corporation: Storage RAID Controllers *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * gdth.c *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 1995-06 ICP vortex GmbH, Achim Leubner *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2002-04 Intel Corporation *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2003-06 Adaptec Inc. *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * <achim_leubner@adaptec.com> *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Additions/Fixes: *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Boji Tony Kannanthanam <boji.t.kannanthanam@intel.com> *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Johannes Dinner <johannes_dinner@adaptec.com> *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Linux kernel 2.6.x supported *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) ************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* All GDT Disk Array Controllers are fully supported by this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * This includes the PCI SCSI Disk Array Controllers and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * PCI Fibre Channel Disk Array Controllers. See gdth.h for a complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * list of all controller types.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * After the optional list of IRQ values, other possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * command line options are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * disable:Y disable driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * disable:N enable driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * reserve_mode:0 reserve no drives for the raw service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * reserve_mode:1 reserve all not init., removable drives
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * reserve_mode:2 reserve all not init. drives
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * reserve_list:h,b,t,l,h,b,t,l,... reserve particular drive(s) with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * h- controller no., b- channel no.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * t- target ID, l- LUN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * reverse_scan:Y reverse scan order for PCI controllers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * reverse_scan:N scan PCI controllers like BIOS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * max_ids:x x - target ID count per channel (1..MAXID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * rescan:Y rescan all channels/IDs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * rescan:N use all devices found until now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * hdr_channel:x x - number of virtual bus for host drives
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * shared_access:Y disable driver reserve/release protocol to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * access a shared resource from several nodes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * appropriate controller firmware required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * shared_access:N enable driver reserve/release protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * force_dma32:Y use only 32 bit DMA mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * force_dma32:N use 64 bit DMA mode, if supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * The default values are: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * max_ids:127,rescan:N,hdr_channel:0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * shared_access:Y,force_dma32:N".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * When loading the gdth driver as a module, the same options are available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * You can set the IRQs with "IRQ=...". However, the syntax to specify the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * options changes slightly. You must replace all ',' between options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * with ' ' and all ':' with '=' and you must use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * '1' in place of 'Y' and '0' in place of 'N'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * max_ids=127 rescan=0 hdr_channel=0 shared_access=0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * force_dma32=0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* The meaning of the Scsi_Pointer members in this driver is as follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * ptr: Chaining
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * this_residual: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * buffer: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * dma_handle: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * buffers_residual: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * Status: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Message: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * have_data_in: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * sent_command: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * phase: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* statistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define GDTH_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #include <linux/version.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #include <asm/dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #include <linux/scatterlist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #include "scsi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #include "gdth.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static DEFINE_MUTEX(gdth_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static void gdth_delay(int milliseconds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static void gdth_eval_mapping(u32 size, u32 *cyls, int *heads, int *secs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static irqreturn_t gdth_interrupt(int irq, void *dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static irqreturn_t __gdth_interrupt(gdth_ha_str *ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int gdth_from_wait, int* pIndex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int gdth_sync_event(gdth_ha_str *ha, int service, u8 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct scsi_cmnd *scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int gdth_async_event(gdth_ha_str *ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static void gdth_log_event(gdth_evt_data *dvr, char *buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static void gdth_putq(gdth_ha_str *ha, struct scsi_cmnd *scp, u8 priority);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static void gdth_next(gdth_ha_str *ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int gdth_fill_raw_cmd(gdth_ha_str *ha, struct scsi_cmnd *scp, u8 b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int gdth_special_cmd(gdth_ha_str *ha, struct scsi_cmnd *scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, u16 source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u16 idx, gdth_evt_data *evt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void gdth_readapp_event(gdth_ha_str *ha, u8 application,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) gdth_evt_str *estr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static void gdth_clear_events(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static void gdth_copy_internal_data(gdth_ha_str *ha, struct scsi_cmnd *scp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) char *buffer, u16 count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int gdth_internal_cache_cmd(gdth_ha_str *ha, struct scsi_cmnd *scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static int gdth_fill_cache_cmd(gdth_ha_str *ha, struct scsi_cmnd *scp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u16 hdrive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void gdth_enable_int(gdth_ha_str *ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int gdth_test_busy(gdth_ha_str *ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int gdth_get_cmd_index(gdth_ha_str *ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void gdth_release_event(gdth_ha_str *ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int gdth_wait(gdth_ha_str *ha, int index,u32 time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int gdth_internal_cmd(gdth_ha_str *ha, u8 service, u16 opcode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u32 p1, u64 p2,u64 p3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static int gdth_search_drives(gdth_ha_str *ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int gdth_analyse_hdrive(gdth_ha_str *ha, u16 hdrive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static const char *gdth_ctr_name(gdth_ha_str *ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static int gdth_open(struct inode *inode, struct file *filep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static int gdth_close(struct inode *inode, struct file *filep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static long gdth_unlocked_ioctl(struct file *filep, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static void gdth_flush(gdth_ha_str *ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int gdth_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct gdth_cmndinfo *cmndinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void gdth_scsi_done(struct scsi_cmnd *scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #ifdef DEBUG_GDTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static u8 DebugState = DEBUG_GDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define TRACE(a) {if (DebugState==1) {printk a;}}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define TRACE2(a) {if (DebugState==1 || DebugState==2) {printk a;}}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define TRACE3(a) {if (DebugState!=0) {printk a;}}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #else /* !DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define TRACE(a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define TRACE2(a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define TRACE3(a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #ifdef GDTH_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static u32 max_rq=0, max_index=0, max_sg=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static u32 act_ints=0, act_ios=0, act_stats=0, act_rq=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static struct timer_list gdth_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define PTR2USHORT(a) (u16)(unsigned long)(a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define INDEX_OK(i,t) ((i)<ARRAY_SIZE(t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static u8 gdth_polling; /* polling if TRUE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static int gdth_ctr_count = 0; /* controller count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static LIST_HEAD(gdth_instances); /* controller list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static u8 gdth_write_through = FALSE; /* write through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static int elastidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static int eoldidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static int major;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) #define DIN 1 /* IN data direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #define DOU 2 /* OUT data direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #define DNO DIN /* no data transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define DUN DIN /* unknown data direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static u8 gdth_direction_tab[0x100] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) DNO,DNO,DIN,DIN,DOU,DIN,DIN,DOU,DIN,DUN,DOU,DOU,DUN,DUN,DUN,DIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) DNO,DIN,DIN,DOU,DIN,DOU,DNO,DNO,DOU,DNO,DIN,DNO,DIN,DOU,DNO,DUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) DIN,DUN,DIN,DUN,DOU,DIN,DUN,DUN,DIN,DIN,DOU,DNO,DUN,DIN,DOU,DOU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) DOU,DOU,DOU,DNO,DIN,DNO,DNO,DIN,DOU,DOU,DOU,DOU,DIN,DOU,DIN,DOU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) DOU,DOU,DIN,DIN,DIN,DNO,DUN,DNO,DNO,DNO,DUN,DNO,DOU,DIN,DUN,DUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DOU,DUN,DNO,DUN,DOU,DOU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* LILO and modprobe/insmod parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* disable driver flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static int disable __initdata = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* reserve flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int reserve_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* reserve list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static int reserve_list[MAX_RES_ARGS] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* scan order for PCI controllers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static int reverse_scan = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* virtual channel for the host drives */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int hdr_channel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* max. IDs per channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static int max_ids = MAXID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* rescan all IDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static int rescan = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* shared access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static int shared_access = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* 64 bit DMA mode, support for drives > 2 TB, if force_dma32 = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static int force_dma32 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* parameters for modprobe/insmod */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) module_param(disable, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) module_param(reserve_mode, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) module_param_array(reserve_list, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) module_param(reverse_scan, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) module_param(hdr_channel, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) module_param(max_ids, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) module_param(rescan, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) module_param(shared_access, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) module_param(force_dma32, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) MODULE_AUTHOR("Achim Leubner");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* ioctl interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static const struct file_operations gdth_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .unlocked_ioctl = gdth_unlocked_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .open = gdth_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .release = gdth_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .llseek = noop_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #include "gdth_proc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) #include "gdth_proc.c"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static gdth_ha_str *gdth_find_ha(int hanum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) list_for_each_entry(ha, &gdth_instances, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (hanum == ha->hanum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static struct gdth_cmndinfo *gdth_get_cmndinfo(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct gdth_cmndinfo *priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) for (i=0; i<GDTH_MAXCMDS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (ha->cmndinfo[i].index == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) priv = &ha->cmndinfo[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) memset(priv, 0, sizeof(*priv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) priv->index = i+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static void gdth_put_cmndinfo(struct gdth_cmndinfo *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) BUG_ON(!priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) priv->index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static void gdth_delay(int milliseconds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (milliseconds == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) mdelay(milliseconds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static void gdth_scsi_done(struct scsi_cmnd *scp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int internal_command = cmndinfo->internal_command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) TRACE2(("gdth_scsi_done()\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) gdth_put_cmndinfo(cmndinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) scp->host_scribble = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (internal_command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) complete((struct completion *)scp->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) scp->scsi_done(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) char *cmnd, int timeout, u32 *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) gdth_ha_str *ha = shost_priv(sdev->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct scsi_cmnd *scp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct gdth_cmndinfo cmndinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) DECLARE_COMPLETION_ONSTACK(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) scp = kzalloc(sizeof(*scp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (!scp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) scp->sense_buffer = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (!scp->sense_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) kfree(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) scp->device = sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) memset(&cmndinfo, 0, sizeof(cmndinfo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* use request field to save the ptr. to completion struct. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) scp->request = (struct request *)&wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) scp->cmd_len = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) scp->cmnd = cmnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) cmndinfo.priority = IOCTL_PRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) cmndinfo.internal_cmd_str = gdtcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) cmndinfo.internal_command = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) TRACE(("__gdth_execute() cmd 0x%x\n", scp->cmnd[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) __gdth_queuecommand(ha, scp, &cmndinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) wait_for_completion(&wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) rval = cmndinfo.status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) *info = cmndinfo.info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) kfree(scp->sense_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) kfree(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) int timeout, u32 *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct scsi_device *sdev = scsi_get_host_dev(shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) int rval = __gdth_execute(sdev, gdtcmd, cmnd, timeout, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) scsi_free_host_dev(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static void gdth_eval_mapping(u32 size, u32 *cyls, int *heads, int *secs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) *cyls = size /HEADS/SECS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (*cyls <= MAXCYLS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) *heads = HEADS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) *secs = SECS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) } else { /* too high for 64*32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) *cyls = size /MEDHEADS/MEDSECS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (*cyls <= MAXCYLS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) *heads = MEDHEADS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) *secs = MEDSECS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) } else { /* too high for 127*63 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) *cyls = size /BIGHEADS/BIGSECS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) *heads = BIGHEADS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) *secs = BIGSECS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static bool gdth_search_vortex(u16 device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (device <= PCI_DEVICE_ID_VORTEX_GDT6555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (device == PCI_DEVICE_ID_VORTEX_GDTNEWRX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) device == PCI_DEVICE_ID_VORTEX_GDTNEWRX2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static int gdth_pci_init_one(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) const struct pci_device_id *ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static void gdth_pci_remove_one(struct pci_dev *pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static void gdth_remove_one(gdth_ha_str *ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* Vortex only makes RAID controllers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * We do not really want to specify all 550 ids here, so wildcard match.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static const struct pci_device_id gdthtable[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) { PCI_VDEVICE(VORTEX, PCI_ANY_ID) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC_XSCALE) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) { } /* terminate list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) MODULE_DEVICE_TABLE(pci, gdthtable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static struct pci_driver gdth_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) .name = "gdth",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) .id_table = gdthtable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) .probe = gdth_pci_init_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) .remove = gdth_pci_remove_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) static void gdth_pci_remove_one(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) gdth_ha_str *ha = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) list_del(&ha->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) gdth_remove_one(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static int gdth_pci_init_one(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) u16 vendor = pdev->vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) u16 device = pdev->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) unsigned long base0, base1, base2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) gdth_pci_str gdth_pcistr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) gdth_ha_str *ha = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) gdth_ctr_count, vendor, device));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) memset(&gdth_pcistr, 0, sizeof(gdth_pcistr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (vendor == PCI_VENDOR_ID_VORTEX && !gdth_search_vortex(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) rc = pci_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (gdth_ctr_count >= MAXHA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* GDT PCI controller found, resources are already in pdev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) gdth_pcistr.pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) base0 = pci_resource_flags(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) base1 = pci_resource_flags(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) base2 = pci_resource_flags(pdev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (!(base0 & IORESOURCE_MEM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) gdth_pcistr.dpmem = pci_resource_start(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) } else { /* GDT6110, GDT6120, .. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (!(base0 & IORESOURCE_MEM) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) !(base2 & IORESOURCE_MEM) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) !(base1 & IORESOURCE_IO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) gdth_pcistr.dpmem = pci_resource_start(pdev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) gdth_pcistr.io = pci_resource_start(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) gdth_pcistr.pdev->bus->number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) PCI_SLOT(gdth_pcistr.pdev->devfn),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) gdth_pcistr.irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) gdth_pcistr.dpmem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) rc = gdth_pci_probe_one(&gdth_pcistr, &ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) register gdt6_dpram_str __iomem *dp6_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) register gdt6c_dpram_str __iomem *dp6c_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) register gdt6m_dpram_str __iomem *dp6m_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) u32 retries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) u8 prot_ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) u16 command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) int i, found = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) TRACE(("gdth_init_pci()\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (pdev->vendor == PCI_VENDOR_ID_INTEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) ha->oem_id = OEM_ID_INTEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ha->oem_id = OEM_ID_ICP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) ha->brd_phys = (pdev->bus->number << 8) | (pdev->devfn & 0xf8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) ha->stype = (u32)pdev->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) ha->irq = pdev->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) ha->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6_dpram_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (ha->brd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) /* check and reset interface area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) dp6_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) writel(DPMEM_MAGIC, &dp6_ptr->u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (readl(&dp6_ptr->u) != DPMEM_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) pcistr->dpmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) found = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) ha->brd = ioremap(i, sizeof(u16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (ha->brd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (readw(ha->brd) != 0xffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) TRACE2(("init_pci_old() address 0x%x busy\n", i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) ha->brd = ioremap(i, sizeof(gdt6_dpram_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (ha->brd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) dp6_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) writel(DPMEM_MAGIC, &dp6_ptr->u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (readl(&dp6_ptr->u) == DPMEM_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) printk("GDT-PCI: Use free address at 0x%x\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) found = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) printk("GDT-PCI: No free address found!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) memset_io(&dp6_ptr->u, 0, sizeof(dp6_ptr->u));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (readl(&dp6_ptr->u) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) printk("GDT-PCI: Initialization error (DPMEM write error)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /* disable board interrupts, deinit services */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) writeb(0xff, &dp6_ptr->io.irqdel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) writeb(0x00, &dp6_ptr->io.irqen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) writeb(0x00, &dp6_ptr->u.ic.S_Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) writeb(0, &dp6_ptr->io.event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) retries = INIT_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) gdth_delay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) while (readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (--retries == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) printk("GDT-PCI: Initialization error (DEINIT failed)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) prot_ver = (u8)readl(&dp6_ptr->u.ic.S_Info[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) writeb(0, &dp6_ptr->u.ic.S_Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) writeb(0xff, &dp6_ptr->io.irqdel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (prot_ver != PROTOCOL_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) printk("GDT-PCI: Illegal protocol version\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) ha->type = GDT_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ha->ic_all_size = sizeof(dp6_ptr->u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /* special command to controller BIOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) writel(0x00, &dp6_ptr->u.ic.S_Info[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) writeb(0, &dp6_ptr->io.event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) retries = INIT_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) gdth_delay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) while (readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (--retries == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) printk("GDT-PCI: Initialization error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) writeb(0, &dp6_ptr->u.ic.S_Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) writeb(0xff, &dp6_ptr->io.irqdel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ha->dma64_support = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) } else if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) ha->plx = (gdt6c_plx_regs *)pcistr->io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) TRACE2(("init_pci_new() dpmem %lx irq %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) pcistr->dpmem,ha->irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6c_dpram_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (ha->brd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) /* check and reset interface area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) dp6c_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) writel(DPMEM_MAGIC, &dp6c_ptr->u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (readl(&dp6c_ptr->u) != DPMEM_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) pcistr->dpmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) found = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) ha->brd = ioremap(i, sizeof(u16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (ha->brd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (readw(ha->brd) != 0xffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) TRACE2(("init_pci_plx() address 0x%x busy\n", i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) pci_write_config_dword(pdev, PCI_BASE_ADDRESS_2, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) ha->brd = ioremap(i, sizeof(gdt6c_dpram_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (ha->brd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) dp6c_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) writel(DPMEM_MAGIC, &dp6c_ptr->u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (readl(&dp6c_ptr->u) == DPMEM_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) printk("GDT-PCI: Use free address at 0x%x\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) found = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) printk("GDT-PCI: No free address found!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) memset_io(&dp6c_ptr->u, 0, sizeof(dp6c_ptr->u));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (readl(&dp6c_ptr->u) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) printk("GDT-PCI: Initialization error (DPMEM write error)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) /* disable board interrupts, deinit services */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) outb(0x00,PTR2USHORT(&ha->plx->control1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) outb(0xff,PTR2USHORT(&ha->plx->edoor_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) writeb(0x00, &dp6c_ptr->u.ic.S_Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) retries = INIT_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) gdth_delay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) while (readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (--retries == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) printk("GDT-PCI: Initialization error (DEINIT failed)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) prot_ver = (u8)readl(&dp6c_ptr->u.ic.S_Info[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) writeb(0, &dp6c_ptr->u.ic.Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (prot_ver != PROTOCOL_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) printk("GDT-PCI: Illegal protocol version\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ha->type = GDT_PCINEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) ha->ic_all_size = sizeof(dp6c_ptr->u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /* special command to controller BIOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) writel(0x00, &dp6c_ptr->u.ic.S_Info[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) retries = INIT_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) gdth_delay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) while (readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (--retries == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) printk("GDT-PCI: Initialization error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) writeb(0, &dp6c_ptr->u.ic.S_Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) ha->dma64_support = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) } else { /* MPR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6m_dpram_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (ha->brd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) /* manipulate config. space to enable DPMEM, start RP controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) pci_read_config_word(pdev, PCI_COMMAND, &command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) command |= 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) pci_write_config_word(pdev, PCI_COMMAND, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) dp6m_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) /* Ensure that it is safe to access the non HW portions of DPMEM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) * Aditional check needed for Xscale based RAID controllers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) while( ((int)readb(&dp6m_ptr->i960r.sema0_reg) ) & 3 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /* check and reset interface area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) writel(DPMEM_MAGIC, &dp6m_ptr->u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) pcistr->dpmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) found = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) ha->brd = ioremap(i, sizeof(u16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (ha->brd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (readw(ha->brd) != 0xffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) TRACE2(("init_pci_mpr() address 0x%x busy\n", i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) ha->brd = ioremap(i, sizeof(gdt6m_dpram_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) if (ha->brd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) dp6m_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) writel(DPMEM_MAGIC, &dp6m_ptr->u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (readl(&dp6m_ptr->u) == DPMEM_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) printk("GDT-PCI: Use free address at 0x%x\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) found = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) printk("GDT-PCI: No free address found!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) memset_io(&dp6m_ptr->u, 0, sizeof(dp6m_ptr->u));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /* disable board interrupts, deinit services */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) &dp6m_ptr->i960r.edoor_en_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) writeb(0x00, &dp6m_ptr->u.ic.S_Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) writeb(1, &dp6m_ptr->i960r.ldoor_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) retries = INIT_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) gdth_delay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) while (readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (--retries == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) printk("GDT-PCI: Initialization error (DEINIT failed)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) prot_ver = (u8)readl(&dp6m_ptr->u.ic.S_Info[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) writeb(0, &dp6m_ptr->u.ic.S_Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (prot_ver != PROTOCOL_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) printk("GDT-PCI: Illegal protocol version\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) ha->type = GDT_PCIMPR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) ha->ic_all_size = sizeof(dp6m_ptr->u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /* special command to controller BIOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) writel(0x00, &dp6m_ptr->u.ic.S_Info[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) writeb(1, &dp6m_ptr->i960r.ldoor_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) retries = INIT_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) gdth_delay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (--retries == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) printk("GDT-PCI: Initialization error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) writeb(0, &dp6m_ptr->u.ic.S_Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) /* read FW version to detect 64-bit DMA support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) writeb(1, &dp6m_ptr->i960r.ldoor_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) retries = INIT_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) gdth_delay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (--retries == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) printk("GDT-PCI: Initialization error (DEINIT failed)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) iounmap(ha->brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) prot_ver = (u8)(readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) writeb(0, &dp6m_ptr->u.ic.S_Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (prot_ver < 0x2b) /* FW < x.43: no 64-bit DMA support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) ha->dma64_support = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) ha->dma64_support = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) /* controller protocol functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) static void gdth_enable_int(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) gdt6_dpram_str __iomem *dp6_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) gdt6m_dpram_str __iomem *dp6m_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) TRACE(("gdth_enable_int() hanum %d\n",ha->hanum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (ha->type == GDT_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) dp6_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) writeb(1, &dp6_ptr->io.irqdel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) writeb(0, &dp6_ptr->u.ic.Cmd_Index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) writeb(1, &dp6_ptr->io.irqen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) } else if (ha->type == GDT_PCINEW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) outb(0x03, PTR2USHORT(&ha->plx->control1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) } else if (ha->type == GDT_PCIMPR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) dp6m_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) &dp6m_ptr->i960r.edoor_en_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /* return IStatus if interrupt was from this card else 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) static u8 gdth_get_status(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) u8 IStatus = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) TRACE(("gdth_get_status() irq %d ctr_count %d\n", ha->irq, gdth_ctr_count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (ha->type == GDT_PCI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) IStatus =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) else if (ha->type == GDT_PCINEW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) IStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) else if (ha->type == GDT_PCIMPR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) IStatus =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return IStatus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) static int gdth_test_busy(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) register int gdtsema0 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) TRACE(("gdth_test_busy() hanum %d\n", ha->hanum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (ha->type == GDT_PCI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) gdtsema0 = (int)readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) else if (ha->type == GDT_PCINEW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) else if (ha->type == GDT_PCIMPR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) gdtsema0 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) (int)readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return (gdtsema0 & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) static int gdth_get_cmd_index(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) TRACE(("gdth_get_cmd_index() hanum %d\n", ha->hanum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) for (i=0; i<GDTH_MAXCMDS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (ha->cmd_tab[i].cmnd == UNUSED_CMND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) ha->cmd_tab[i].cmnd = ha->pccb->RequestBuffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) ha->cmd_tab[i].service = ha->pccb->Service;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) ha->pccb->CommandIndex = (u32)i+2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return (i+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) static void gdth_set_sema0(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) TRACE(("gdth_set_sema0() hanum %d\n", ha->hanum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (ha->type == GDT_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) writeb(1, &((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) } else if (ha->type == GDT_PCINEW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) outb(1, PTR2USHORT(&ha->plx->sema0_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) } else if (ha->type == GDT_PCIMPR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) static void gdth_copy_command(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) register gdth_cmd_str *cmd_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) register gdt6m_dpram_str __iomem *dp6m_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) register gdt6c_dpram_str __iomem *dp6c_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) gdt6_dpram_str __iomem *dp6_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) u16 cp_count,dp_offset,cmd_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) TRACE(("gdth_copy_command() hanum %d\n", ha->hanum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) cp_count = ha->cmd_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) dp_offset= ha->cmd_offs_dpmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) cmd_no = ha->cmd_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) cmd_ptr = ha->pccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) ++ha->cmd_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) /* set cpcount dword aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (cp_count & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) cp_count += (4 - (cp_count & 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) ha->cmd_offs_dpmem += cp_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) /* set offset and service, copy command to DPMEM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (ha->type == GDT_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) dp6_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) writew(dp_offset + DPMEM_COMMAND_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) writew((u16)cmd_ptr->Service,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) } else if (ha->type == GDT_PCINEW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) dp6c_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) writew(dp_offset + DPMEM_COMMAND_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) writew((u16)cmd_ptr->Service,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) } else if (ha->type == GDT_PCIMPR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) dp6m_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) writew(dp_offset + DPMEM_COMMAND_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) writew((u16)cmd_ptr->Service,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) memcpy_toio(&dp6m_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) static void gdth_release_event(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) TRACE(("gdth_release_event() hanum %d\n", ha->hanum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) #ifdef GDTH_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) u32 i,j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) for (i=0,j=0; j<GDTH_MAXCMDS; ++j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (ha->cmd_tab[j].cmnd != UNUSED_CMND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) ++i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (max_index < i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) max_index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) TRACE3(("GDT: max_index = %d\n",(u16)i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (ha->pccb->OpCode == GDT_INIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) ha->pccb->Service |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (ha->type == GDT_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) writeb(0, &((gdt6_dpram_str __iomem *)ha->brd)->io.event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) } else if (ha->type == GDT_PCINEW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) } else if (ha->type == GDT_PCIMPR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.ldoor_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) static int gdth_wait(gdth_ha_str *ha, int index, u32 time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) int answer_found = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) int wait_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) TRACE(("gdth_wait() hanum %d index %d time %d\n", ha->hanum, index, time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) if (index == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) return 1; /* no wait required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) __gdth_interrupt(ha, true, &wait_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (wait_index == index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) answer_found = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) } while (--time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) while (gdth_test_busy(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) gdth_delay(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return (answer_found);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) static int gdth_internal_cmd(gdth_ha_str *ha, u8 service, u16 opcode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) u32 p1, u64 p2, u64 p3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) register gdth_cmd_str *cmd_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) int retries,index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) TRACE2(("gdth_internal_cmd() service %d opcode %d\n",service,opcode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) cmd_ptr = ha->pccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) memset((char*)cmd_ptr,0,sizeof(gdth_cmd_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) /* make command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) for (retries = INIT_RETRIES;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) cmd_ptr->Service = service;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) cmd_ptr->RequestBuffer = INTERNAL_CMND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (!(index=gdth_get_cmd_index(ha))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) TRACE(("GDT: No free command index found\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) gdth_set_sema0(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) cmd_ptr->OpCode = opcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) cmd_ptr->BoardNode = LOCALBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if (service == CACHESERVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (opcode == GDT_IOCTL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) cmd_ptr->u.ioctl.subfunc = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) cmd_ptr->u.ioctl.channel = (u32)p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) cmd_ptr->u.ioctl.param_size = (u16)p3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) cmd_ptr->u.ioctl.p_param = ha->scratch_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (ha->cache_feat & GDT_64BIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) cmd_ptr->u.cache64.DeviceNo = (u16)p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) cmd_ptr->u.cache64.BlockNo = p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) cmd_ptr->u.cache.DeviceNo = (u16)p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) cmd_ptr->u.cache.BlockNo = (u32)p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) } else if (service == SCSIRAWSERVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (ha->raw_feat & GDT_64BIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) cmd_ptr->u.raw64.direction = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) cmd_ptr->u.raw64.bus = (u8)p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) cmd_ptr->u.raw64.target = (u8)p3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) cmd_ptr->u.raw64.lun = (u8)(p3 >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) cmd_ptr->u.raw.direction = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) cmd_ptr->u.raw.bus = (u8)p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) cmd_ptr->u.raw.target = (u8)p3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) cmd_ptr->u.raw.lun = (u8)(p3 >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) } else if (service == SCREENSERVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if (opcode == GDT_REALTIME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) *(u32 *)&cmd_ptr->u.screen.su.data[0] = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) *(u32 *)&cmd_ptr->u.screen.su.data[4] = (u32)p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) *(u32 *)&cmd_ptr->u.screen.su.data[8] = (u32)p3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) ha->cmd_len = sizeof(gdth_cmd_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) ha->cmd_offs_dpmem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) ha->cmd_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) gdth_copy_command(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) gdth_release_event(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) gdth_delay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (!gdth_wait(ha, index, INIT_TIMEOUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) printk("GDT: Initialization error (timeout service %d)\n",service);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) if (ha->status != S_BSY || --retries == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) return (ha->status != S_OK ? 0:1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) /* search for devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) static int gdth_search_drives(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) u16 cdev_cnt, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) int ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) u32 bus_no, drv_cnt, drv_no, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) gdth_getch_str *chn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) gdth_drlist_str *drl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) gdth_iochan_str *ioc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) gdth_raw_iochan_str *iocr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) gdth_arcdl_str *alst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) gdth_alist_str *alst2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) gdth_oem_str_ioctl *oemstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) TRACE(("gdth_search_drives() hanum %d\n", ha->hanum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) ok = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) /* initialize controller services, at first: screen service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) ha->screen_feat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (!force_dma32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) ok = gdth_internal_cmd(ha, SCREENSERVICE, GDT_X_INIT_SCR, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) ha->screen_feat = GDT_64BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (force_dma32 || (!ok && ha->status == (u16)S_NOFUNC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) ok = gdth_internal_cmd(ha, SCREENSERVICE, GDT_INIT, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (!ok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) printk("GDT-HA %d: Initialization error screen service (code %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) ha->hanum, ha->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) /* unfreeze all IOs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) gdth_internal_cmd(ha, CACHESERVICE, GDT_UNFREEZE_IO, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) /* initialize cache service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) ha->cache_feat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (!force_dma32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) ok = gdth_internal_cmd(ha, CACHESERVICE, GDT_X_INIT_HOST, LINUX_OS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) ha->cache_feat = GDT_64BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) if (force_dma32 || (!ok && ha->status == (u16)S_NOFUNC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) ok = gdth_internal_cmd(ha, CACHESERVICE, GDT_INIT, LINUX_OS, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (!ok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) printk("GDT-HA %d: Initialization error cache service (code %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) ha->hanum, ha->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) cdev_cnt = (u16)ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) ha->fw_vers = ha->service;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) /* detect number of buses - try new IOCTL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) iocr = (gdth_raw_iochan_str *)ha->pscratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) iocr->hdr.version = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) iocr->hdr.list_entries = MAXBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) iocr->hdr.first_chan = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) iocr->hdr.last_chan = MAXBUS-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) iocr->hdr.list_offset = GDTOFFSOF(gdth_raw_iochan_str, list[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, IOCHAN_RAW_DESC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) INVALID_CHANNEL,sizeof(gdth_raw_iochan_str))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) TRACE2(("IOCHAN_RAW_DESC supported!\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) ha->bus_cnt = iocr->hdr.chan_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) if (iocr->list[bus_no].proc_id < MAXID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) ha->bus_id[bus_no] = iocr->list[bus_no].proc_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) ha->bus_id[bus_no] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) /* old method */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) chn = (gdth_getch_str *)ha->pscratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) for (bus_no = 0; bus_no < MAXBUS; ++bus_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) chn->channel_no = bus_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) SCSI_CHAN_CNT | L_CTRL_PATTERN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) IO_CHANNEL | INVALID_CHANNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) sizeof(gdth_getch_str))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) if (bus_no == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) printk("GDT-HA %d: Error detecting channel count (0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) ha->hanum, ha->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (chn->siop_id < MAXID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) ha->bus_id[bus_no] = chn->siop_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) ha->bus_id[bus_no] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) ha->bus_cnt = (u8)bus_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) /* read cache configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) printk("GDT-HA %d: Initialization error cache service (code %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) ha->hanum, ha->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) TRACE2(("gdth_search_drives() cinfo: vs %x sta %d str %d dw %d b %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) ha->cpar.version,ha->cpar.state,ha->cpar.strategy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) ha->cpar.write_back,ha->cpar.block_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) /* read board info and features */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) ha->more_proc = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, BOARD_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) memcpy(&ha->binfo, (gdth_binfo_str *)ha->pscratch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) sizeof(gdth_binfo_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, BOARD_FEATURES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) INVALID_CHANNEL,sizeof(gdth_bfeat_str))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) ha->bfeat = *(gdth_bfeat_str *)ha->pscratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) ha->more_proc = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) TRACE2(("BOARD_INFO requires firmware >= 1.10/2.08\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) strcpy(ha->binfo.type_string, gdth_ctr_name(ha));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) TRACE2(("Controller name: %s\n",ha->binfo.type_string));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) /* read more informations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (ha->more_proc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) /* physical drives, channel addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) ioc = (gdth_iochan_str *)ha->pscratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) ioc->hdr.version = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) ioc->hdr.list_entries = MAXBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) ioc->hdr.first_chan = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) ioc->hdr.last_chan = MAXBUS-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) ioc->hdr.list_offset = GDTOFFSOF(gdth_iochan_str, list[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, IOCHAN_DESC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) ha->raw[bus_no].address = ioc->list[bus_no].address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) ha->raw[bus_no].local_no = ioc->list[bus_no].local_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) ha->raw[bus_no].address = IO_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) ha->raw[bus_no].local_no = bus_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) chn = (gdth_getch_str *)ha->pscratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) chn->channel_no = ha->raw[bus_no].local_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) SCSI_CHAN_CNT | L_CTRL_PATTERN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) ha->raw[bus_no].address | INVALID_CHANNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) sizeof(gdth_getch_str))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) ha->raw[bus_no].pdev_cnt = chn->drive_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) TRACE2(("Channel %d: %d phys. drives\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) bus_no,chn->drive_cnt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) if (ha->raw[bus_no].pdev_cnt > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) drl = (gdth_drlist_str *)ha->pscratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) drl->sc_no = ha->raw[bus_no].local_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) drl->sc_cnt = ha->raw[bus_no].pdev_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) SCSI_DR_LIST | L_CTRL_PATTERN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) ha->raw[bus_no].address | INVALID_CHANNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) sizeof(gdth_drlist_str))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) for (j = 0; j < ha->raw[bus_no].pdev_cnt; ++j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) ha->raw[bus_no].id_list[j] = drl->sc_list[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) ha->raw[bus_no].pdev_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) /* logical drives */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_DRV_CNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) INVALID_CHANNEL,sizeof(u32))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) drv_cnt = *(u32 *)ha->pscratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_DRV_LIST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) INVALID_CHANNEL,drv_cnt * sizeof(u32))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) for (j = 0; j < drv_cnt; ++j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) drv_no = ((u32 *)ha->pscratch)[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) if (drv_no < MAX_LDRIVES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) ha->hdr[drv_no].is_logdrv = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) TRACE2(("Drive %d is log. drive\n",drv_no));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) alst = (gdth_arcdl_str *)ha->pscratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) alst->entries_avail = MAX_LDRIVES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) alst->first_entry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) alst->list_offset = GDTOFFSOF(gdth_arcdl_str, list[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) ARRAY_DRV_LIST2 | LA_CTRL_PATTERN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) INVALID_CHANNEL, sizeof(gdth_arcdl_str) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) (alst->entries_avail-1) * sizeof(gdth_alist_str))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) for (j = 0; j < alst->entries_init; ++j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) ha->hdr[j].is_arraydrv = alst->list[j].is_arrayd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) ha->hdr[j].is_master = alst->list[j].is_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) ha->hdr[j].is_parity = alst->list[j].is_parity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) ha->hdr[j].is_hotfix = alst->list[j].is_hotfix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) ha->hdr[j].master_no = alst->list[j].cd_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) } else if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) ARRAY_DRV_LIST | LA_CTRL_PATTERN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 0, 35 * sizeof(gdth_alist_str))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) for (j = 0; j < 35; ++j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) alst2 = &((gdth_alist_str *)ha->pscratch)[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) ha->hdr[j].is_arraydrv = alst2->is_arrayd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) ha->hdr[j].is_master = alst2->is_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) ha->hdr[j].is_parity = alst2->is_parity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) ha->hdr[j].is_hotfix = alst2->is_hotfix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) ha->hdr[j].master_no = alst2->cd_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) /* initialize raw service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) ha->raw_feat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if (!force_dma32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) ok = gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_X_INIT_RAW, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) ha->raw_feat = GDT_64BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) if (force_dma32 || (!ok && ha->status == (u16)S_NOFUNC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) ok = gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_INIT, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (!ok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) printk("GDT-HA %d: Initialization error raw service (code %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) ha->hanum, ha->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) /* set/get features raw service (scatter/gather) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) if (gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_SET_FEAT, SCATTER_GATHER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 0, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_GET_FEAT, 0, 0, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) ha->info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) ha->raw_feat |= (u16)ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) /* set/get features cache service (equal to raw service) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_SET_FEAT, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) SCATTER_GATHER,0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_GET_FEAT, 0, 0, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) ha->info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) ha->cache_feat |= (u16)ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) /* reserve drives for raw service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if (reserve_mode != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_RESERVE_ALL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) reserve_mode == 1 ? 1 : 3, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) ha->status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) for (i = 0; i < MAX_RES_ARGS; i += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (reserve_list[i] == ha->hanum && reserve_list[i+1] < ha->bus_cnt &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) reserve_list[i+2] < ha->tid_cnt && reserve_list[i+3] < MAXLUN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d lun %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) reserve_list[i], reserve_list[i+1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) reserve_list[i+2], reserve_list[i+3]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (!gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_RESERVE, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) reserve_list[i+1], reserve_list[i+2] |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) (reserve_list[i+3] << 8))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) printk("GDT-HA %d: Error raw service (RESERVE, code %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) ha->hanum, ha->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) /* Determine OEM string using IOCTL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) oemstr = (gdth_oem_str_ioctl *)ha->pscratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) oemstr->params.ctl_version = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) oemstr->params.buffer_size = sizeof(oemstr->text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) sizeof(gdth_oem_str_ioctl))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) printk("GDT-HA %d: Vendor: %s Name: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) ha->hanum, oemstr->text.oem_company_name, ha->binfo.type_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) /* Save the Host Drive inquiry data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) strlcpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) sizeof(ha->oem_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) /* Old method, based on PCI ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) printk("GDT-HA %d: Name: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) ha->hanum, ha->binfo.type_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) if (ha->oem_id == OEM_ID_INTEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) strlcpy(ha->oem_name,"Intel ", sizeof(ha->oem_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) strlcpy(ha->oem_name,"ICP ", sizeof(ha->oem_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) /* scanning for host drives */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) for (i = 0; i < cdev_cnt; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) gdth_analyse_hdrive(ha, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) TRACE(("gdth_search_drives() OK\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) static int gdth_analyse_hdrive(gdth_ha_str *ha, u16 hdrive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) u32 drv_cyls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) int drv_hds, drv_secs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n", ha->hanum, hdrive));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (hdrive >= MAX_HDRIVES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_INFO, hdrive, 0, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) ha->hdr[hdrive].present = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) ha->hdr[hdrive].size = ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) /* evaluate mapping (sectors per head, heads per cylinder) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) ha->hdr[hdrive].size &= ~SECS32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) if (ha->info2 == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) gdth_eval_mapping(ha->hdr[hdrive].size,&drv_cyls,&drv_hds,&drv_secs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) drv_hds = ha->info2 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) drv_secs = (ha->info2 >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) drv_cyls = (u32)ha->hdr[hdrive].size / drv_hds / drv_secs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) ha->hdr[hdrive].heads = (u8)drv_hds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) ha->hdr[hdrive].secs = (u8)drv_secs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) /* round size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) ha->hdr[hdrive].size = drv_cyls * drv_hds * drv_secs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) if (ha->cache_feat & GDT_64BIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_X_INFO, hdrive, 0, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) && ha->info2 != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) ha->hdr[hdrive].size = ((u64)ha->info2 << 32) | ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) /* get informations about device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_DEVTYPE, hdrive, 0, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) TRACE2(("gdth_search_dr() cache drive %d devtype %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) hdrive,ha->info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) ha->hdr[hdrive].devtype = (u16)ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) /* cluster info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_CLUST_INFO, hdrive, 0, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) TRACE2(("gdth_search_dr() cache drive %d cluster info %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) hdrive,ha->info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) if (!shared_access)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) ha->hdr[hdrive].cluster_type = (u8)ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) /* R/W attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (gdth_internal_cmd(ha, CACHESERVICE, GDT_RW_ATTRIBS, hdrive, 0, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) TRACE2(("gdth_search_dr() cache drive %d r/w attrib. %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) hdrive,ha->info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) ha->hdr[hdrive].rw_attribs = (u8)ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) /* command queueing/sending functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) static void gdth_putq(gdth_ha_str *ha, struct scsi_cmnd *scp, u8 priority)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) register struct scsi_cmnd *pscp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) register struct scsi_cmnd *nscp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) TRACE(("gdth_putq() priority %d\n",priority));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) if (!cmndinfo->internal_command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) cmndinfo->priority = priority;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) if (ha->req_first==NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) ha->req_first = scp; /* queue was empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) scp->SCp.ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) } else { /* queue not empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) pscp = ha->req_first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) nscp = (struct scsi_cmnd *)pscp->SCp.ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) /* priority: 0-highest,..,0xff-lowest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) while (nscp && gdth_cmnd_priv(nscp)->priority <= priority) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) pscp = nscp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) nscp = (struct scsi_cmnd *)pscp->SCp.ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) pscp->SCp.ptr = (char *)scp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) scp->SCp.ptr = (char *)nscp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) #ifdef GDTH_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) for (nscp=ha->req_first; nscp; nscp=(struct scsi_cmnd*)nscp->SCp.ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) ++flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if (max_rq < flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) max_rq = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) TRACE3(("GDT: max_rq = %d\n",(u16)max_rq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) static void gdth_next(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) register struct scsi_cmnd *pscp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) register struct scsi_cmnd *nscp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) u8 b, t, l, firsttime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) u8 this_cmd, next_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) int cmd_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) TRACE(("gdth_next() hanum %d\n", ha->hanum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) if (!gdth_polling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) this_cmd = firsttime = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) next_cmd = gdth_polling ? FALSE:TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) cmd_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) for (nscp = pscp = ha->req_first; nscp; nscp = (struct scsi_cmnd *)nscp->SCp.ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) struct gdth_cmndinfo *nscp_cmndinfo = gdth_cmnd_priv(nscp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) if (nscp != pscp && nscp != (struct scsi_cmnd *)pscp->SCp.ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) pscp = (struct scsi_cmnd *)pscp->SCp.ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) if (!nscp_cmndinfo->internal_command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) b = nscp->device->channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) t = nscp->device->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) l = nscp->device->lun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) if (nscp_cmndinfo->priority >= DEFAULT_PRI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) b = t = l = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) if (firsttime) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) if (gdth_test_busy(ha)) { /* controller busy ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) TRACE(("gdth_next() controller %d busy !\n", ha->hanum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) if (!gdth_polling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) while (gdth_test_busy(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) gdth_delay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) firsttime = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) if (!nscp_cmndinfo->internal_command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) if (nscp_cmndinfo->phase == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) nscp_cmndinfo->phase = CACHESERVICE; /* default: cache svc. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) if (nscp->cmnd[0] == TEST_UNIT_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) b, t, l));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) /* TEST_UNIT_READY -> set scan mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) if ((ha->scan_mode & 0x0f) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if (b == 0 && t == 0 && l == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) ha->scan_mode |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) } else if ((ha->scan_mode & 0x0f) == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) if (b == 0 && ((t == 0 && l == 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) (t == 1 && l == 0))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) nscp_cmndinfo->OpCode = GDT_SCAN_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) nscp_cmndinfo->phase = ((ha->scan_mode & 0x10 ? 1:0) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) | SCSIRAWSERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) ha->scan_mode = 0x12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) TRACE2(("Scan mode: 0x%x (SCAN_START)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) ha->scan_mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) ha->scan_mode &= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) } else if (ha->scan_mode == 0x12) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) if (b == ha->bus_cnt && t == ha->tid_cnt-1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) nscp_cmndinfo->phase = SCSIRAWSERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) nscp_cmndinfo->OpCode = GDT_SCAN_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) ha->scan_mode &= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) TRACE2(("Scan mode: 0x%x (SCAN_END)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) ha->scan_mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) if (b == ha->virt_bus && nscp->cmnd[0] != INQUIRY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) nscp->cmnd[0] != READ_CAPACITY && nscp->cmnd[0] != MODE_SENSE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) (ha->hdr[t].cluster_type & CLUSTER_DRIVE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) /* always GDT_CLUST_INFO! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) nscp_cmndinfo->OpCode = GDT_CLUST_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) if (nscp_cmndinfo->OpCode != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) if ((nscp_cmndinfo->phase & 0xff) == CACHESERVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) this_cmd = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) next_cmd = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) } else if ((nscp_cmndinfo->phase & 0xff) == SCSIRAWSERVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) if (!(cmd_index=gdth_fill_raw_cmd(ha, nscp, BUS_L2P(ha, b))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) this_cmd = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) next_cmd = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) memset((char*)nscp->sense_buffer,0,16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) nscp->sense_buffer[0] = 0x70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) nscp->sense_buffer[2] = NOT_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) if (!nscp_cmndinfo->wait_for_completion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) nscp_cmndinfo->wait_for_completion++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) gdth_scsi_done(nscp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) } else if (gdth_cmnd_priv(nscp)->internal_command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) if (!(cmd_index=gdth_special_cmd(ha, nscp)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) this_cmd = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) next_cmd = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) } else if (b != ha->virt_bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) !(cmd_index=gdth_fill_raw_cmd(ha, nscp, BUS_L2P(ha, b))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) this_cmd = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) ha->raw[BUS_L2P(ha,b)].io_cnt[t]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) } else if (t >= MAX_HDRIVES || !ha->hdr[t].present || l != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) nscp->cmnd[0], b, t, l));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) nscp->result = DID_BAD_TARGET << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) if (!nscp_cmndinfo->wait_for_completion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) nscp_cmndinfo->wait_for_completion++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) gdth_scsi_done(nscp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) switch (nscp->cmnd[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) case TEST_UNIT_READY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) case INQUIRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) case REQUEST_SENSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) case READ_CAPACITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) case VERIFY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) case START_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) case MODE_SENSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) case SERVICE_ACTION_IN_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) nscp->cmnd[4],nscp->cmnd[5]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if (ha->hdr[t].media_changed && nscp->cmnd[0] != INQUIRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) /* return UNIT_ATTENTION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) nscp->cmnd[0], t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) ha->hdr[t].media_changed = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) memset((char*)nscp->sense_buffer,0,16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) nscp->sense_buffer[0] = 0x70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) nscp->sense_buffer[2] = UNIT_ATTENTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) if (!nscp_cmndinfo->wait_for_completion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) nscp_cmndinfo->wait_for_completion++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) gdth_scsi_done(nscp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) } else if (gdth_internal_cache_cmd(ha, nscp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) gdth_scsi_done(nscp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) case ALLOW_MEDIUM_REMOVAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) nscp->cmnd[4],nscp->cmnd[5]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if ( (nscp->cmnd[4]&1) && !(ha->hdr[t].devtype&1) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) TRACE(("Prevent r. nonremov. drive->do nothing\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) nscp->result = DID_OK << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) nscp->sense_buffer[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) if (!nscp_cmndinfo->wait_for_completion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) nscp_cmndinfo->wait_for_completion++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) gdth_scsi_done(nscp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) TRACE(("Prevent/allow r. %d rem. drive %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) nscp->cmnd[4],nscp->cmnd[3]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) this_cmd = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) case RESERVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) case RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) TRACE2(("cache cmd %s\n",nscp->cmnd[0] == RESERVE ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) "RESERVE" : "RELEASE"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) this_cmd = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) case READ_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) case WRITE_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) case READ_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) case WRITE_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) case READ_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) case WRITE_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) if (ha->hdr[t].media_changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) /* return UNIT_ATTENTION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) nscp->cmnd[0], t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) ha->hdr[t].media_changed = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) memset((char*)nscp->sense_buffer,0,16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) nscp->sense_buffer[0] = 0x70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) nscp->sense_buffer[2] = UNIT_ATTENTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) if (!nscp_cmndinfo->wait_for_completion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) nscp_cmndinfo->wait_for_completion++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) gdth_scsi_done(nscp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) } else if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) this_cmd = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp->cmnd[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) nscp->cmnd[4],nscp->cmnd[5]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) printk("GDT-HA %d: Unknown SCSI command 0x%x to cache service !\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) ha->hanum, nscp->cmnd[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) nscp->result = DID_ABORT << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) if (!nscp_cmndinfo->wait_for_completion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) nscp_cmndinfo->wait_for_completion++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) gdth_scsi_done(nscp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) if (!this_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) if (nscp == ha->req_first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) ha->req_first = pscp = (struct scsi_cmnd *)nscp->SCp.ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) pscp->SCp.ptr = nscp->SCp.ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) if (!next_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) if (ha->cmd_cnt > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) gdth_release_event(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) if (!gdth_polling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) if (gdth_polling && ha->cmd_cnt > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) if (!gdth_wait(ha, cmd_index, POLL_TIMEOUT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) printk("GDT-HA %d: Command %d timed out !\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) ha->hanum, cmd_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) * gdth_copy_internal_data() - copy to/from a buffer onto a scsi_cmnd's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) * buffers, kmap_atomic() as needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) static void gdth_copy_internal_data(gdth_ha_str *ha, struct scsi_cmnd *scp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) char *buffer, u16 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) u16 cpcount,i, max_sg = scsi_sg_count(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) u16 cpsum,cpnow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) struct scatterlist *sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) char *address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) cpcount = min_t(u16, count, scsi_bufflen(scp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) if (cpcount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) cpsum=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) scsi_for_each_sg(scp, sl, max_sg, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) cpnow = (u16)sl->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) TRACE(("copy_internal() now %d sum %d count %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) cpnow, cpsum, cpcount, scsi_bufflen(scp)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) if (cpsum+cpnow > cpcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) cpnow = cpcount - cpsum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) cpsum += cpnow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) if (!sg_page(sl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) ha->hanum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) address = kmap_atomic(sg_page(sl)) + sl->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) memcpy(address, buffer, cpnow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) flush_dcache_page(sg_page(sl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) kunmap_atomic(address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) if (cpsum == cpcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) buffer += cpnow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) } else if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) printk("GDT-HA %d: SCSI command with no buffers but data transfer expected!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) ha->hanum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) static int gdth_internal_cache_cmd(gdth_ha_str *ha, struct scsi_cmnd *scp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) u8 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) gdth_inq_data inq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) gdth_rdcap_data rdc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) gdth_sense_data sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) gdth_modep_data mpd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) t = scp->device->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) scp->cmnd[0],t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) scp->result = DID_OK << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) scp->sense_buffer[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) switch (scp->cmnd[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) case TEST_UNIT_READY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) case VERIFY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) case START_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) TRACE2(("Test/Verify/Start hdrive %d\n",t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) case INQUIRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) TRACE2(("Inquiry hdrive %d devtype %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) t,ha->hdr[t].devtype));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) inq.type_qual = (ha->hdr[t].devtype&4) ? TYPE_ROM:TYPE_DISK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) /* you can here set all disks to removable, if you want to do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) a flush using the ALLOW_MEDIUM_REMOVAL command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) inq.modif_rmb = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) if ((ha->hdr[t].devtype & 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) (ha->hdr[t].cluster_type & CLUSTER_DRIVE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) inq.modif_rmb = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) inq.version = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) inq.resp_aenc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) inq.add_length= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) strcpy(inq.vendor,ha->oem_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) snprintf(inq.product, sizeof(inq.product), "Host Drive #%02d",t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) strcpy(inq.revision," ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) case REQUEST_SENSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) TRACE2(("Request sense hdrive %d\n",t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) sd.errorcode = 0x70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) sd.segno = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) sd.key = NO_SENSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) sd.info = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) sd.add_length= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) case MODE_SENSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) TRACE2(("Mode sense hdrive %d\n",t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) memset((char*)&mpd,0,sizeof(gdth_modep_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) mpd.hd.data_length = sizeof(gdth_modep_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) mpd.hd.dev_par = (ha->hdr[t].devtype&2) ? 0x80:0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) mpd.hd.bd_length = sizeof(mpd.bd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) case READ_CAPACITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) TRACE2(("Read capacity hdrive %d\n",t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) if (ha->hdr[t].size > (u64)0xffffffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) rdc.last_block_no = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) rdc.block_length = cpu_to_be32(SECTOR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) case SERVICE_ACTION_IN_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) if ((scp->cmnd[1] & 0x1f) == SAI_READ_CAPACITY_16 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) (ha->cache_feat & GDT_64BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) gdth_rdcap16_data rdc16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) TRACE2(("Read capacity (16) hdrive %d\n",t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) rdc16.block_length = cpu_to_be32(SECTOR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) gdth_copy_internal_data(ha, scp, (char*)&rdc16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) sizeof(gdth_rdcap16_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) scp->result = DID_ABORT << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) if (!cmndinfo->wait_for_completion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) cmndinfo->wait_for_completion++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) static int gdth_fill_cache_cmd(gdth_ha_str *ha, struct scsi_cmnd *scp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) u16 hdrive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) register gdth_cmd_str *cmdp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) u32 cnt, blockcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) u64 no, blockno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) int i, cmd_index, read_write, sgcnt, mode64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) cmdp = ha->pccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) scp->cmnd[0],scp->cmd_len,hdrive));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) mode64 = (ha->cache_feat & GDT_64BIT) ? TRUE : FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) /* test for READ_16, WRITE_16 if !mode64 ? ---
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) not required, should not occur due to error return on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) READ_CAPACITY_16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) cmdp->Service = CACHESERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) cmdp->RequestBuffer = scp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) /* search free command index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) if (!(cmd_index=gdth_get_cmd_index(ha))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) TRACE(("GDT: No free command index found\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) /* if it's the first command, set command semaphore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) if (ha->cmd_cnt == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) gdth_set_sema0(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) /* fill command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) read_write = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) if (cmndinfo->OpCode != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) cmdp->OpCode = cmndinfo->OpCode; /* special cache cmd. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) else if (scp->cmnd[0] == RESERVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) cmdp->OpCode = GDT_RESERVE_DRV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) else if (scp->cmnd[0] == RELEASE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) cmdp->OpCode = GDT_RELEASE_DRV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) else if (scp->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) if (scp->cmnd[4] & 1) /* prevent ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) cmdp->OpCode = GDT_MOUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) else if (scp->cmnd[3] & 1) /* removable drive ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) cmdp->OpCode = GDT_UNMOUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) cmdp->OpCode = GDT_FLUSH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) scp->cmnd[0] == WRITE_12 || scp->cmnd[0] == WRITE_16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) read_write = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) (ha->cache_feat & GDT_WR_THROUGH)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) cmdp->OpCode = GDT_WRITE_THR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) cmdp->OpCode = GDT_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) read_write = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) cmdp->OpCode = GDT_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) cmdp->BoardNode = LOCALBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) if (mode64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) cmdp->u.cache64.DeviceNo = hdrive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) cmdp->u.cache64.BlockNo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) cmdp->u.cache64.sg_canz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) cmdp->u.cache.DeviceNo = hdrive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) cmdp->u.cache.BlockNo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) cmdp->u.cache.sg_canz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) if (read_write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) if (scp->cmd_len == 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) memcpy(&no, &scp->cmnd[2], sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) blockno = be64_to_cpu(no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) memcpy(&cnt, &scp->cmnd[10], sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) blockcnt = be32_to_cpu(cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) } else if (scp->cmd_len == 10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) memcpy(&no, &scp->cmnd[2], sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) blockno = be32_to_cpu(no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) memcpy(&cnt, &scp->cmnd[7], sizeof(u16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) blockcnt = be16_to_cpu(cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) memcpy(&no, &scp->cmnd[0], sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) blockno = be32_to_cpu(no) & 0x001fffffUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) blockcnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) if (mode64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) cmdp->u.cache64.BlockNo = blockno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) cmdp->u.cache64.BlockCnt = blockcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) cmdp->u.cache.BlockNo = (u32)blockno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) cmdp->u.cache.BlockCnt = blockcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) if (scsi_bufflen(scp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) cmndinfo->dma_dir = (read_write == 1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) DMA_TO_DEVICE : DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) sgcnt = dma_map_sg(&ha->pdev->dev, scsi_sglist(scp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) scsi_sg_count(scp), cmndinfo->dma_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) if (mode64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) struct scatterlist *sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) cmdp->u.cache64.DestAddr= (u64)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) cmdp->u.cache64.sg_canz = sgcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) scsi_for_each_sg(scp, sl, sgcnt, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) cmdp->u.cache64.sg_lst[i].sg_ptr = sg_dma_address(sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) cmdp->u.cache64.sg_lst[i].sg_len = sg_dma_len(sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) struct scatterlist *sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) cmdp->u.cache.DestAddr= 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) cmdp->u.cache.sg_canz = sgcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) scsi_for_each_sg(scp, sl, sgcnt, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) cmdp->u.cache.sg_lst[i].sg_ptr = sg_dma_address(sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) #ifdef GDTH_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) if (max_sg < (u32)sgcnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) max_sg = (u32)sgcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) TRACE3(("GDT: max_sg = %d\n",max_sg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) /* evaluate command size, check space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) if (mode64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) cmdp->u.cache64.DestAddr,cmdp->u.cache64.sg_canz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) cmdp->u.cache64.sg_lst[0].sg_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) cmdp->u.cache64.sg_lst[0].sg_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) cmdp->OpCode,cmdp->u.cache64.BlockNo,cmdp->u.cache64.BlockCnt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) (u16)cmdp->u.cache64.sg_canz * sizeof(gdth_sg64_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) cmdp->u.cache.sg_lst[0].sg_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) cmdp->u.cache.sg_lst[0].sg_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) (u16)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) if (ha->cmd_len & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) ha->cmd_len += (4 - (ha->cmd_len & 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) if (ha->cmd_cnt > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) ha->ic_all_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) TRACE2(("gdth_fill_cache() DPMEM overflow\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) /* copy command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) gdth_copy_command(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) return cmd_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) static int gdth_fill_raw_cmd(gdth_ha_str *ha, struct scsi_cmnd *scp, u8 b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) register gdth_cmd_str *cmdp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) u16 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) dma_addr_t sense_paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) int cmd_index, sgcnt, mode64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) u8 t,l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) struct gdth_cmndinfo *cmndinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) t = scp->device->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) l = scp->device->lun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) cmdp = ha->pccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) scp->cmnd[0],b,t,l));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) mode64 = (ha->raw_feat & GDT_64BIT) ? TRUE : FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) cmdp->Service = SCSIRAWSERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) cmdp->RequestBuffer = scp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) /* search free command index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) if (!(cmd_index=gdth_get_cmd_index(ha))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) TRACE(("GDT: No free command index found\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) /* if it's the first command, set command semaphore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) if (ha->cmd_cnt == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) gdth_set_sema0(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) cmndinfo = gdth_cmnd_priv(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) /* fill command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) if (cmndinfo->OpCode != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) cmdp->OpCode = cmndinfo->OpCode; /* special raw cmd. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) cmdp->BoardNode = LOCALBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) if (mode64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) cmdp->u.raw64.direction = (cmndinfo->phase >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) TRACE2(("special raw cmd 0x%x param 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) cmdp->OpCode, cmdp->u.raw64.direction));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) /* evaluate command size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) cmdp->u.raw.direction = (cmndinfo->phase >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) TRACE2(("special raw cmd 0x%x param 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) cmdp->OpCode, cmdp->u.raw.direction));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) /* evaluate command size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) sense_paddr = dma_map_single(&ha->pdev->dev, scp->sense_buffer, 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) cmndinfo->sense_paddr = sense_paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) cmdp->OpCode = GDT_WRITE; /* always */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) cmdp->BoardNode = LOCALBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) if (mode64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) cmdp->u.raw64.reserved = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) cmdp->u.raw64.mdisc_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) cmdp->u.raw64.mcon_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) cmdp->u.raw64.clen = scp->cmd_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) cmdp->u.raw64.target = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) cmdp->u.raw64.lun = l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) cmdp->u.raw64.bus = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) cmdp->u.raw64.priority = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) cmdp->u.raw64.sdlen = scsi_bufflen(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) cmdp->u.raw64.sense_len = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) cmdp->u.raw64.sense_data = sense_paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) cmdp->u.raw64.direction =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) memcpy(cmdp->u.raw64.cmd,scp->cmnd,16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) cmdp->u.raw64.sg_ranz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) cmdp->u.raw.reserved = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) cmdp->u.raw.mdisc_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) cmdp->u.raw.mcon_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) cmdp->u.raw.clen = scp->cmd_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) cmdp->u.raw.target = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) cmdp->u.raw.lun = l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) cmdp->u.raw.bus = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) cmdp->u.raw.priority = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) cmdp->u.raw.link_p = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) cmdp->u.raw.sdlen = scsi_bufflen(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) cmdp->u.raw.sense_len = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) cmdp->u.raw.sense_data = sense_paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) cmdp->u.raw.direction =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) cmdp->u.raw.sg_ranz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) if (scsi_bufflen(scp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) cmndinfo->dma_dir = DMA_BIDIRECTIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) sgcnt = dma_map_sg(&ha->pdev->dev, scsi_sglist(scp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) scsi_sg_count(scp), cmndinfo->dma_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) if (mode64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) struct scatterlist *sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) cmdp->u.raw64.sdata = (u64)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) cmdp->u.raw64.sg_ranz = sgcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) scsi_for_each_sg(scp, sl, sgcnt, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) cmdp->u.raw64.sg_lst[i].sg_ptr = sg_dma_address(sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) cmdp->u.raw64.sg_lst[i].sg_len = sg_dma_len(sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) struct scatterlist *sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) cmdp->u.raw.sdata = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) cmdp->u.raw.sg_ranz = sgcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) scsi_for_each_sg(scp, sl, sgcnt, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) cmdp->u.raw.sg_lst[i].sg_ptr = sg_dma_address(sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) #ifdef GDTH_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) if (max_sg < sgcnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) max_sg = sgcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) TRACE3(("GDT: max_sg = %d\n",sgcnt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) if (mode64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) cmdp->u.raw64.sdata,cmdp->u.raw64.sg_ranz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) cmdp->u.raw64.sg_lst[0].sg_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) cmdp->u.raw64.sg_lst[0].sg_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) /* evaluate command size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) (u16)cmdp->u.raw64.sg_ranz * sizeof(gdth_sg64_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) cmdp->u.raw.sg_lst[0].sg_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) cmdp->u.raw.sg_lst[0].sg_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) /* evaluate command size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) (u16)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) /* check space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) if (ha->cmd_len & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) ha->cmd_len += (4 - (ha->cmd_len & 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) if (ha->cmd_cnt > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) ha->ic_all_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) TRACE2(("gdth_fill_raw() DPMEM overflow\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) /* copy command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) gdth_copy_command(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) return cmd_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) static int gdth_special_cmd(gdth_ha_str *ha, struct scsi_cmnd *scp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) register gdth_cmd_str *cmdp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) int cmd_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) cmdp= ha->pccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) TRACE2(("gdth_special_cmd(): "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) *cmdp = *cmndinfo->internal_cmd_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) cmdp->RequestBuffer = scp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) /* search free command index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) if (!(cmd_index=gdth_get_cmd_index(ha))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) TRACE(("GDT: No free command index found\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) /* if it's the first command, set command semaphore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) if (ha->cmd_cnt == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) gdth_set_sema0(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) /* evaluate command size, check space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) if (cmdp->OpCode == GDT_IOCTL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) TRACE2(("IOCTL\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) ha->cmd_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) } else if (cmdp->Service == CACHESERVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) TRACE2(("cache command %d\n",cmdp->OpCode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) if (ha->cache_feat & GDT_64BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) ha->cmd_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) + sizeof(gdth_sg64_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) ha->cmd_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) } else if (cmdp->Service == SCSIRAWSERVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) TRACE2(("raw command %d\n",cmdp->OpCode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) if (ha->raw_feat & GDT_64BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) ha->cmd_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) + sizeof(gdth_sg64_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) ha->cmd_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) if (ha->cmd_len & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) ha->cmd_len += (4 - (ha->cmd_len & 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) if (ha->cmd_cnt > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) ha->ic_all_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) TRACE2(("gdth_special_cmd() DPMEM overflow\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) /* copy command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) gdth_copy_command(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) return cmd_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) /* Controller event handling functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, u16 source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) u16 idx, gdth_evt_data *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) gdth_evt_str *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) /* no GDTH_LOCK_HA() ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) TRACE2(("gdth_store_event() source %d idx %d\n", source, idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) if (source == 0) /* no source -> no event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) if (ebuffer[elastidx].event_source == source &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) ebuffer[elastidx].event_idx == idx &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) ((evt->size != 0 && ebuffer[elastidx].event_data.size != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) !memcmp((char *)&ebuffer[elastidx].event_data.eu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) (char *)&evt->eu, evt->size)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) (evt->size == 0 && ebuffer[elastidx].event_data.size == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) !strcmp((char *)&ebuffer[elastidx].event_data.event_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) (char *)&evt->event_string)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) e = &ebuffer[elastidx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) e->last_stamp = (u32)ktime_get_real_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) ++e->same_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) if (ebuffer[elastidx].event_source != 0) { /* entry not free ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) ++elastidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) if (elastidx == MAX_EVENTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) elastidx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) if (elastidx == eoldidx) { /* reached mark ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) ++eoldidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) if (eoldidx == MAX_EVENTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) eoldidx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) e = &ebuffer[elastidx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) e->event_source = source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) e->event_idx = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) e->first_stamp = e->last_stamp = (u32)ktime_get_real_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) e->same_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) e->event_data = *evt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) e->application = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) gdth_evt_str *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) int eindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) TRACE2(("gdth_read_event() handle %d\n", handle));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) if (handle == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) eindex = eoldidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) eindex = handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) estr->event_source = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) if (eindex < 0 || eindex >= MAX_EVENTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) return eindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) e = &ebuffer[eindex];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) if (e->event_source != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) if (eindex != elastidx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) if (++eindex == MAX_EVENTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) eindex = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) eindex = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) memcpy(estr, e, sizeof(gdth_evt_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) return eindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) static void gdth_readapp_event(gdth_ha_str *ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) u8 application, gdth_evt_str *estr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) gdth_evt_str *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) int eindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) u8 found = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) TRACE2(("gdth_readapp_event() app. %d\n", application));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) eindex = eoldidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) e = &ebuffer[eindex];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) if (e->event_source == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) if ((e->application & application) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) e->application |= application;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) found = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) if (eindex == elastidx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) if (++eindex == MAX_EVENTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) eindex = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) if (found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) memcpy(estr, e, sizeof(gdth_evt_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) estr->event_source = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) static void gdth_clear_events(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) TRACE(("gdth_clear_events()"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) eoldidx = elastidx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) ebuffer[0].event_source = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) /* SCSI interface functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) static irqreturn_t __gdth_interrupt(gdth_ha_str *ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) int gdth_from_wait, int* pIndex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) gdt6m_dpram_str __iomem *dp6m_ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) gdt6_dpram_str __iomem *dp6_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) struct scsi_cmnd *scp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) int rval, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) u8 IStatus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) u16 Service;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) TRACE(("gdth_interrupt() IRQ %d\n", ha->irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) /* if polling and not from gdth_wait() -> return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) if (gdth_polling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) if (!gdth_from_wait) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) if (!gdth_polling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) /* search controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) IStatus = gdth_get_status(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) if (IStatus == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) /* spurious interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) if (!gdth_polling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) #ifdef GDTH_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) ++act_ints;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) if (ha->type == GDT_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) dp6_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) if (IStatus & 0x80) { /* error flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) IStatus &= ~0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) ha->status = readw(&dp6_ptr->u.ic.Status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) } else /* no error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) ha->status = S_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) ha->info = readl(&dp6_ptr->u.ic.Info[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) ha->service = readw(&dp6_ptr->u.ic.Service);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) ha->info2 = readl(&dp6_ptr->u.ic.Info[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) writeb(0, &dp6_ptr->u.ic.Cmd_Index);/* reset command index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) } else if (ha->type == GDT_PCINEW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) if (IStatus & 0x80) { /* error flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) IStatus &= ~0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) ha->status = inw(PTR2USHORT(&ha->plx->status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) ha->status = S_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) ha->info = inl(PTR2USHORT(&ha->plx->info[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) ha->service = inw(PTR2USHORT(&ha->plx->service));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) ha->info2 = inl(PTR2USHORT(&ha->plx->info[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) outb(0x00, PTR2USHORT(&ha->plx->sema1_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) } else if (ha->type == GDT_PCIMPR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) dp6m_ptr = ha->brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) if (IStatus & 0x80) { /* error flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) IStatus &= ~0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) ha->status = readw(&dp6m_ptr->i960r.status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) } else /* no error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) ha->status = S_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) ha->info = readl(&dp6m_ptr->i960r.info[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) ha->service = readw(&dp6m_ptr->i960r.service);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) ha->info2 = readl(&dp6m_ptr->i960r.info[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) /* event string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) if (IStatus == ASYNCINDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) if (ha->service != SCREENSERVICE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) (ha->fw_vers & 0xff) >= 0x1a) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) ha->dvr.severity = readb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.severity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) for (i = 0; i < 256; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) ha->dvr.event_string[i] = readb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.evt_str[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) if (ha->dvr.event_string[i] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) writeb(0, &dp6m_ptr->i960r.sema1_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) TRACE2(("gdth_interrupt() unknown controller type\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) if (!gdth_polling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) TRACE(("gdth_interrupt() index %d stat %d info %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) IStatus,ha->status,ha->info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) if (gdth_from_wait) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) *pIndex = (int)IStatus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) if (IStatus == ASYNCINDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) TRACE2(("gdth_interrupt() async. event\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) gdth_async_event(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) if (!gdth_polling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) gdth_next(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) if (IStatus == SPEZINDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) TRACE2(("Service unknown or not initialized !\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) ha->dvr.size = sizeof(ha->dvr.eu.driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) ha->dvr.eu.driver.ionode = ha->hanum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) if (!gdth_polling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) scp = ha->cmd_tab[IStatus-2].cmnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) Service = ha->cmd_tab[IStatus-2].service;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) if (scp == UNUSED_CMND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) ha->dvr.size = sizeof(ha->dvr.eu.driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) ha->dvr.eu.driver.ionode = ha->hanum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) ha->dvr.eu.driver.index = IStatus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) if (!gdth_polling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) if (scp == INTERNAL_CMND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) TRACE(("gdth_interrupt() answer to internal command\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) if (!gdth_polling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) TRACE(("gdth_interrupt() sync. status\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) rval = gdth_sync_event(ha,Service,IStatus,scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) if (!gdth_polling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) if (rval == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) gdth_putq(ha, scp, gdth_cmnd_priv(scp)->priority);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) } else if (rval == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) gdth_scsi_done(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) gdth_next(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) static irqreturn_t gdth_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) gdth_ha_str *ha = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) return __gdth_interrupt(ha, false, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) static int gdth_sync_event(gdth_ha_str *ha, int service, u8 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) struct scsi_cmnd *scp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) gdth_msg_str *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) gdth_cmd_str *cmdp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) u8 b, t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) cmdp = ha->pccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) TRACE(("gdth_sync_event() serv %d status %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) service,ha->status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) if (service == SCREENSERVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) msg = ha->pmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) TRACE(("len: %d, answer: %d, ext: %d, alen: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) if (msg->msg_len > MSGLEN+1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) msg->msg_len = MSGLEN+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) if (msg->msg_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) if (!(msg->msg_answer && msg->msg_ext)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) msg->msg_text[msg->msg_len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) printk("%s",msg->msg_text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) if (msg->msg_ext && !msg->msg_answer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) while (gdth_test_busy(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) gdth_delay(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) cmdp->Service = SCREENSERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) cmdp->RequestBuffer = SCREEN_CMND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) gdth_get_cmd_index(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) gdth_set_sema0(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) cmdp->OpCode = GDT_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) cmdp->BoardNode = LOCALBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) cmdp->u.screen.reserved = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) cmdp->u.screen.su.msg.msg_addr = ha->msg_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) ha->cmd_offs_dpmem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) + sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) ha->cmd_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) gdth_copy_command(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) gdth_release_event(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) if (msg->msg_answer && msg->msg_alen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) /* default answers (getchar() not possible) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) if (msg->msg_alen == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) msg->msg_alen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) msg->msg_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) msg->msg_text[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) msg->msg_alen -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) msg->msg_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) msg->msg_text[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) msg->msg_text[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) msg->msg_ext = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) msg->msg_answer = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) while (gdth_test_busy(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) gdth_delay(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) cmdp->Service = SCREENSERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) cmdp->RequestBuffer = SCREEN_CMND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) gdth_get_cmd_index(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) gdth_set_sema0(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) cmdp->OpCode = GDT_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) cmdp->BoardNode = LOCALBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) cmdp->u.screen.reserved = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) cmdp->u.screen.su.msg.msg_addr = ha->msg_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) ha->cmd_offs_dpmem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) + sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) ha->cmd_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) gdth_copy_command(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) gdth_release_event(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) b = scp->device->channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) t = scp->device->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) if (cmndinfo->OpCode == -1 && b != ha->virt_bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) ha->raw[BUS_L2P(ha,b)].io_cnt[t]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) /* cache or raw service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) if (ha->status == S_BSY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) TRACE2(("Controller busy -> retry !\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) if (cmndinfo->OpCode == GDT_MOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) cmndinfo->OpCode = GDT_CLUST_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) /* retry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) if (scsi_bufflen(scp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) dma_unmap_sg(&ha->pdev->dev, scsi_sglist(scp), scsi_sg_count(scp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) cmndinfo->dma_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) if (cmndinfo->sense_paddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) dma_unmap_page(&ha->pdev->dev, cmndinfo->sense_paddr, 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) if (ha->status == S_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) cmndinfo->status = S_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) cmndinfo->info = ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) if (cmndinfo->OpCode != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) cmndinfo->OpCode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) /* special commands GDT_CLUST_INFO/GDT_MOUNT ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) if (cmndinfo->OpCode == GDT_CLUST_INFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) ha->hdr[t].cluster_type = (u8)ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) if (!(ha->hdr[t].cluster_type &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) CLUSTER_MOUNTED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) /* NOT MOUNTED -> MOUNT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) cmndinfo->OpCode = GDT_MOUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) if (ha->hdr[t].cluster_type &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) CLUSTER_RESERVED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) /* cluster drive RESERVED (on the other node) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) cmndinfo->phase = -2; /* reservation conflict */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) cmndinfo->OpCode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) if (cmndinfo->OpCode == GDT_MOUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) ha->hdr[t].cluster_type |= CLUSTER_MOUNTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) ha->hdr[t].media_changed = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) } else if (cmndinfo->OpCode == GDT_UNMOUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) ha->hdr[t].cluster_type &= ~CLUSTER_MOUNTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) ha->hdr[t].media_changed = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) cmndinfo->OpCode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) /* retry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) cmndinfo->priority = HIGH_PRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) /* RESERVE/RELEASE ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) if (scp->cmnd[0] == RESERVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) ha->hdr[t].cluster_type |= CLUSTER_RESERVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) } else if (scp->cmnd[0] == RELEASE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) scp->result = DID_OK << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) scp->sense_buffer[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) cmndinfo->status = ha->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) cmndinfo->info = ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) if (cmndinfo->OpCode != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) cmndinfo->OpCode, ha->status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) if (cmndinfo->OpCode == GDT_SCAN_START ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) cmndinfo->OpCode == GDT_SCAN_END) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) cmndinfo->OpCode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) /* retry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) cmndinfo->priority = HIGH_PRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) memset((char*)scp->sense_buffer,0,16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) scp->sense_buffer[0] = 0x70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) scp->sense_buffer[2] = NOT_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) } else if (service == CACHESERVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) if (ha->status == S_CACHE_UNKNOWN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) (ha->hdr[t].cluster_type &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) CLUSTER_RESERVE_STATE) == CLUSTER_RESERVE_STATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) /* bus reset -> force GDT_CLUST_INFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) memset((char*)scp->sense_buffer,0,16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) if (ha->status == (u16)S_CACHE_RESERV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) scp->result = (DID_OK << 16) | (RESERVATION_CONFLICT << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) scp->sense_buffer[0] = 0x70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) scp->sense_buffer[2] = NOT_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) if (!cmndinfo->internal_command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) ha->dvr.size = sizeof(ha->dvr.eu.sync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) ha->dvr.eu.sync.ionode = ha->hanum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) ha->dvr.eu.sync.service = service;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) ha->dvr.eu.sync.status = ha->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) ha->dvr.eu.sync.info = ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) ha->dvr.eu.sync.hostdrive = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) if (ha->status >= 0x8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) gdth_store_event(ha, ES_SYNC, 0, &ha->dvr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) gdth_store_event(ha, ES_SYNC, service, &ha->dvr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) /* sense buffer filled from controller firmware (DMA) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) if (ha->status != S_RAW_SCSI || ha->info >= 0x100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) scp->result = DID_BAD_TARGET << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) scp->result = (DID_OK << 16) | ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) if (!cmndinfo->wait_for_completion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) cmndinfo->wait_for_completion++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) static char *async_cache_tab[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) /* 0*/ "\011\000\002\002\002\004\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) "GDT HA %u, service %u, async. status %u/%lu unknown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) /* 1*/ "\011\000\002\002\002\004\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) "GDT HA %u, service %u, async. status %u/%lu unknown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) /* 2*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) "GDT HA %u, Host Drive %lu not ready",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) /* 3*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) "GDT HA %u, Host Drive %lu: REASSIGN not successful and/or data error on reassigned blocks. Drive may crash in the future and should be replaced",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) /* 4*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) "GDT HA %u, mirror update on Host Drive %lu failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) /* 5*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) "GDT HA %u, Mirror Drive %lu failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) /* 6*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) "GDT HA %u, Mirror Drive %lu: REASSIGN not successful and/or data error on reassigned blocks. Drive may crash in the future and should be replaced",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) /* 7*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) "GDT HA %u, Host Drive %lu write protected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) /* 8*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) "GDT HA %u, media changed in Host Drive %lu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) /* 9*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) "GDT HA %u, Host Drive %lu is offline",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) /*10*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) "GDT HA %u, media change of Mirror Drive %lu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) /*11*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) "GDT HA %u, Mirror Drive %lu is write protected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) /*12*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) "GDT HA %u, general error on Host Drive %lu. Please check the devices of this drive!",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) /*13*/ "\007\000\002\006\002\010\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) "GDT HA %u, Array Drive %u: Cache Drive %u failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) /*14*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) "GDT HA %u, Array Drive %u: FAIL state entered",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) /*15*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) "GDT HA %u, Array Drive %u: error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) /*16*/ "\007\000\002\006\002\010\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) "GDT HA %u, Array Drive %u: failed drive replaced by Cache Drive %u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) /*17*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) "GDT HA %u, Array Drive %u: parity build failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) /*18*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) "GDT HA %u, Array Drive %u: drive rebuild failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) /*19*/ "\005\000\002\010\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) "GDT HA %u, Test of Hot Fix %u failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) /*20*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) "GDT HA %u, Array Drive %u: drive build finished successfully",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) /*21*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) "GDT HA %u, Array Drive %u: drive rebuild finished successfully",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) /*22*/ "\007\000\002\006\002\010\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) "GDT HA %u, Array Drive %u: Hot Fix %u activated",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) /*23*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) "GDT HA %u, Host Drive %u: processing of i/o aborted due to serious drive error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) /*24*/ "\005\000\002\010\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) "GDT HA %u, mirror update on Cache Drive %u completed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) /*25*/ "\005\000\002\010\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) "GDT HA %u, mirror update on Cache Drive %lu failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) /*26*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) "GDT HA %u, Array Drive %u: drive rebuild started",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) /*27*/ "\005\000\002\012\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) "GDT HA %u, Fault bus %u: SHELF OK detected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) /*28*/ "\005\000\002\012\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) "GDT HA %u, Fault bus %u: SHELF not OK detected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) /*29*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug started",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) /*30*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) "GDT HA %u, Fault bus %u, ID %u: new disk detected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) /*31*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) "GDT HA %u, Fault bus %u, ID %u: old disk detected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) /*32*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) "GDT HA %u, Fault bus %u, ID %u: plugging an active disk is invalid",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) /*33*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) "GDT HA %u, Fault bus %u, ID %u: invalid device detected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) /*34*/ "\011\000\002\012\001\013\001\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) "GDT HA %u, Fault bus %u, ID %u: insufficient disk capacity (%lu MB required)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) /*35*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) "GDT HA %u, Fault bus %u, ID %u: disk write protected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) /*36*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) "GDT HA %u, Fault bus %u, ID %u: disk not available",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) /*37*/ "\007\000\002\012\001\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) "GDT HA %u, Fault bus %u: swap detected (%lu)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) /*38*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug finished successfully",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) /*39*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted due to user Hot Plug",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) /*40*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) /*41*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug for Hot Fix started",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) /*42*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) "GDT HA %u, Array Drive %u: drive build started",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) /*43*/ "\003\000\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) "GDT HA %u, DRAM parity error detected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) /*44*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) "GDT HA %u, Mirror Drive %u: update started",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) /*45*/ "\007\000\002\006\002\010\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) "GDT HA %u, Mirror Drive %u: Hot Fix %u activated",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) /*46*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) "GDT HA %u, Array Drive %u: no matching Pool Hot Fix Drive available",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) /*47*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) "GDT HA %u, Array Drive %u: Pool Hot Fix Drive available",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) /*48*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) "GDT HA %u, Mirror Drive %u: no matching Pool Hot Fix Drive available",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) /*49*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) "GDT HA %u, Mirror Drive %u: Pool Hot Fix Drive available",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) /*50*/ "\007\000\002\012\001\013\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) "GDT HA %u, SCSI bus %u, ID %u: IGNORE_WIDE_RESIDUE message received",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) /*51*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) "GDT HA %u, Array Drive %u: expand started",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) /*52*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) "GDT HA %u, Array Drive %u: expand finished successfully",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) /*53*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) "GDT HA %u, Array Drive %u: expand failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) /*54*/ "\003\000\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) "GDT HA %u, CPU temperature critical",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) /*55*/ "\003\000\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) "GDT HA %u, CPU temperature OK",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) /*56*/ "\005\000\002\006\004"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) "GDT HA %u, Host drive %lu created",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) /*57*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) "GDT HA %u, Array Drive %u: expand restarted",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) /*58*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) "GDT HA %u, Array Drive %u: expand stopped",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) /*59*/ "\005\000\002\010\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) "GDT HA %u, Mirror Drive %u: drive build quited",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) /*60*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) "GDT HA %u, Array Drive %u: parity build quited",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) /*61*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) "GDT HA %u, Array Drive %u: drive rebuild quited",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) /*62*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) "GDT HA %u, Array Drive %u: parity verify started",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) /*63*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) "GDT HA %u, Array Drive %u: parity verify done",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) /*64*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) "GDT HA %u, Array Drive %u: parity verify failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) /*65*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) "GDT HA %u, Array Drive %u: parity error detected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) /*66*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) "GDT HA %u, Array Drive %u: parity verify quited",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) /*67*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) "GDT HA %u, Host Drive %u reserved",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) /*68*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) "GDT HA %u, Host Drive %u mounted and released",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) /*69*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) "GDT HA %u, Host Drive %u released",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) /*70*/ "\003\000\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) "GDT HA %u, DRAM error detected and corrected with ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) /*71*/ "\003\000\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) "GDT HA %u, Uncorrectable DRAM error detected with ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) /*72*/ "\011\000\002\012\001\013\001\014\001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) "GDT HA %u, SCSI bus %u, ID %u, LUN %u: reassigning block",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) /*73*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) "GDT HA %u, Host drive %u resetted locally",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) /*74*/ "\005\000\002\006\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) "GDT HA %u, Host drive %u resetted remotely",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) /*75*/ "\003\000\002"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) "GDT HA %u, async. status 75 unknown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) static int gdth_async_event(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) gdth_cmd_str *cmdp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) cmdp= ha->pccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) TRACE2(("gdth_async_event() ha %d serv %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) ha->hanum, ha->service));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) if (ha->service == SCREENSERVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) if (ha->status == MSG_REQUEST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) while (gdth_test_busy(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) gdth_delay(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) cmdp->Service = SCREENSERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) cmdp->RequestBuffer = SCREEN_CMND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) gdth_set_sema0(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) cmdp->OpCode = GDT_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) cmdp->BoardNode = LOCALBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) cmdp->u.screen.reserved = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) cmdp->u.screen.su.msg.msg_handle= MSG_INV_HANDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) cmdp->u.screen.su.msg.msg_addr = ha->msg_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) ha->cmd_offs_dpmem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) + sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) ha->cmd_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) gdth_copy_command(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) printk("[PCI %d/%d] ",(u16)(ha->brd_phys>>8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) (u16)((ha->brd_phys>>3)&0x1f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) gdth_release_event(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) if (ha->type == GDT_PCIMPR &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) (ha->fw_vers & 0xff) >= 0x1a) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) ha->dvr.size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) ha->dvr.eu.async.ionode = ha->hanum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) ha->dvr.eu.async.status = ha->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) /* severity and event_string already set! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) ha->dvr.size = sizeof(ha->dvr.eu.async);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) ha->dvr.eu.async.ionode = ha->hanum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) ha->dvr.eu.async.service = ha->service;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) ha->dvr.eu.async.status = ha->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) ha->dvr.eu.async.info = ha->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) *(u32 *)ha->dvr.eu.async.scsi_coord = ha->info2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) gdth_store_event( ha, ES_ASYNC, ha->service, &ha->dvr );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) gdth_log_event( &ha->dvr, NULL );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) /* new host drive from expand? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) if (ha->service == CACHESERVICE && ha->status == 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) TRACE2(("gdth_async_event(): new host drive %d created\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) (u16)ha->info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) /* gdth_analyse_hdrive(hanum, (u16)ha->info); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) static void gdth_log_event(gdth_evt_data *dvr, char *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) gdth_stackframe stack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) char *f = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) int i,j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) TRACE2(("gdth_log_event()\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) if (dvr->size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) if (buffer == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) printk("Adapter %d: %s\n",dvr->eu.async.ionode,dvr->event_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) sprintf(buffer,"Adapter %d: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) dvr->eu.async.ionode,dvr->event_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) } else if (dvr->eu.async.service == CACHESERVICE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) INDEX_OK(dvr->eu.async.status, async_cache_tab)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) TRACE2(("GDT: Async. event cache service, event no.: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) dvr->eu.async.status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) f = async_cache_tab[dvr->eu.async.status];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) /* i: parameter to push, j: stack element to fill */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) for (j=0,i=1; i < f[0]; i+=2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) switch (f[i+1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) stack.b[j++] = *(u32*)&dvr->eu.stream[(int)f[i]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) stack.b[j++] = *(u16*)&dvr->eu.stream[(int)f[i]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) stack.b[j++] = *(u8*)&dvr->eu.stream[(int)f[i]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) if (buffer == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) printk(&f[(int)f[0]],stack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) sprintf(buffer,&f[(int)f[0]],stack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) if (buffer == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) printk("GDT HA %u, Unknown async. event service %d event no. %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) dvr->eu.async.ionode,dvr->eu.async.service,dvr->eu.async.status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) sprintf(buffer,"GDT HA %u, Unknown async. event service %d event no. %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) dvr->eu.async.ionode,dvr->eu.async.service,dvr->eu.async.status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) #ifdef GDTH_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) static u8 gdth_timer_running;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) static void gdth_timeout(struct timer_list *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) struct scsi_cmnd *nscp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) if(unlikely(list_empty(&gdth_instances))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) gdth_timer_running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) ha = list_first_entry(&gdth_instances, gdth_ha_str, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) if (ha->cmd_tab[i].cmnd != UNUSED_CMND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) ++act_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) for (act_rq=0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) nscp=ha->req_first; nscp; nscp=(struct scsi_cmnd*)nscp->SCp.ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) ++act_rq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) TRACE2(("gdth_to(): ints %d, ios %d, act_stats %d, act_rq %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) act_ints, act_ios, act_stats, act_rq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) act_ints = act_ios = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) gdth_timer.expires = jiffies + 30 * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) add_timer(&gdth_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) static void gdth_timer_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) if (gdth_timer_running)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) gdth_timer_running = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) TRACE2(("gdth_detect(): Initializing timer !\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) gdth_timer.expires = jiffies + HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) add_timer(&gdth_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) static inline void gdth_timer_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) static const char *gdth_ctr_name(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) TRACE2(("gdth_ctr_name()\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) if (ha->type == GDT_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) switch (ha->pdev->device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) case PCI_DEVICE_ID_VORTEX_GDT60x0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) return("GDT6000/6020/6050");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) case PCI_DEVICE_ID_VORTEX_GDT6000B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) return("GDT6000B/6010");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) /* new controllers (GDT_PCINEW, GDT_PCIMPR, ..) use board_info IOCTL! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) return("");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) static const char *gdth_info(struct Scsi_Host *shp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) gdth_ha_str *ha = shost_priv(shp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) TRACE2(("gdth_info()\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) return ((const char *)ha->binfo.type_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) static enum blk_eh_timer_return gdth_timed_out(struct scsi_cmnd *scp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) gdth_ha_str *ha = shost_priv(scp->device->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) u8 b, t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) enum blk_eh_timer_return retval = BLK_EH_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) TRACE(("%s() cmd 0x%x\n", scp->cmnd[0], __func__));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) b = scp->device->channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) t = scp->device->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) * We don't really honor the command timeout, but we try to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) * honor 6 times of the actual command timeout! So reset the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) * timer if this is less than 6th timeout on this command!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) if (++cmndinfo->timeout_count < 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) retval = BLK_EH_RESET_TIMER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) /* Reset the timeout if it is locked IO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha, b)].lock) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) TRACE2(("%s(): locked IO, reset timeout\n", __func__));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) retval = BLK_EH_RESET_TIMER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) static int gdth_eh_bus_reset(struct scsi_cmnd *scp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) gdth_ha_str *ha = shost_priv(scp->device->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) struct scsi_cmnd *cmnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) u8 b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) TRACE2(("gdth_eh_bus_reset()\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) b = scp->device->channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) /* clear command tab */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) for (i = 0; i < GDTH_MAXCMDS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) cmnd = ha->cmd_tab[i].cmnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) if (!SPECIAL_SCP(cmnd) && cmnd->device->channel == b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) ha->cmd_tab[i].cmnd = UNUSED_CMND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) if (b == ha->virt_bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) /* host drives */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) for (i = 0; i < MAX_HDRIVES; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) if (ha->hdr[i].present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) gdth_polling = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) while (gdth_test_busy(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) gdth_delay(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) if (gdth_internal_cmd(ha, CACHESERVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) GDT_CLUST_RESET, i, 0, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) gdth_polling = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) /* raw devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) for (i = 0; i < MAXID; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) ha->raw[BUS_L2P(ha,b)].io_cnt[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) gdth_polling = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) while (gdth_test_busy(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) gdth_delay(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_RESET_BUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) BUS_L2P(ha,b), 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) gdth_polling = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) return SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) static int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) u8 b, t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) gdth_ha_str *ha = shost_priv(sdev->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) struct scsi_device *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) unsigned capacity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) sd = sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) capacity = cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) b = sd->channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) t = sd->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", ha->hanum, b, t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) if (b != ha->virt_bus || ha->hdr[t].heads == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) /* raw device or host drive without mapping information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) TRACE2(("Evaluate mapping\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) gdth_eval_mapping(capacity,&ip[2],&ip[0],&ip[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) ip[0] = ha->hdr[t].heads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) ip[1] = ha->hdr[t].secs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) ip[2] = capacity / ip[0] / ip[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) ip[0],ip[1],ip[2]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) static int gdth_queuecommand_lck(struct scsi_cmnd *scp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) void (*done)(struct scsi_cmnd *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) gdth_ha_str *ha = shost_priv(scp->device->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) struct gdth_cmndinfo *cmndinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) cmndinfo = gdth_get_cmndinfo(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) BUG_ON(!cmndinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) scp->scsi_done = done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) cmndinfo->timeout_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) cmndinfo->priority = DEFAULT_PRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) return __gdth_queuecommand(ha, scp, cmndinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) static DEF_SCSI_QCMD(gdth_queuecommand)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) struct gdth_cmndinfo *cmndinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) scp->host_scribble = (unsigned char *)cmndinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) cmndinfo->wait_for_completion = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) cmndinfo->phase = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) cmndinfo->OpCode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) #ifdef GDTH_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) ++act_ios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) gdth_putq(ha, scp, cmndinfo->priority);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) gdth_next(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) static int gdth_open(struct inode *inode, struct file *filep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) mutex_lock(&gdth_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) list_for_each_entry(ha, &gdth_instances, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) if (!ha->sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) ha->sdev = scsi_get_host_dev(ha->shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) mutex_unlock(&gdth_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) TRACE(("gdth_open()\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) static int gdth_close(struct inode *inode, struct file *filep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) TRACE(("gdth_close()\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) static int ioc_event(void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) gdth_ioctl_event evt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) if (copy_from_user(&evt, arg, sizeof(gdth_ioctl_event)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) ha = gdth_find_ha(evt.ionode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) if (!ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) if (evt.erase == 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) if (evt.event.event_source == ES_TEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) evt.event.event_data.size=sizeof(evt.event.event_data.eu.test);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) else if (evt.event.event_source == ES_DRIVER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) else if (evt.event.event_source == ES_SYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) evt.event.event_data.size=sizeof(evt.event.event_data.eu.async);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) gdth_store_event(ha, evt.event.event_source, evt.event.event_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) &evt.event.event_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) } else if (evt.erase == 0xfe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) gdth_clear_events();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) } else if (evt.erase == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) evt.handle = gdth_read_event(ha, evt.handle, &evt.event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) gdth_readapp_event(ha, evt.erase, &evt.event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) if (copy_to_user(arg, &evt, sizeof(gdth_ioctl_event)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) static int ioc_lockdrv(void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) gdth_ioctl_lockdrv ldrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) u8 i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) if (copy_from_user(&ldrv, arg, sizeof(gdth_ioctl_lockdrv)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) ha = gdth_find_ha(ldrv.ionode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) if (!ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) j = ldrv.drives[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) if (j >= MAX_HDRIVES || !ha->hdr[j].present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) if (ldrv.lock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) ha->hdr[j].lock = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) gdth_wait_completion(ha, ha->bus_cnt, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) ha->hdr[j].lock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) gdth_next(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) static int ioc_resetdrv(void __user *arg, char *cmnd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) gdth_ioctl_reset res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) gdth_cmd_str cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) res.number >= MAX_HDRIVES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) ha = gdth_find_ha(res.ionode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) if (!ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) if (!ha->hdr[res.number].present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) memset(&cmd, 0, sizeof(gdth_cmd_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) cmd.Service = CACHESERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) cmd.OpCode = GDT_CLUST_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) if (ha->cache_feat & GDT_64BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) cmd.u.cache64.DeviceNo = res.number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) cmd.u.cache.DeviceNo = res.number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) rval = __gdth_execute(ha->sdev, &cmd, cmnd, 30, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) res.status = rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) if (copy_to_user(arg, &res, sizeof(gdth_ioctl_reset)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) static void gdth_ioc_cacheservice(gdth_ha_str *ha, gdth_ioctl_general *gen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) u64 paddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) if (ha->cache_feat & GDT_64BIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) /* copy elements from 32-bit IOCTL structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) gen->command.u.cache64.BlockCnt = gen->command.u.cache.BlockCnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) gen->command.u.cache64.BlockNo = gen->command.u.cache.BlockNo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) gen->command.u.cache64.DeviceNo = gen->command.u.cache.DeviceNo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) if (ha->cache_feat & SCATTER_GATHER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) gen->command.u.cache64.DestAddr = (u64)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) gen->command.u.cache64.sg_canz = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) gen->command.u.cache64.sg_lst[0].sg_ptr = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) gen->command.u.cache64.sg_lst[0].sg_len = gen->data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) gen->command.u.cache64.sg_lst[1].sg_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) gen->command.u.cache64.DestAddr = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) gen->command.u.cache64.sg_canz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) if (ha->cache_feat & SCATTER_GATHER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) gen->command.u.cache.DestAddr = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) gen->command.u.cache.sg_canz = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) gen->command.u.cache.sg_lst[0].sg_ptr = (u32)paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) gen->command.u.cache.sg_lst[0].sg_len = gen->data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) gen->command.u.cache.sg_lst[1].sg_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) gen->command.u.cache.DestAddr = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) gen->command.u.cache.sg_canz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) static void gdth_ioc_scsiraw(gdth_ha_str *ha, gdth_ioctl_general *gen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) u64 paddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) if (ha->raw_feat & GDT_64BIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) /* copy elements from 32-bit IOCTL structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) char cmd[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) gen->command.u.raw64.sense_len = gen->command.u.raw.sense_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) gen->command.u.raw64.bus = gen->command.u.raw.bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) gen->command.u.raw64.lun = gen->command.u.raw.lun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) gen->command.u.raw64.target = gen->command.u.raw.target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) memcpy(cmd, gen->command.u.raw.cmd, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) memcpy(gen->command.u.raw64.cmd, cmd, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) gen->command.u.raw64.clen = gen->command.u.raw.clen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) gen->command.u.raw64.sdlen = gen->command.u.raw.sdlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) gen->command.u.raw64.direction = gen->command.u.raw.direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) /* addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) if (ha->raw_feat & SCATTER_GATHER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) gen->command.u.raw64.sdata = (u64)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) gen->command.u.raw64.sg_ranz = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) gen->command.u.raw64.sg_lst[0].sg_ptr = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) gen->command.u.raw64.sg_lst[0].sg_len = gen->data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) gen->command.u.raw64.sg_lst[1].sg_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) gen->command.u.raw64.sdata = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) gen->command.u.raw64.sg_ranz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) gen->command.u.raw64.sense_data = paddr + gen->data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) if (ha->raw_feat & SCATTER_GATHER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) gen->command.u.raw.sdata = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) gen->command.u.raw.sg_ranz = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) gen->command.u.raw.sg_lst[0].sg_ptr = (u32)paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) gen->command.u.raw.sg_lst[0].sg_len = gen->data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) gen->command.u.raw.sg_lst[1].sg_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) gen->command.u.raw.sdata = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) gen->command.u.raw.sg_ranz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) gen->command.u.raw.sense_data = (u32)paddr + gen->data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) static int ioc_general(void __user *arg, char *cmnd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) gdth_ioctl_general gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) char *buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) dma_addr_t paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) ha = gdth_find_ha(gen.ionode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) if (!ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) if (gen.data_len > INT_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) if (gen.sense_len > INT_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) if (gen.data_len + gen.sense_len > INT_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) if (gen.data_len + gen.sense_len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) buf = dma_alloc_coherent(&ha->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) gen.data_len + gen.sense_len, &paddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) rval = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) if (copy_from_user(buf, arg + sizeof(gdth_ioctl_general),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) gen.data_len + gen.sense_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) if (gen.command.OpCode == GDT_IOCTL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) gen.command.u.ioctl.p_param = paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) else if (gen.command.Service == CACHESERVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) gdth_ioc_cacheservice(ha, &gen, paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) else if (gen.command.Service == SCSIRAWSERVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) gdth_ioc_scsiraw(ha, &gen, paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) rval = __gdth_execute(ha->sdev, &gen.command, cmnd, gen.timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) &gen.info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) gen.status = rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) rval = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) gen.data_len + gen.sense_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) if (copy_to_user(arg, &gen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) out_free_buf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611) if (buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) dma_free_coherent(&ha->pdev->dev, gen.data_len + gen.sense_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) buf, paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) static int ioc_hdrlist(void __user *arg, char *cmnd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) gdth_ioctl_rescan *rsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) gdth_cmd_str *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) int rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) u32 cluster_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) if (!rsc || !cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) goto free_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) (NULL == (ha = gdth_find_ha(rsc->ionode)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) goto free_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) memset(cmd, 0, sizeof(gdth_cmd_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) for (i = 0; i < MAX_HDRIVES; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) if (!ha->hdr[i].present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) rsc->hdr_list[i].bus = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) rsc->hdr_list[i].bus = ha->virt_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) rsc->hdr_list[i].target = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) rsc->hdr_list[i].lun = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) rsc->hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) cmd->Service = CACHESERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649) cmd->OpCode = GDT_CLUST_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650) if (ha->cache_feat & GDT_64BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) cmd->u.cache64.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) cmd->u.cache.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) if (__gdth_execute(ha->sdev, cmd, cmnd, 30, &cluster_type) == S_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) rsc->hdr_list[i].cluster_type = cluster_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) free_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) kfree(rsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) static int ioc_rescan(void __user *arg, char *cmnd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) gdth_ioctl_rescan *rsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) gdth_cmd_str *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) u16 i, status, hdr_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675) u32 info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) int cyls, hds, secs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) int rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) if (!cmd || !rsc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) goto free_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) (NULL == (ha = gdth_find_ha(rsc->ionode)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) goto free_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) memset(cmd, 0, sizeof(gdth_cmd_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) if (rsc->flag == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) /* old method: re-init. cache service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) cmd->Service = CACHESERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) if (ha->cache_feat & GDT_64BIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) cmd->OpCode = GDT_X_INIT_HOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) cmd->u.cache64.DeviceNo = LINUX_OS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) cmd->OpCode = GDT_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) cmd->u.cache.DeviceNo = LINUX_OS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) hdr_cnt = (status == S_OK ? (u16)info : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) i = rsc->hdr_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709) hdr_cnt = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) cmd->Service = CACHESERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) cmd->OpCode = GDT_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) if (ha->cache_feat & GDT_64BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) cmd->u.cache64.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) cmd->u.cache.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) rsc->hdr_list[i].bus = ha->virt_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) rsc->hdr_list[i].target = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) rsc->hdr_list[i].lun = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) if (status != S_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) ha->hdr[i].present = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) ha->hdr[i].present = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) ha->hdr[i].size = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) /* evaluate mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732) ha->hdr[i].size &= ~SECS32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) gdth_eval_mapping(ha->hdr[i].size,&cyls,&hds,&secs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) ha->hdr[i].heads = hds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) ha->hdr[i].secs = secs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) /* round size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) ha->hdr[i].size = cyls * hds * secs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) if (status != S_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) /* extended info, if GDT_64BIT, for drives > 2 TB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) /* but we need ha->info2, not yet stored in scp->SCp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) /* devtype, cluster info, R/W attribs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) cmd->Service = CACHESERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) cmd->OpCode = GDT_DEVTYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) if (ha->cache_feat & GDT_64BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) cmd->u.cache64.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) cmd->u.cache.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) ha->hdr[i].devtype = (status == S_OK ? (u16)info : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) cmd->Service = CACHESERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) cmd->OpCode = GDT_CLUST_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) if (ha->cache_feat & GDT_64BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) cmd->u.cache64.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) cmd->u.cache.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) ha->hdr[i].cluster_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) ((status == S_OK && !shared_access) ? (u16)info : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773) rsc->hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) cmd->Service = CACHESERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) cmd->OpCode = GDT_RW_ATTRIBS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) if (ha->cache_feat & GDT_64BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) cmd->u.cache64.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) cmd->u.cache.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) ha->hdr[i].rw_attribs = (status == S_OK ? (u16)info : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) free_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) kfree(rsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) static int gdth_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) struct scsi_cmnd *scp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) char cmnd[MAX_COMMAND_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) memset(cmnd, 0xff, 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) TRACE(("gdth_ioctl() cmd 0x%x\n", cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) case GDTIOCTL_CTRCNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) int cnt = gdth_ctr_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) if (put_user(cnt, (int __user *)argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821) case GDTIOCTL_DRVERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) int ver = (GDTH_VERSION<<8) | GDTH_SUBVERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) if (put_user(ver, (int __user *)argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) case GDTIOCTL_OSVERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) gdth_ioctl_osvers osv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) osv.version = (u8)(LINUX_VERSION_CODE >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) osv.subversion = (u8)(LINUX_VERSION_CODE >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) osv.revision = (u16)(LINUX_VERSION_CODE & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) if (copy_to_user(argp, &osv, sizeof(gdth_ioctl_osvers)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) case GDTIOCTL_CTRTYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) gdth_ioctl_ctrtype ctrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) if (copy_from_user(&ctrt, argp, sizeof(gdth_ioctl_ctrtype)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) (NULL == (ha = gdth_find_ha(ctrt.ionode))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) if (ha->type != GDT_PCIMPR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) ctrt.type = (u8)((ha->stype<<4) + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) ctrt.type = (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) if (ha->stype >= 0x300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) ctrt.ext_type = 0x6000 | ha->pdev->subsystem_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) ctrt.ext_type = 0x6000 | ha->stype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) ctrt.device_id = ha->pdev->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) ctrt.sub_device_id = ha->pdev->subsystem_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) ctrt.info = ha->brd_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) ctrt.oem_id = ha->oem_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) if (copy_to_user(argp, &ctrt, sizeof(gdth_ioctl_ctrtype)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) case GDTIOCTL_GENERAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) return ioc_general(argp, cmnd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) case GDTIOCTL_EVENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) return ioc_event(argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) case GDTIOCTL_LOCKDRV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) return ioc_lockdrv(argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) case GDTIOCTL_LOCKCHN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) gdth_ioctl_lockchn lchn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) u8 i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) if (copy_from_user(&lchn, argp, sizeof(gdth_ioctl_lockchn)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) (NULL == (ha = gdth_find_ha(lchn.ionode))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) i = lchn.channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) if (i < ha->bus_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) if (lchn.lock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) ha->raw[i].lock = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) for (j = 0; j < ha->tid_cnt; ++j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) gdth_wait_completion(ha, i, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) spin_lock_irqsave(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) ha->raw[i].lock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) spin_unlock_irqrestore(&ha->smp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) for (j = 0; j < ha->tid_cnt; ++j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) gdth_next(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) case GDTIOCTL_RESCAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) return ioc_rescan(argp, cmnd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907) case GDTIOCTL_HDRLIST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) return ioc_hdrlist(argp, cmnd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) case GDTIOCTL_RESET_BUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) gdth_ioctl_reset res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) if (copy_from_user(&res, argp, sizeof(gdth_ioctl_reset)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) (NULL == (ha = gdth_find_ha(res.ionode))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) scp = kzalloc(sizeof(*scp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) if (!scp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) scp->device = ha->sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) scp->cmd_len = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924) scp->device->channel = res.number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) rval = gdth_eh_bus_reset(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) res.status = (rval == SUCCESS ? S_OK : S_GENERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) kfree(scp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) if (copy_to_user(argp, &res, sizeof(gdth_ioctl_reset)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) case GDTIOCTL_RESET_DRV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) return ioc_resetdrv(argp, cmnd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) static long gdth_unlocked_ioctl(struct file *file, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) mutex_lock(&gdth_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949) ret = gdth_ioctl(file, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) mutex_unlock(&gdth_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955) /* flush routine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) static void gdth_flush(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959) gdth_cmd_str gdtcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) char cmnd[MAX_COMMAND_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) memset(cmnd, 0xff, MAX_COMMAND_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963) TRACE2(("gdth_flush() hanum %d\n", ha->hanum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) for (i = 0; i < MAX_HDRIVES; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) if (ha->hdr[i].present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967) gdtcmd.BoardNode = LOCALBOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) gdtcmd.Service = CACHESERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) gdtcmd.OpCode = GDT_FLUSH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) if (ha->cache_feat & GDT_64BIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971) gdtcmd.u.cache64.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) gdtcmd.u.cache64.BlockNo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973) gdtcmd.u.cache64.sg_canz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) gdtcmd.u.cache.DeviceNo = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) gdtcmd.u.cache.BlockNo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977) gdtcmd.u.cache.sg_canz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) TRACE2(("gdth_flush(): flush ha %d drive %d\n", ha->hanum, i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) gdth_execute(ha->shost, &gdtcmd, cmnd, 30, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986) /* configure lun */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) static int gdth_slave_configure(struct scsi_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) sdev->skip_ms_page_3f = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) sdev->skip_ms_page_8 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) static struct scsi_host_template gdth_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) .name = "GDT SCSI Disk Array Controller",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) .info = gdth_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) .queuecommand = gdth_queuecommand,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998) .eh_bus_reset_handler = gdth_eh_bus_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) .slave_configure = gdth_slave_configure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) .bios_param = gdth_bios_param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) .show_info = gdth_show_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) .write_info = gdth_set_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003) .eh_timed_out = gdth_timed_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) .proc_name = "gdth",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005) .can_queue = GDTH_MAXCMDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) .this_id = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) .sg_tablesize = GDTH_MAXSG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) .cmd_per_lun = GDTH_MAXC_P_L,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) .unchecked_isa_dma = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010) .no_write_same = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013) static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015) struct Scsi_Host *shp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) dma_addr_t scratch_dma_handle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) int error, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) struct pci_dev *pdev = pcistr->pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021) *ha_out = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024) if (!shp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) ha = shost_priv(shp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) error = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) if (!gdth_init_pci(pdev, pcistr, ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030) goto out_host_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) /* controller found and initialized */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033) printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034) pdev->bus->number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035) PCI_SLOT(pdev->devfn),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036) ha->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) error = request_irq(ha->irq, gdth_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039) IRQF_SHARED, "gdth", ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041) printk("GDT-PCI: Unable to allocate IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042) goto out_host_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045) shp->unchecked_isa_dma = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) shp->irq = ha->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) shp->dma_channel = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049) ha->hanum = gdth_ctr_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) ha->shost = shp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052) ha->pccb = &ha->cmdext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053) ha->ccb_phys = 0L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057) ha->pscratch = dma_alloc_coherent(&ha->pdev->dev, GDTH_SCRATCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) &scratch_dma_handle, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059) if (!ha->pscratch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) goto out_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061) ha->scratch_phys = scratch_dma_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063) ha->pmsg = dma_alloc_coherent(&ha->pdev->dev, sizeof(gdth_msg_str),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) &scratch_dma_handle, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) if (!ha->pmsg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) goto out_free_pscratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067) ha->msg_phys = scratch_dma_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) ha->scratch_busy = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070) ha->req_first = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071) ha->tid_cnt = pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) if (max_ids > 0 && max_ids < ha->tid_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073) ha->tid_cnt = max_ids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074) for (i = 0; i < GDTH_MAXCMDS; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) ha->cmd_tab[i].cmnd = UNUSED_CMND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) ha->scan_mode = rescan ? 0x10 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078) error = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079) if (!gdth_search_drives(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) printk("GDT-PCI %d: Error during device scan\n", ha->hanum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) goto out_free_pmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085) hdr_channel = ha->bus_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) ha->virt_bus = hdr_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) /* 64-bit DMA only supported from FW >= x.43 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089) if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090) !ha->dma64_support) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091) if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092) printk(KERN_WARNING "GDT-PCI %d: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093) "Unable to set 32-bit DMA\n", ha->hanum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094) goto out_free_pmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097) shp->max_cmd_len = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098) if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) printk("GDT-PCI %d: 64-bit DMA enabled\n", ha->hanum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100) } else if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101) printk(KERN_WARNING "GDT-PCI %d: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102) "Unable to set 64/32-bit DMA\n", ha->hanum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103) goto out_free_pmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107) shp->max_id = ha->tid_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108) shp->max_lun = MAXLUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109) shp->max_channel = ha->bus_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) spin_lock_init(&ha->smp_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112) gdth_enable_int(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114) error = scsi_add_host(shp, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116) goto out_free_pmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117) list_add_tail(&ha->list, &gdth_instances);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) pci_set_drvdata(ha->pdev, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120) gdth_timer_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122) scsi_scan_host(shp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) *ha_out = ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128) out_free_pmsg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129) dma_free_coherent(&ha->pdev->dev, sizeof(gdth_msg_str),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130) ha->pmsg, ha->msg_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) out_free_pscratch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132) dma_free_coherent(&ha->pdev->dev, GDTH_SCRATCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) ha->pscratch, ha->scratch_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134) out_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135) free_irq(ha->irq, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136) gdth_ctr_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) out_host_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138) scsi_host_put(shp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142) static void gdth_remove_one(gdth_ha_str *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144) struct Scsi_Host *shp = ha->shost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146) TRACE2(("gdth_remove_one()\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148) scsi_remove_host(shp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150) gdth_flush(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152) if (ha->sdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153) scsi_free_host_dev(ha->sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) ha->sdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157) if (shp->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158) free_irq(shp->irq,ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160) if (ha->pscratch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161) dma_free_coherent(&ha->pdev->dev, GDTH_SCRATCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162) ha->pscratch, ha->scratch_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) if (ha->pmsg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164) dma_free_coherent(&ha->pdev->dev, sizeof(gdth_msg_str),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) ha->pmsg, ha->msg_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166) if (ha->ccb_phys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167) dma_unmap_single(&ha->pdev->dev, ha->ccb_phys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168) sizeof(gdth_cmd_str), DMA_BIDIRECTIONAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) scsi_host_put(shp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173) static int gdth_halt(struct notifier_block *nb, unsigned long event, void *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177) TRACE2(("gdth_halt() event %d\n", (int)event));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178) if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179) return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181) list_for_each_entry(ha, &gdth_instances, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182) gdth_flush(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184) return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187) static struct notifier_block gdth_notifier = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188) gdth_halt, NULL, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191) static int __init gdth_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193) if (disable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194) printk("GDT-HA: Controller driver disabled from"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195) " command line !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199) printk("GDT-HA: Storage RAID Controller Driver. Version: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200) GDTH_VERSION_STR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202) /* initializations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203) gdth_polling = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204) gdth_clear_events();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) timer_setup(&gdth_timer, gdth_timeout, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207) /* scanning for PCI controllers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) if (pci_register_driver(&gdth_pci_driver)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211) list_for_each_entry(ha, &gdth_instances, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212) gdth_remove_one(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216) TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218) major = register_chrdev(0,"gdth", &gdth_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) register_reboot_notifier(&gdth_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220) gdth_polling = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224) static void __exit gdth_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226) gdth_ha_str *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228) unregister_chrdev(major, "gdth");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) unregister_reboot_notifier(&gdth_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231) #ifdef GDTH_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232) del_timer_sync(&gdth_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235) pci_unregister_driver(&gdth_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237) list_for_each_entry(ha, &gdth_instances, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) gdth_remove_one(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241) module_init(gdth_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242) module_exit(gdth_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245) static void __init internal_setup(char *str,int *ints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248) char *cur_str, *argv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250) TRACE2(("internal_setup() str %s ints[0] %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251) str ? str:"NULL", ints ? ints[0]:0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) /* analyse string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) argv = str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255) while (argv && (cur_str = strchr(argv, ':'))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256) int val = 0, c = *++cur_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258) if (c == 'n' || c == 'N')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260) else if (c == 'y' || c == 'Y')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261) val = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263) val = (int)simple_strtoul(cur_str, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265) if (!strncmp(argv, "disable:", 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266) disable = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267) else if (!strncmp(argv, "reserve_mode:", 13))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) reserve_mode = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) else if (!strncmp(argv, "reverse_scan:", 13))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270) reverse_scan = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271) else if (!strncmp(argv, "hdr_channel:", 12))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272) hdr_channel = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4273) else if (!strncmp(argv, "max_ids:", 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4274) max_ids = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4275) else if (!strncmp(argv, "rescan:", 7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4276) rescan = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4277) else if (!strncmp(argv, "shared_access:", 14))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4278) shared_access = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4279) else if (!strncmp(argv, "reserve_list:", 13)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4280) reserve_list[0] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4281) for (i = 1; i < MAX_RES_ARGS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4282) cur_str = strchr(cur_str, ',');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4283) if (!cur_str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4284) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4285) if (!isdigit((int)*++cur_str)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4286) --cur_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4287) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4289) reserve_list[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4290) (int)simple_strtoul(cur_str, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4292) if (!cur_str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4293) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4294) argv = ++cur_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4295) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4298) if ((argv = strchr(argv, ',')))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4299) ++argv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4303) static int __init option_setup(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4305) int ints[MAXHA];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4306) char *cur = str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4307) int i = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4309) TRACE2(("option_setup() str %s\n", str ? str:"NULL"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4311) while (cur && isdigit(*cur) && i < MAXHA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4312) ints[i++] = simple_strtoul(cur, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4313) if ((cur = strchr(cur, ',')) != NULL) cur++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4316) ints[0] = i - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4317) internal_setup(cur, ints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4318) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4321) __setup("gdth=", option_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4322) #endif