blob: 256dd6791fcc8bb0196e359ba6bd509c234080e3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/***************************************************************************
2 dpti.c - description
3 -------------------
4 begin : Thu Sep 7 2000
5 copyright : (C) 2000 by Adaptec
6
7 July 30, 2001 First version being submitted
8 for inclusion in the kernel. V2.4
9
10 See Documentation/scsi/dpti.txt for history, notes, license info
11 and credits
12 ***************************************************************************/
13
14/***************************************************************************
15 * *
16 * This program is free software; you can redistribute it and/or modify *
17 * it under the terms of the GNU General Public License as published by *
18 * the Free Software Foundation; either version 2 of the License, or *
19 * (at your option) any later version. *
20 * *
21 ***************************************************************************/
22/***************************************************************************
23 * Sat Dec 20 2003 Go Taniguchi <go@turbolinux.co.jp>
24 - Support 2.6 kernel and DMA-mapping
25 - ioctl fix for raid tools
26 - use schedule_timeout in long long loop
27 **************************************************************************/
28
29/*#define DEBUG 1 */
30/*#define UARTDELAY 1 */
31
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/module.h>
33
34MODULE_AUTHOR("Deanna Bonds, with _lots_ of help from Mark Salyzyn");
35MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
36
37////////////////////////////////////////////////////////////////
38
39#include <linux/ioctl.h> /* For SCSI-Passthrough */
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080040#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42#include <linux/stat.h>
43#include <linux/slab.h> /* for kmalloc() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/pci.h> /* for PCI support */
45#include <linux/proc_fs.h>
46#include <linux/blkdev.h>
47#include <linux/delay.h> /* for udelay */
48#include <linux/interrupt.h>
49#include <linux/kernel.h> /* for printk */
50#include <linux/sched.h>
51#include <linux/reboot.h>
52#include <linux/spinlock.h>
Matthias Gehre910638a2006-03-28 01:56:48 -080053#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55#include <linux/timer.h>
56#include <linux/string.h>
57#include <linux/ioport.h>
Arjan van de Ven0b950672006-01-11 13:16:10 +010058#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60#include <asm/processor.h> /* for boot_cpu_data */
61#include <asm/pgtable.h>
62#include <asm/io.h> /* for virt_to_bus, etc. */
63
64#include <scsi/scsi.h>
65#include <scsi/scsi_cmnd.h>
66#include <scsi/scsi_device.h>
67#include <scsi/scsi_host.h>
68#include <scsi/scsi_tcq.h>
69
70#include "dpt/dptsig.h"
71#include "dpti.h"
72
73/*============================================================================
74 * Create a binary signature - this is read by dptsig
75 * Needed for our management apps
76 *============================================================================
77 */
Arnd Bergmannc45d15d2010-06-02 14:28:52 +020078static DEFINE_MUTEX(adpt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079static dpt_sig_S DPTI_sig = {
80 {'d', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION,
81#ifdef __i386__
82 PROC_INTEL, PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM,
83#elif defined(__ia64__)
84 PROC_INTEL, PROC_IA64,
85#elif defined(__sparc__)
86 PROC_ULTRASPARC, PROC_ULTRASPARC,
87#elif defined(__alpha__)
88 PROC_ALPHA, PROC_ALPHA,
89#else
90 (-1),(-1),
91#endif
92 FT_HBADRVR, 0, OEM_DPT, OS_LINUX, CAP_OVERLAP, DEV_ALL,
93 ADF_ALL_SC5, 0, 0, DPT_VERSION, DPT_REVISION, DPT_SUBREVISION,
94 DPT_MONTH, DPT_DAY, DPT_YEAR, "Adaptec Linux I2O RAID Driver"
95};
96
97
98
99
100/*============================================================================
101 * Globals
102 *============================================================================
103 */
104
Arjan van de Ven0b950672006-01-11 13:16:10 +0100105static DEFINE_MUTEX(adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200107static struct i2o_sys_tbl *sys_tbl;
108static dma_addr_t sys_tbl_pa;
109static int sys_tbl_ind;
110static int sys_tbl_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112static adpt_hba* hba_chain = NULL;
113static int hba_count = 0;
114
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +0200115static struct class *adpt_sysfs_class;
116
Arnd Bergmannf4927c42010-04-27 00:24:01 +0200117static long adpt_unlocked_ioctl(struct file *, unsigned int, unsigned long);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200118#ifdef CONFIG_COMPAT
119static long compat_adpt_ioctl(struct file *, unsigned int, unsigned long);
120#endif
121
Arjan van de Ven00977a52007-02-12 00:55:34 -0800122static const struct file_operations adpt_fops = {
Arnd Bergmannf4927c42010-04-27 00:24:01 +0200123 .unlocked_ioctl = adpt_unlocked_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 .open = adpt_open,
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200125 .release = adpt_close,
126#ifdef CONFIG_COMPAT
127 .compat_ioctl = compat_adpt_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128#endif
Arnd Bergmann6038f372010-08-15 18:52:59 +0200129 .llseek = noop_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
132/* Structures and definitions for synchronous message posting.
133 * See adpt_i2o_post_wait() for description
134 * */
135struct adpt_i2o_post_wait_data
136{
137 int status;
138 u32 id;
139 adpt_wait_queue_head_t *wq;
140 struct adpt_i2o_post_wait_data *next;
141};
142
143static struct adpt_i2o_post_wait_data *adpt_post_wait_queue = NULL;
144static u32 adpt_post_wait_id = 0;
145static DEFINE_SPINLOCK(adpt_post_wait_lock);
146
147
148/*============================================================================
149 * Functions
150 *============================================================================
151 */
152
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200153static inline int dpt_dma64(adpt_hba *pHba)
154{
155 return (sizeof(dma_addr_t) > 4 && (pHba)->dma64);
156}
157
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200158static inline u32 dma_high(dma_addr_t addr)
159{
160 return upper_32_bits(addr);
161}
162
163static inline u32 dma_low(dma_addr_t addr)
164{
165 return (u32)addr;
166}
167
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168static u8 adpt_read_blink_led(adpt_hba* host)
169{
Harvey Harrison172c1222008-04-28 16:50:03 -0700170 if (host->FwDebugBLEDflag_P) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 if( readb(host->FwDebugBLEDflag_P) == 0xbc ){
172 return readb(host->FwDebugBLEDvalue_P);
173 }
174 }
175 return 0;
176}
177
178/*============================================================================
179 * Scsi host template interface functions
180 *============================================================================
181 */
182
Sudip Mukherjeef50abb92016-02-18 13:59:13 +0530183#ifdef MODULE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184static struct pci_device_id dptids[] = {
185 { PCI_DPT_VENDOR_ID, PCI_DPT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
186 { PCI_DPT_VENDOR_ID, PCI_DPT_RAPTOR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
187 { 0, }
188};
Sudip Mukherjeef50abb92016-02-18 13:59:13 +0530189#endif
190
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191MODULE_DEVICE_TABLE(pci,dptids);
192
Andrew Morton24601bb2007-12-10 15:49:20 -0800193static int adpt_detect(struct scsi_host_template* sht)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194{
195 struct pci_dev *pDev = NULL;
Dan Carpenter229bab62010-03-15 11:26:56 +0300196 adpt_hba *pHba;
197 adpt_hba *next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 PINFO("Detecting Adaptec I2O RAID controllers...\n");
200
201 /* search for all Adatpec I2O RAID cards */
Alan Coxa07f3532006-09-15 15:34:32 +0100202 while ((pDev = pci_get_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 if(pDev->device == PCI_DPT_DEVICE_ID ||
204 pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){
Andrew Morton24601bb2007-12-10 15:49:20 -0800205 if(adpt_install_hba(sht, pDev) ){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 PERROR("Could not Init an I2O RAID device\n");
207 PERROR("Will not try to detect others.\n");
208 return hba_count-1;
209 }
Alan Coxa07f3532006-09-15 15:34:32 +0100210 pci_dev_get(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 }
212 }
213
214 /* In INIT state, Activate IOPs */
Dan Carpenter229bab62010-03-15 11:26:56 +0300215 for (pHba = hba_chain; pHba; pHba = next) {
216 next = pHba->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 // Activate does get status , init outbound, and get hrt
218 if (adpt_i2o_activate_hba(pHba) < 0) {
219 adpt_i2o_delete_hba(pHba);
220 }
221 }
222
223
224 /* Active IOPs in HOLD state */
225
226rebuild_sys_tab:
227 if (hba_chain == NULL)
228 return 0;
229
230 /*
231 * If build_sys_table fails, we kill everything and bail
232 * as we can't init the IOPs w/o a system table
233 */
234 if (adpt_i2o_build_sys_table() < 0) {
235 adpt_i2o_sys_shutdown();
236 return 0;
237 }
238
239 PDEBUG("HBA's in HOLD state\n");
240
241 /* If IOP don't get online, we need to rebuild the System table */
242 for (pHba = hba_chain; pHba; pHba = pHba->next) {
243 if (adpt_i2o_online_hba(pHba) < 0) {
244 adpt_i2o_delete_hba(pHba);
245 goto rebuild_sys_tab;
246 }
247 }
248
249 /* Active IOPs now in OPERATIONAL state */
250 PDEBUG("HBA's in OPERATIONAL state\n");
251
252 printk("dpti: If you have a lot of devices this could take a few minutes.\n");
Dan Carpenter229bab62010-03-15 11:26:56 +0300253 for (pHba = hba_chain; pHba; pHba = next) {
254 next = pHba->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name);
256 if (adpt_i2o_lct_get(pHba) < 0){
257 adpt_i2o_delete_hba(pHba);
258 continue;
259 }
260
261 if (adpt_i2o_parse_lct(pHba) < 0){
262 adpt_i2o_delete_hba(pHba);
263 continue;
264 }
265 adpt_inquiry(pHba);
266 }
267
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +0200268 adpt_sysfs_class = class_create(THIS_MODULE, "dpt_i2o");
269 if (IS_ERR(adpt_sysfs_class)) {
270 printk(KERN_WARNING"dpti: unable to create dpt_i2o class\n");
271 adpt_sysfs_class = NULL;
272 }
273
Dan Carpenter229bab62010-03-15 11:26:56 +0300274 for (pHba = hba_chain; pHba; pHba = next) {
275 next = pHba->next;
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +0200276 if (adpt_scsi_host_alloc(pHba, sht) < 0){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 adpt_i2o_delete_hba(pHba);
278 continue;
279 }
280 pHba->initialized = TRUE;
281 pHba->state &= ~DPTI_STATE_RESET;
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +0200282 if (adpt_sysfs_class) {
Greg Kroah-Hartmand73a1a672008-07-21 20:03:34 -0700283 struct device *dev = device_create(adpt_sysfs_class,
Greg Kroah-Hartman9def0b92008-05-21 12:52:33 -0700284 NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +0200285 "dpti%d", pHba->unit);
286 if (IS_ERR(dev)) {
287 printk(KERN_WARNING"dpti%d: unable to "
288 "create device in dpt_i2o class\n",
289 pHba->unit);
290 }
291 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 }
293
294 // Register our control device node
295 // nodes will need to be created in /dev to access this
296 // the nodes can not be created from within the driver
297 if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) {
Andrew Morton24601bb2007-12-10 15:49:20 -0800298 adpt_i2o_sys_shutdown();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 return 0;
300 }
301 return hba_count;
302}
303
304
Andrew Morton24601bb2007-12-10 15:49:20 -0800305/*
306 * scsi_unregister will be called AFTER we return.
307 */
308static int adpt_release(struct Scsi_Host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309{
Andrew Morton24601bb2007-12-10 15:49:20 -0800310 adpt_hba* pHba = (adpt_hba*) host->hostdata[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311// adpt_i2o_quiesce_hba(pHba);
312 adpt_i2o_delete_hba(pHba);
Andrew Morton24601bb2007-12-10 15:49:20 -0800313 scsi_unregister(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 return 0;
315}
316
317
318static void adpt_inquiry(adpt_hba* pHba)
319{
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200320 u32 msg[17];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 u32 *mptr;
322 u32 *lenptr;
323 int direction;
324 int scsidir;
325 u32 len;
326 u32 reqlen;
327 u8* buf;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200328 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 u8 scb[16];
330 s32 rcode;
331
332 memset(msg, 0, sizeof(msg));
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200333 buf = dma_alloc_coherent(&pHba->pDev->dev, 80, &addr, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 if(!buf){
335 printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name);
336 return;
337 }
338 memset((void*)buf, 0, 36);
339
340 len = 36;
341 direction = 0x00000000;
342 scsidir =0x40000000; // DATA IN (iop<--dev)
343
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200344 if (dpt_dma64(pHba))
345 reqlen = 17; // SINGLE SGE, 64 bit
346 else
347 reqlen = 14; // SINGLE SGE, 32 bit
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 /* Stick the headers on */
349 msg[0] = reqlen<<16 | SGL_OFFSET_12;
350 msg[1] = (0xff<<24|HOST_TID<<12|ADAPTER_TID);
351 msg[2] = 0;
352 msg[3] = 0;
353 // Adaptec/DPT Private stuff
354 msg[4] = I2O_CMD_SCSI_EXEC|DPT_ORGANIZATION_ID<<16;
355 msg[5] = ADAPTER_TID | 1<<16 /* Interpret*/;
356 /* Direction, disconnect ok | sense data | simple queue , CDBLen */
357 // I2O_SCB_FLAG_ENABLE_DISCONNECT |
358 // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG |
359 // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;
360 msg[6] = scsidir|0x20a00000| 6 /* cmd len*/;
361
362 mptr=msg+7;
363
364 memset(scb, 0, sizeof(scb));
365 // Write SCSI command into the message - always 16 byte block
366 scb[0] = INQUIRY;
367 scb[1] = 0;
368 scb[2] = 0;
369 scb[3] = 0;
370 scb[4] = 36;
371 scb[5] = 0;
372 // Don't care about the rest of scb
373
374 memcpy(mptr, scb, sizeof(scb));
375 mptr+=4;
376 lenptr=mptr++; /* Remember me - fill in when we know */
377
378 /* Now fill in the SGList and command */
379 *lenptr = len;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200380 if (dpt_dma64(pHba)) {
381 *mptr++ = (0x7C<<24)+(2<<16)+0x02; /* Enable 64 bit */
382 *mptr++ = 1 << PAGE_SHIFT;
383 *mptr++ = 0xD0000000|direction|len;
384 *mptr++ = dma_low(addr);
385 *mptr++ = dma_high(addr);
386 } else {
387 *mptr++ = 0xD0000000|direction|len;
388 *mptr++ = addr;
389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
391 // Send it on it's way
392 rcode = adpt_i2o_post_wait(pHba, msg, reqlen<<2, 120);
393 if (rcode != 0) {
394 sprintf(pHba->detail, "Adaptec I2O RAID");
395 printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode);
396 if (rcode != -ETIME && rcode != -EINTR)
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200397 dma_free_coherent(&pHba->pDev->dev, 80, buf, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 } else {
399 memset(pHba->detail, 0, sizeof(pHba->detail));
400 memcpy(&(pHba->detail), "Vendor: Adaptec ", 16);
401 memcpy(&(pHba->detail[16]), " Model: ", 8);
402 memcpy(&(pHba->detail[24]), (u8*) &buf[16], 16);
403 memcpy(&(pHba->detail[40]), " FW: ", 4);
404 memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4);
405 pHba->detail[48] = '\0'; /* precautionary */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200406 dma_free_coherent(&pHba->pDev->dev, 80, buf, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 }
408 adpt_i2o_status_get(pHba);
409 return ;
410}
411
412
413static int adpt_slave_configure(struct scsi_device * device)
414{
415 struct Scsi_Host *host = device->host;
416 adpt_hba* pHba;
417
418 pHba = (adpt_hba *) host->hostdata[0];
419
420 if (host->can_queue && device->tagged_supported) {
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +0100421 scsi_change_queue_depth(device,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 host->can_queue - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 }
424 return 0;
425}
426
Jeff Garzikf2812332010-11-16 02:10:29 -0500427static int adpt_queue_lck(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{
429 adpt_hba* pHba = NULL;
430 struct adpt_device* pDev = NULL; /* dpt per device information */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
432 cmd->scsi_done = done;
433 /*
434 * SCSI REQUEST_SENSE commands will be executed automatically by the
435 * Host Adapter for any errors, so they should not be executed
436 * explicitly unless the Sense Data is zero indicating that no error
437 * occurred.
438 */
439
440 if ((cmd->cmnd[0] == REQUEST_SENSE) && (cmd->sense_buffer[0] != 0)) {
441 cmd->result = (DID_OK << 16);
442 cmd->scsi_done(cmd);
443 return 0;
444 }
445
446 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
447 if (!pHba) {
448 return FAILED;
449 }
450
451 rmb();
Hannes Reinecke63d80c42013-10-23 10:51:16 +0200452 if ((pHba->state) & DPTI_STATE_RESET)
453 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 // TODO if the cmd->device if offline then I may need to issue a bus rescan
456 // followed by a get_lct to see if the device is there anymore
457 if((pDev = (struct adpt_device*) (cmd->device->hostdata)) == NULL) {
458 /*
459 * First command request for this device. Set up a pointer
460 * to the device structure. This should be a TEST_UNIT_READY
461 * command from scan_scsis_single.
462 */
Hannes Reinecke9cb78c12014-06-25 15:27:36 +0200463 if ((pDev = adpt_find_device(pHba, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun)) == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 // TODO: if any luns are at this bus, scsi id then fake a TEST_UNIT_READY and INQUIRY response
465 // with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue.
466 cmd->result = (DID_NO_CONNECT << 16);
467 cmd->scsi_done(cmd);
468 return 0;
469 }
470 cmd->device->hostdata = pDev;
471 }
472 pDev->pScsi_dev = cmd->device;
473
474 /*
475 * If we are being called from when the device is being reset,
476 * delay processing of the command until later.
477 */
478 if (pDev->state & DPTI_DEV_RESET ) {
479 return FAILED;
480 }
481 return adpt_scsi_to_i2o(pHba, cmd, pDev);
482}
483
Jeff Garzikf2812332010-11-16 02:10:29 -0500484static DEF_SCSI_QCMD(adpt_queue)
485
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486static int adpt_bios_param(struct scsi_device *sdev, struct block_device *dev,
487 sector_t capacity, int geom[])
488{
489 int heads=-1;
490 int sectors=-1;
491 int cylinders=-1;
492
493 // *** First lets set the default geometry ****
494
495 // If the capacity is less than ox2000
496 if (capacity < 0x2000 ) { // floppy
497 heads = 18;
498 sectors = 2;
499 }
500 // else if between 0x2000 and 0x20000
501 else if (capacity < 0x20000) {
502 heads = 64;
503 sectors = 32;
504 }
505 // else if between 0x20000 and 0x40000
506 else if (capacity < 0x40000) {
507 heads = 65;
508 sectors = 63;
509 }
510 // else if between 0x4000 and 0x80000
511 else if (capacity < 0x80000) {
512 heads = 128;
513 sectors = 63;
514 }
515 // else if greater than 0x80000
516 else {
517 heads = 255;
518 sectors = 63;
519 }
520 cylinders = sector_div(capacity, heads * sectors);
521
522 // Special case if CDROM
523 if(sdev->type == 5) { // CDROM
524 heads = 252;
525 sectors = 63;
526 cylinders = 1111;
527 }
528
529 geom[0] = heads;
530 geom[1] = sectors;
531 geom[2] = cylinders;
532
533 PDEBUG("adpt_bios_param: exit\n");
534 return 0;
535}
536
537
538static const char *adpt_info(struct Scsi_Host *host)
539{
540 adpt_hba* pHba;
541
542 pHba = (adpt_hba *) host->hostdata[0];
543 return (char *) (pHba->detail);
544}
545
Al Viroff98f7c2013-03-31 03:21:50 -0400546static int adpt_show_info(struct seq_file *m, struct Scsi_Host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547{
548 struct adpt_device* d;
549 int id;
550 int chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 adpt_hba* pHba;
552 int unit;
553
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 // Find HBA (host bus adapter) we are looking for
Arjan van de Ven0b950672006-01-11 13:16:10 +0100555 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 for (pHba = hba_chain; pHba; pHba = pHba->next) {
557 if (pHba->host == host) {
558 break; /* found adapter */
559 }
560 }
Arjan van de Ven0b950672006-01-11 13:16:10 +0100561 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 if (pHba == NULL) {
563 return 0;
564 }
565 host = pHba->host;
566
Al Viroff98f7c2013-03-31 03:21:50 -0400567 seq_printf(m, "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION);
568 seq_printf(m, "%s\n", pHba->detail);
569 seq_printf(m, "SCSI Host=scsi%d Control Node=/dev/%s irq=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 pHba->host->host_no, pHba->name, host->irq);
Al Viroff98f7c2013-03-31 03:21:50 -0400571 seq_printf(m, "\tpost fifo size = %d\n\treply fifo size = %d\n\tsg table size = %d\n\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 host->can_queue, (int) pHba->reply_fifo_size , host->sg_tablesize);
573
Rasmus Villemoes91c40f22014-12-03 00:10:52 +0100574 seq_puts(m, "Devices:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 for(chan = 0; chan < MAX_CHANNEL; chan++) {
576 for(id = 0; id < MAX_ID; id++) {
577 d = pHba->channel[chan].device[id];
Al Viroff98f7c2013-03-31 03:21:50 -0400578 while(d) {
579 seq_printf(m,"\t%-24.24s", d->pScsi_dev->vendor);
580 seq_printf(m," Rev: %-8.8s\n", d->pScsi_dev->rev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
582 unit = d->pI2o_dev->lct_data.tid;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +0200583 seq_printf(m, "\tTID=%d, (Channel=%d, Target=%d, Lun=%llu) (%s)\n\n",
584 unit, (int)d->scsi_channel, (int)d->scsi_id, d->scsi_lun,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 scsi_device_online(d->pScsi_dev)? "online":"offline");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 d = d->next_lun;
587 }
588 }
589 }
Al Viroff98f7c2013-03-31 03:21:50 -0400590 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591}
592
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200593/*
594 * Turn a struct scsi_cmnd * into a unique 32 bit 'context'.
595 */
596static u32 adpt_cmd_to_context(struct scsi_cmnd *cmd)
597{
598 return (u32)cmd->serial_number;
599}
600
601/*
602 * Go from a u32 'context' to a struct scsi_cmnd * .
603 * This could probably be made more efficient.
604 */
605static struct scsi_cmnd *
606 adpt_cmd_from_context(adpt_hba * pHba, u32 context)
607{
608 struct scsi_cmnd * cmd;
609 struct scsi_device * d;
610
611 if (context == 0)
612 return NULL;
613
614 spin_unlock(pHba->host->host_lock);
615 shost_for_each_device(d, pHba->host) {
616 unsigned long flags;
617 spin_lock_irqsave(&d->list_lock, flags);
618 list_for_each_entry(cmd, &d->cmd_list, list) {
619 if (((u32)cmd->serial_number == context)) {
620 spin_unlock_irqrestore(&d->list_lock, flags);
621 scsi_device_put(d);
622 spin_lock(pHba->host->host_lock);
623 return cmd;
624 }
625 }
626 spin_unlock_irqrestore(&d->list_lock, flags);
627 }
628 spin_lock(pHba->host->host_lock);
629
630 return NULL;
631}
632
633/*
634 * Turn a pointer to ioctl reply data into an u32 'context'
635 */
636static u32 adpt_ioctl_to_context(adpt_hba * pHba, void *reply)
637{
638#if BITS_PER_LONG == 32
639 return (u32)(unsigned long)reply;
640#else
641 ulong flags = 0;
642 u32 nr, i;
643
644 spin_lock_irqsave(pHba->host->host_lock, flags);
645 nr = ARRAY_SIZE(pHba->ioctl_reply_context);
646 for (i = 0; i < nr; i++) {
647 if (pHba->ioctl_reply_context[i] == NULL) {
648 pHba->ioctl_reply_context[i] = reply;
649 break;
650 }
651 }
652 spin_unlock_irqrestore(pHba->host->host_lock, flags);
653 if (i >= nr) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200654 printk(KERN_WARNING"%s: Too many outstanding "
655 "ioctl commands\n", pHba->name);
656 return (u32)-1;
657 }
658
659 return i;
660#endif
661}
662
663/*
664 * Go from an u32 'context' to a pointer to ioctl reply data.
665 */
666static void *adpt_ioctl_from_context(adpt_hba *pHba, u32 context)
667{
668#if BITS_PER_LONG == 32
669 return (void *)(unsigned long)context;
670#else
671 void *p = pHba->ioctl_reply_context[context];
672 pHba->ioctl_reply_context[context] = NULL;
673
674 return p;
675#endif
676}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678/*===========================================================================
679 * Error Handling routines
680 *===========================================================================
681 */
682
683static int adpt_abort(struct scsi_cmnd * cmd)
684{
685 adpt_hba* pHba = NULL; /* host bus adapter structure */
686 struct adpt_device* dptdevice; /* dpt per device information */
687 u32 msg[5];
688 int rcode;
689
690 if(cmd->serial_number == 0){
691 return FAILED;
692 }
693 pHba = (adpt_hba*) cmd->device->host->hostdata[0];
Christoph Hellwig5cd049a2011-04-04 09:42:14 -0400694 printk(KERN_INFO"%s: Trying to Abort\n",pHba->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 if ((dptdevice = (void*) (cmd->device->hostdata)) == NULL) {
696 printk(KERN_ERR "%s: Unable to abort: No device in cmnd\n",pHba->name);
697 return FAILED;
698 }
699
700 memset(msg, 0, sizeof(msg));
701 msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
702 msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|dptdevice->tid;
703 msg[2] = 0;
704 msg[3]= 0;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200705 msg[4] = adpt_cmd_to_context(cmd);
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800706 if (pHba->host)
707 spin_lock_irq(pHba->host->host_lock);
708 rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER);
709 if (pHba->host)
710 spin_unlock_irq(pHba->host->host_lock);
711 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 if(rcode == -EOPNOTSUPP ){
713 printk(KERN_INFO"%s: Abort cmd not supported\n",pHba->name);
714 return FAILED;
715 }
Christoph Hellwig5cd049a2011-04-04 09:42:14 -0400716 printk(KERN_INFO"%s: Abort failed.\n",pHba->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 return FAILED;
718 }
Christoph Hellwig5cd049a2011-04-04 09:42:14 -0400719 printk(KERN_INFO"%s: Abort complete.\n",pHba->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 return SUCCESS;
721}
722
723
724#define I2O_DEVICE_RESET 0x27
725// This is the same for BLK and SCSI devices
726// NOTE this is wrong in the i2o.h definitions
727// This is not currently supported by our adapter but we issue it anyway
728static int adpt_device_reset(struct scsi_cmnd* cmd)
729{
730 adpt_hba* pHba;
731 u32 msg[4];
732 u32 rcode;
733 int old_state;
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -0700734 struct adpt_device* d = cmd->device->hostdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735
736 pHba = (void*) cmd->device->host->hostdata[0];
737 printk(KERN_INFO"%s: Trying to reset device\n",pHba->name);
738 if (!d) {
739 printk(KERN_INFO"%s: Reset Device: Device Not found\n",pHba->name);
740 return FAILED;
741 }
742 memset(msg, 0, sizeof(msg));
743 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
744 msg[1] = (I2O_DEVICE_RESET<<24|HOST_TID<<12|d->tid);
745 msg[2] = 0;
746 msg[3] = 0;
747
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800748 if (pHba->host)
749 spin_lock_irq(pHba->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 old_state = d->state;
751 d->state |= DPTI_DEV_RESET;
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800752 rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
753 d->state = old_state;
754 if (pHba->host)
755 spin_unlock_irq(pHba->host->host_lock);
756 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 if(rcode == -EOPNOTSUPP ){
758 printk(KERN_INFO"%s: Device reset not supported\n",pHba->name);
759 return FAILED;
760 }
761 printk(KERN_INFO"%s: Device reset failed\n",pHba->name);
762 return FAILED;
763 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 printk(KERN_INFO"%s: Device reset successful\n",pHba->name);
765 return SUCCESS;
766 }
767}
768
769
770#define I2O_HBA_BUS_RESET 0x87
771// This version of bus reset is called by the eh_error handler
772static int adpt_bus_reset(struct scsi_cmnd* cmd)
773{
774 adpt_hba* pHba;
775 u32 msg[4];
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800776 u32 rcode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777
778 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
779 memset(msg, 0, sizeof(msg));
780 printk(KERN_WARNING"%s: Bus reset: SCSI Bus %d: tid: %d\n",pHba->name, cmd->device->channel,pHba->channel[cmd->device->channel].tid );
781 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
782 msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->device->channel].tid);
783 msg[2] = 0;
784 msg[3] = 0;
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800785 if (pHba->host)
786 spin_lock_irq(pHba->host->host_lock);
787 rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
788 if (pHba->host)
789 spin_unlock_irq(pHba->host->host_lock);
790 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name);
792 return FAILED;
793 } else {
794 printk(KERN_WARNING"%s: Bus reset success.\n",pHba->name);
795 return SUCCESS;
796 }
797}
798
799// This version of reset is called by the eh_error_handler
Jeff Garzik df0ae242005-05-28 07:57:14 -0400800static int __adpt_reset(struct scsi_cmnd* cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801{
802 adpt_hba* pHba;
803 int rcode;
804 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
805 printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n",pHba->name,cmd->device->channel,pHba->channel[cmd->device->channel].tid );
806 rcode = adpt_hba_reset(pHba);
807 if(rcode == 0){
808 printk(KERN_WARNING"%s: HBA reset complete\n",pHba->name);
809 return SUCCESS;
810 } else {
811 printk(KERN_WARNING"%s: HBA reset failed (%x)\n",pHba->name, rcode);
812 return FAILED;
813 }
814}
815
Jeff Garzik df0ae242005-05-28 07:57:14 -0400816static int adpt_reset(struct scsi_cmnd* cmd)
817{
818 int rc;
819
820 spin_lock_irq(cmd->device->host->host_lock);
821 rc = __adpt_reset(cmd);
822 spin_unlock_irq(cmd->device->host->host_lock);
823
824 return rc;
825}
826
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827// This version of reset is called by the ioctls and indirectly from eh_error_handler via adpt_reset
828static int adpt_hba_reset(adpt_hba* pHba)
829{
830 int rcode;
831
832 pHba->state |= DPTI_STATE_RESET;
833
834 // Activate does get status , init outbound, and get hrt
835 if ((rcode=adpt_i2o_activate_hba(pHba)) < 0) {
836 printk(KERN_ERR "%s: Could not activate\n", pHba->name);
837 adpt_i2o_delete_hba(pHba);
838 return rcode;
839 }
840
841 if ((rcode=adpt_i2o_build_sys_table()) < 0) {
842 adpt_i2o_delete_hba(pHba);
843 return rcode;
844 }
845 PDEBUG("%s: in HOLD state\n",pHba->name);
846
847 if ((rcode=adpt_i2o_online_hba(pHba)) < 0) {
848 adpt_i2o_delete_hba(pHba);
849 return rcode;
850 }
851 PDEBUG("%s: in OPERATIONAL state\n",pHba->name);
852
853 if ((rcode=adpt_i2o_lct_get(pHba)) < 0){
854 adpt_i2o_delete_hba(pHba);
855 return rcode;
856 }
857
858 if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){
859 adpt_i2o_delete_hba(pHba);
860 return rcode;
861 }
862 pHba->state &= ~DPTI_STATE_RESET;
863
864 adpt_fail_posted_scbs(pHba);
865 return 0; /* return success */
866}
867
868/*===========================================================================
869 *
870 *===========================================================================
871 */
872
873
874static void adpt_i2o_sys_shutdown(void)
875{
876 adpt_hba *pHba, *pNext;
Adrian Bunk458af542005-11-27 00:36:37 +0100877 struct adpt_i2o_post_wait_data *p1, *old;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
879 printk(KERN_INFO"Shutting down Adaptec I2O controllers.\n");
880 printk(KERN_INFO" This could take a few minutes if there are many devices attached\n");
881 /* Delete all IOPs from the controller chain */
882 /* They should have already been released by the
883 * scsi-core
884 */
885 for (pHba = hba_chain; pHba; pHba = pNext) {
886 pNext = pHba->next;
887 adpt_i2o_delete_hba(pHba);
888 }
889
890 /* Remove any timedout entries from the wait queue. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891// spin_lock_irqsave(&adpt_post_wait_lock, flags);
892 /* Nothing should be outstanding at this point so just
893 * free them
894 */
Adrian Bunk458af542005-11-27 00:36:37 +0100895 for(p1 = adpt_post_wait_queue; p1;) {
896 old = p1;
897 p1 = p1->next;
898 kfree(old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 }
900// spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
901 adpt_post_wait_queue = NULL;
902
903 printk(KERN_INFO "Adaptec I2O controllers down.\n");
904}
905
Andrew Morton24601bb2007-12-10 15:49:20 -0800906static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907{
908
909 adpt_hba* pHba = NULL;
910 adpt_hba* p = NULL;
911 ulong base_addr0_phys = 0;
912 ulong base_addr1_phys = 0;
913 u32 hba_map0_area_size = 0;
914 u32 hba_map1_area_size = 0;
915 void __iomem *base_addr_virt = NULL;
916 void __iomem *msg_addr_virt = NULL;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200917 int dma64 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918
919 int raptorFlag = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
921 if(pci_enable_device(pDev)) {
922 return -EINVAL;
923 }
Salyzyn, Mark9638d892006-01-12 08:31:57 -0500924
925 if (pci_request_regions(pDev, "dpt_i2o")) {
926 PERROR("dpti: adpt_config_hba: pci request region failed\n");
927 return -EINVAL;
928 }
929
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 pci_set_master(pDev);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200931
932 /*
933 * See if we should enable dma64 mode.
934 */
935 if (sizeof(dma_addr_t) > 4 &&
Yang Hongyang6a355282009-04-06 19:01:13 -0700936 pci_set_dma_mask(pDev, DMA_BIT_MASK(64)) == 0) {
Yang Hongyang284901a2009-04-06 19:01:15 -0700937 if (dma_get_required_mask(&pDev->dev) > DMA_BIT_MASK(32))
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200938 dma64 = 1;
939 }
Yang Hongyang284901a2009-04-06 19:01:15 -0700940 if (!dma64 && pci_set_dma_mask(pDev, DMA_BIT_MASK(32)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 return -EINVAL;
942
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200943 /* adapter only supports message blocks below 4GB */
Yang Hongyang284901a2009-04-06 19:01:15 -0700944 pci_set_consistent_dma_mask(pDev, DMA_BIT_MASK(32));
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200945
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 base_addr0_phys = pci_resource_start(pDev,0);
947 hba_map0_area_size = pci_resource_len(pDev,0);
948
949 // Check if standard PCI card or single BAR Raptor
950 if(pDev->device == PCI_DPT_DEVICE_ID){
951 if(pDev->subsystem_device >=0xc032 && pDev->subsystem_device <= 0xc03b){
952 // Raptor card with this device id needs 4M
953 hba_map0_area_size = 0x400000;
954 } else { // Not Raptor - it is a PCI card
955 if(hba_map0_area_size > 0x100000 ){
956 hba_map0_area_size = 0x100000;
957 }
958 }
959 } else {// Raptor split BAR config
960 // Use BAR1 in this configuration
961 base_addr1_phys = pci_resource_start(pDev,1);
962 hba_map1_area_size = pci_resource_len(pDev,1);
963 raptorFlag = TRUE;
964 }
965
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200966#if BITS_PER_LONG == 64
967 /*
968 * The original Adaptec 64 bit driver has this comment here:
969 * "x86_64 machines need more optimal mappings"
970 *
971 * I assume some HBAs report ridiculously large mappings
972 * and we need to limit them on platforms with IOMMUs.
973 */
974 if (raptorFlag == TRUE) {
975 if (hba_map0_area_size > 128)
976 hba_map0_area_size = 128;
977 if (hba_map1_area_size > 524288)
978 hba_map1_area_size = 524288;
979 } else {
980 if (hba_map0_area_size > 524288)
981 hba_map0_area_size = 524288;
982 }
983#endif
984
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size);
986 if (!base_addr_virt) {
James Bottomley9c472dd2005-08-08 11:51:38 -0500987 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 PERROR("dpti: adpt_config_hba: io remap failed\n");
989 return -EINVAL;
990 }
991
992 if(raptorFlag == TRUE) {
993 msg_addr_virt = ioremap(base_addr1_phys, hba_map1_area_size );
994 if (!msg_addr_virt) {
995 PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n");
996 iounmap(base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -0500997 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 return -EINVAL;
999 }
1000 } else {
1001 msg_addr_virt = base_addr_virt;
1002 }
1003
1004 // Allocate and zero the data structure
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02001005 pHba = kzalloc(sizeof(adpt_hba), GFP_KERNEL);
1006 if (!pHba) {
1007 if (msg_addr_virt != base_addr_virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 iounmap(msg_addr_virt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 iounmap(base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -05001010 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 return -ENOMEM;
1012 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
Arjan van de Ven0b950672006-01-11 13:16:10 +01001014 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
1016 if(hba_chain != NULL){
1017 for(p = hba_chain; p->next; p = p->next);
1018 p->next = pHba;
1019 } else {
1020 hba_chain = pHba;
1021 }
1022 pHba->next = NULL;
1023 pHba->unit = hba_count;
Benoit Boissinot 23a2bc22005-04-25 19:46:30 -07001024 sprintf(pHba->name, "dpti%d", hba_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 hba_count++;
1026
Arjan van de Ven0b950672006-01-11 13:16:10 +01001027 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
1029 pHba->pDev = pDev;
1030 pHba->base_addr_phys = base_addr0_phys;
1031
1032 // Set up the Virtual Base Address of the I2O Device
1033 pHba->base_addr_virt = base_addr_virt;
1034 pHba->msg_addr_virt = msg_addr_virt;
1035 pHba->irq_mask = base_addr_virt+0x30;
1036 pHba->post_port = base_addr_virt+0x40;
1037 pHba->reply_port = base_addr_virt+0x44;
1038
1039 pHba->hrt = NULL;
1040 pHba->lct = NULL;
1041 pHba->lct_size = 0;
1042 pHba->status_block = NULL;
1043 pHba->post_count = 0;
1044 pHba->state = DPTI_STATE_RESET;
1045 pHba->pDev = pDev;
1046 pHba->devices = NULL;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001047 pHba->dma64 = dma64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
1049 // Initializing the spinlocks
1050 spin_lock_init(&pHba->state_lock);
1051 spin_lock_init(&adpt_post_wait_lock);
1052
1053 if(raptorFlag == 0){
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001054 printk(KERN_INFO "Adaptec I2O RAID controller"
1055 " %d at %p size=%x irq=%d%s\n",
1056 hba_count-1, base_addr_virt,
1057 hba_map0_area_size, pDev->irq,
1058 dma64 ? " (64-bit DMA)" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 } else {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001060 printk(KERN_INFO"Adaptec I2O RAID controller %d irq=%d%s\n",
1061 hba_count-1, pDev->irq,
1062 dma64 ? " (64-bit DMA)" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 printk(KERN_INFO" BAR0 %p - size= %x\n",base_addr_virt,hba_map0_area_size);
1064 printk(KERN_INFO" BAR1 %p - size= %x\n",msg_addr_virt,hba_map1_area_size);
1065 }
1066
Thomas Gleixner1d6f3592006-07-01 19:29:42 -07001067 if (request_irq (pDev->irq, adpt_isr, IRQF_SHARED, pHba->name, pHba)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 printk(KERN_ERR"%s: Couldn't register IRQ %d\n", pHba->name, pDev->irq);
1069 adpt_i2o_delete_hba(pHba);
1070 return -EINVAL;
1071 }
1072
1073 return 0;
1074}
1075
1076
1077static void adpt_i2o_delete_hba(adpt_hba* pHba)
1078{
1079 adpt_hba* p1;
1080 adpt_hba* p2;
1081 struct i2o_device* d;
1082 struct i2o_device* next;
1083 int i;
1084 int j;
1085 struct adpt_device* pDev;
1086 struct adpt_device* pNext;
1087
1088
Arjan van de Ven0b950672006-01-11 13:16:10 +01001089 mutex_lock(&adpt_configuration_lock);
Andrew Morton24601bb2007-12-10 15:49:20 -08001090 // scsi_unregister calls our adpt_release which
1091 // does a quiese
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 if(pHba->host){
1093 free_irq(pHba->host->irq, pHba);
1094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 p2 = NULL;
1096 for( p1 = hba_chain; p1; p2 = p1,p1=p1->next){
1097 if(p1 == pHba) {
1098 if(p2) {
1099 p2->next = p1->next;
1100 } else {
1101 hba_chain = p1->next;
1102 }
1103 break;
1104 }
1105 }
1106
1107 hba_count--;
Arjan van de Ven0b950672006-01-11 13:16:10 +01001108 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
1110 iounmap(pHba->base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -05001111 pci_release_regions(pHba->pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 if(pHba->msg_addr_virt != pHba->base_addr_virt){
1113 iounmap(pHba->msg_addr_virt);
1114 }
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001115 if(pHba->FwDebugBuffer_P)
1116 iounmap(pHba->FwDebugBuffer_P);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001117 if(pHba->hrt) {
1118 dma_free_coherent(&pHba->pDev->dev,
1119 pHba->hrt->num_entries * pHba->hrt->entry_len << 2,
1120 pHba->hrt, pHba->hrt_pa);
1121 }
1122 if(pHba->lct) {
1123 dma_free_coherent(&pHba->pDev->dev, pHba->lct_size,
1124 pHba->lct, pHba->lct_pa);
1125 }
1126 if(pHba->status_block) {
1127 dma_free_coherent(&pHba->pDev->dev, sizeof(i2o_status_block),
1128 pHba->status_block, pHba->status_block_pa);
1129 }
1130 if(pHba->reply_pool) {
1131 dma_free_coherent(&pHba->pDev->dev,
1132 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
1133 pHba->reply_pool, pHba->reply_pool_pa);
1134 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
1136 for(d = pHba->devices; d ; d = next){
1137 next = d->next;
1138 kfree(d);
1139 }
1140 for(i = 0 ; i < pHba->top_scsi_channel ; i++){
1141 for(j = 0; j < MAX_ID; j++){
1142 if(pHba->channel[i].device[j] != NULL){
1143 for(pDev = pHba->channel[i].device[j]; pDev; pDev = pNext){
1144 pNext = pDev->next_lun;
1145 kfree(pDev);
1146 }
1147 }
1148 }
1149 }
Alan Coxa07f3532006-09-15 15:34:32 +01001150 pci_dev_put(pHba->pDev);
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +02001151 if (adpt_sysfs_class)
1152 device_destroy(adpt_sysfs_class,
1153 MKDEV(DPTI_I2O_MAJOR, pHba->unit));
Dan Carpenter229bab62010-03-15 11:26:56 +03001154 kfree(pHba);
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +02001155
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 if(hba_count <= 0){
1157 unregister_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER);
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +02001158 if (adpt_sysfs_class) {
1159 class_destroy(adpt_sysfs_class);
1160 adpt_sysfs_class = NULL;
1161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 }
1163}
1164
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02001165static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166{
1167 struct adpt_device* d;
1168
1169 if(chan < 0 || chan >= MAX_CHANNEL)
1170 return NULL;
1171
1172 if( pHba->channel[chan].device == NULL){
1173 printk(KERN_DEBUG"Adaptec I2O RAID: Trying to find device before they are allocated\n");
1174 return NULL;
1175 }
1176
1177 d = pHba->channel[chan].device[id];
1178 if(!d || d->tid == 0) {
1179 return NULL;
1180 }
1181
1182 /* If it is the only lun at that address then this should match*/
1183 if(d->scsi_lun == lun){
1184 return d;
1185 }
1186
1187 /* else we need to look through all the luns */
1188 for(d=d->next_lun ; d ; d = d->next_lun){
1189 if(d->scsi_lun == lun){
1190 return d;
1191 }
1192 }
1193 return NULL;
1194}
1195
1196
1197static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout)
1198{
1199 // I used my own version of the WAIT_QUEUE_HEAD
1200 // to handle some version differences
1201 // When embedded in the kernel this could go back to the vanilla one
1202 ADPT_DECLARE_WAIT_QUEUE_HEAD(adpt_wq_i2o_post);
1203 int status = 0;
1204 ulong flags = 0;
1205 struct adpt_i2o_post_wait_data *p1, *p2;
1206 struct adpt_i2o_post_wait_data *wait_data =
Julia Lawallda2907f2010-05-30 15:49:22 +02001207 kmalloc(sizeof(struct adpt_i2o_post_wait_data), GFP_ATOMIC);
Andrew Morton4452ea52005-06-23 00:10:26 -07001208 DECLARE_WAITQUEUE(wait, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209
Andrew Morton4452ea52005-06-23 00:10:26 -07001210 if (!wait_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 return -ENOMEM;
Andrew Morton4452ea52005-06-23 00:10:26 -07001212
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 /*
1214 * The spin locking is needed to keep anyone from playing
1215 * with the queue pointers and id while we do the same
1216 */
1217 spin_lock_irqsave(&adpt_post_wait_lock, flags);
1218 // TODO we need a MORE unique way of getting ids
1219 // to support async LCT get
1220 wait_data->next = adpt_post_wait_queue;
1221 adpt_post_wait_queue = wait_data;
1222 adpt_post_wait_id++;
1223 adpt_post_wait_id &= 0x7fff;
1224 wait_data->id = adpt_post_wait_id;
1225 spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
1226
1227 wait_data->wq = &adpt_wq_i2o_post;
1228 wait_data->status = -ETIMEDOUT;
1229
Andrew Morton4452ea52005-06-23 00:10:26 -07001230 add_wait_queue(&adpt_wq_i2o_post, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
1232 msg[2] |= 0x80000000 | ((u32)wait_data->id);
1233 timeout *= HZ;
1234 if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){
1235 set_current_state(TASK_INTERRUPTIBLE);
1236 if(pHba->host)
1237 spin_unlock_irq(pHba->host->host_lock);
1238 if (!timeout)
1239 schedule();
1240 else{
1241 timeout = schedule_timeout(timeout);
1242 if (timeout == 0) {
1243 // I/O issued, but cannot get result in
1244 // specified time. Freeing resorces is
1245 // dangerous.
1246 status = -ETIME;
1247 }
1248 }
1249 if(pHba->host)
1250 spin_lock_irq(pHba->host->host_lock);
1251 }
Andrew Morton4452ea52005-06-23 00:10:26 -07001252 remove_wait_queue(&adpt_wq_i2o_post, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
1254 if(status == -ETIMEDOUT){
1255 printk(KERN_INFO"dpti%d: POST WAIT TIMEOUT\n",pHba->unit);
1256 // We will have to free the wait_data memory during shutdown
1257 return status;
1258 }
1259
1260 /* Remove the entry from the queue. */
1261 p2 = NULL;
1262 spin_lock_irqsave(&adpt_post_wait_lock, flags);
1263 for(p1 = adpt_post_wait_queue; p1; p2 = p1, p1 = p1->next) {
1264 if(p1 == wait_data) {
1265 if(p1->status == I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION ) {
1266 status = -EOPNOTSUPP;
1267 }
1268 if(p2) {
1269 p2->next = p1->next;
1270 } else {
1271 adpt_post_wait_queue = p1->next;
1272 }
1273 break;
1274 }
1275 }
1276 spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
1277
1278 kfree(wait_data);
1279
1280 return status;
1281}
1282
1283
1284static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len)
1285{
1286
1287 u32 m = EMPTY_QUEUE;
1288 u32 __iomem *msg;
1289 ulong timeout = jiffies + 30*HZ;
1290 do {
1291 rmb();
1292 m = readl(pHba->post_port);
1293 if (m != EMPTY_QUEUE) {
1294 break;
1295 }
1296 if(time_after(jiffies,timeout)){
1297 printk(KERN_WARNING"dpti%d: Timeout waiting for message frame!\n", pHba->unit);
1298 return -ETIMEDOUT;
1299 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001300 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 } while(m == EMPTY_QUEUE);
1302
1303 msg = pHba->msg_addr_virt + m;
1304 memcpy_toio(msg, data, len);
1305 wmb();
1306
1307 //post message
1308 writel(m, pHba->post_port);
1309 wmb();
1310
1311 return 0;
1312}
1313
1314
1315static void adpt_i2o_post_wait_complete(u32 context, int status)
1316{
1317 struct adpt_i2o_post_wait_data *p1 = NULL;
1318 /*
1319 * We need to search through the adpt_post_wait
1320 * queue to see if the given message is still
1321 * outstanding. If not, it means that the IOP
1322 * took longer to respond to the message than we
1323 * had allowed and timer has already expired.
1324 * Not much we can do about that except log
1325 * it for debug purposes, increase timeout, and recompile
1326 *
1327 * Lock needed to keep anyone from moving queue pointers
1328 * around while we're looking through them.
1329 */
1330
1331 context &= 0x7fff;
1332
1333 spin_lock(&adpt_post_wait_lock);
1334 for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) {
1335 if(p1->id == context) {
1336 p1->status = status;
1337 spin_unlock(&adpt_post_wait_lock);
1338 wake_up_interruptible(p1->wq);
1339 return;
1340 }
1341 }
1342 spin_unlock(&adpt_post_wait_lock);
1343 // If this happens we lose commands that probably really completed
1344 printk(KERN_DEBUG"dpti: Could Not find task %d in wait queue\n",context);
1345 printk(KERN_DEBUG" Tasks in wait queue:\n");
1346 for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) {
1347 printk(KERN_DEBUG" %d\n",p1->id);
1348 }
1349 return;
1350}
1351
1352static s32 adpt_i2o_reset_hba(adpt_hba* pHba)
1353{
1354 u32 msg[8];
1355 u8* status;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001356 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 u32 m = EMPTY_QUEUE ;
1358 ulong timeout = jiffies + (TMOUT_IOPRESET*HZ);
1359
1360 if(pHba->initialized == FALSE) { // First time reset should be quick
1361 timeout = jiffies + (25*HZ);
1362 } else {
1363 adpt_i2o_quiesce_hba(pHba);
1364 }
1365
1366 do {
1367 rmb();
1368 m = readl(pHba->post_port);
1369 if (m != EMPTY_QUEUE) {
1370 break;
1371 }
1372 if(time_after(jiffies,timeout)){
1373 printk(KERN_WARNING"Timeout waiting for message!\n");
1374 return -ETIMEDOUT;
1375 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001376 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 } while (m == EMPTY_QUEUE);
1378
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001379 status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 if(status == NULL) {
1381 adpt_send_nop(pHba, m);
1382 printk(KERN_ERR"IOP reset failed - no free memory.\n");
1383 return -ENOMEM;
1384 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001385 memset(status,0,4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387 msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
1388 msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
1389 msg[2]=0;
1390 msg[3]=0;
1391 msg[4]=0;
1392 msg[5]=0;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001393 msg[6]=dma_low(addr);
1394 msg[7]=dma_high(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
1396 memcpy_toio(pHba->msg_addr_virt+m, msg, sizeof(msg));
1397 wmb();
1398 writel(m, pHba->post_port);
1399 wmb();
1400
1401 while(*status == 0){
1402 if(time_after(jiffies,timeout)){
1403 printk(KERN_WARNING"%s: IOP Reset Timeout\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001404 /* We lose 4 bytes of "status" here, but we cannot
1405 free these because controller may awake and corrupt
1406 those bytes at any time */
1407 /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 return -ETIMEDOUT;
1409 }
1410 rmb();
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001411 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 }
1413
1414 if(*status == 0x01 /*I2O_EXEC_IOP_RESET_IN_PROGRESS*/) {
1415 PDEBUG("%s: Reset in progress...\n", pHba->name);
1416 // Here we wait for message frame to become available
1417 // indicated that reset has finished
1418 do {
1419 rmb();
1420 m = readl(pHba->post_port);
1421 if (m != EMPTY_QUEUE) {
1422 break;
1423 }
1424 if(time_after(jiffies,timeout)){
1425 printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001426 /* We lose 4 bytes of "status" here, but we
1427 cannot free these because controller may
1428 awake and corrupt those bytes at any time */
1429 /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 return -ETIMEDOUT;
1431 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001432 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 } while (m == EMPTY_QUEUE);
1434 // Flush the offset
1435 adpt_send_nop(pHba, m);
1436 }
1437 adpt_i2o_status_get(pHba);
1438 if(*status == 0x02 ||
1439 pHba->status_block->iop_state != ADAPTER_STATE_RESET) {
1440 printk(KERN_WARNING"%s: Reset reject, trying to clear\n",
1441 pHba->name);
1442 } else {
1443 PDEBUG("%s: Reset completed.\n", pHba->name);
1444 }
1445
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001446 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447#ifdef UARTDELAY
1448 // This delay is to allow someone attached to the card through the debug UART to
1449 // set up the dump levels that they want before the rest of the initialization sequence
1450 adpt_delay(20000);
1451#endif
1452 return 0;
1453}
1454
1455
1456static int adpt_i2o_parse_lct(adpt_hba* pHba)
1457{
1458 int i;
1459 int max;
1460 int tid;
1461 struct i2o_device *d;
1462 i2o_lct *lct = pHba->lct;
1463 u8 bus_no = 0;
1464 s16 scsi_id;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02001465 u64 scsi_lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 u32 buf[10]; // larger than 7, or 8 ...
1467 struct adpt_device* pDev;
1468
1469 if (lct == NULL) {
1470 printk(KERN_ERR "%s: LCT is empty???\n",pHba->name);
1471 return -1;
1472 }
1473
1474 max = lct->table_size;
1475 max -= 3;
1476 max /= 9;
1477
1478 for(i=0;i<max;i++) {
1479 if( lct->lct_entry[i].user_tid != 0xfff){
1480 /*
1481 * If we have hidden devices, we need to inform the upper layers about
1482 * the possible maximum id reference to handle device access when
1483 * an array is disassembled. This code has no other purpose but to
1484 * allow us future access to devices that are currently hidden
1485 * behind arrays, hotspares or have not been configured (JBOD mode).
1486 */
1487 if( lct->lct_entry[i].class_id != I2O_CLASS_RANDOM_BLOCK_STORAGE &&
1488 lct->lct_entry[i].class_id != I2O_CLASS_SCSI_PERIPHERAL &&
1489 lct->lct_entry[i].class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
1490 continue;
1491 }
1492 tid = lct->lct_entry[i].tid;
1493 // I2O_DPT_DEVICE_INFO_GROUP_NO;
1494 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) {
1495 continue;
1496 }
1497 bus_no = buf[0]>>16;
1498 scsi_id = buf[1];
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02001499 scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1501 printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no);
1502 continue;
1503 }
1504 if (scsi_id >= MAX_ID){
1505 printk(KERN_WARNING"%s: SCSI ID %d out of range \n", pHba->name, bus_no);
1506 continue;
1507 }
1508 if(bus_no > pHba->top_scsi_channel){
1509 pHba->top_scsi_channel = bus_no;
1510 }
1511 if(scsi_id > pHba->top_scsi_id){
1512 pHba->top_scsi_id = scsi_id;
1513 }
1514 if(scsi_lun > pHba->top_scsi_lun){
1515 pHba->top_scsi_lun = scsi_lun;
1516 }
1517 continue;
1518 }
Robert P. J. Day5cbded52006-12-13 00:35:56 -08001519 d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 if(d==NULL)
1521 {
1522 printk(KERN_CRIT"%s: Out of memory for I2O device data.\n",pHba->name);
1523 return -ENOMEM;
1524 }
1525
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07001526 d->controller = pHba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 d->next = NULL;
1528
1529 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
1530
1531 d->flags = 0;
1532 tid = d->lct_data.tid;
1533 adpt_i2o_report_hba_unit(pHba, d);
1534 adpt_i2o_install_device(pHba, d);
1535 }
1536 bus_no = 0;
1537 for(d = pHba->devices; d ; d = d->next) {
1538 if(d->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT ||
1539 d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PORT){
1540 tid = d->lct_data.tid;
1541 // TODO get the bus_no from hrt-but for now they are in order
1542 //bus_no =
1543 if(bus_no > pHba->top_scsi_channel){
1544 pHba->top_scsi_channel = bus_no;
1545 }
1546 pHba->channel[bus_no].type = d->lct_data.class_id;
1547 pHba->channel[bus_no].tid = tid;
1548 if(adpt_i2o_query_scalar(pHba, tid, 0x0200, -1, buf, 28)>=0)
1549 {
1550 pHba->channel[bus_no].scsi_id = buf[1];
1551 PDEBUG("Bus %d - SCSI ID %d.\n", bus_no, buf[1]);
1552 }
1553 // TODO remove - this is just until we get from hrt
1554 bus_no++;
1555 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1556 printk(KERN_WARNING"%s: Channel number %d out of range - LCT\n", pHba->name, bus_no);
1557 break;
1558 }
1559 }
1560 }
1561
1562 // Setup adpt_device table
1563 for(d = pHba->devices; d ; d = d->next) {
1564 if(d->lct_data.class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE ||
1565 d->lct_data.class_id == I2O_CLASS_SCSI_PERIPHERAL ||
1566 d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
1567
1568 tid = d->lct_data.tid;
1569 scsi_id = -1;
1570 // I2O_DPT_DEVICE_INFO_GROUP_NO;
1571 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)>=0) {
1572 bus_no = buf[0]>>16;
1573 scsi_id = buf[1];
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02001574 scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1576 continue;
1577 }
1578 if (scsi_id >= MAX_ID) {
1579 continue;
1580 }
1581 if( pHba->channel[bus_no].device[scsi_id] == NULL){
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301582 pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 if(pDev == NULL) {
1584 return -ENOMEM;
1585 }
1586 pHba->channel[bus_no].device[scsi_id] = pDev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 } else {
1588 for( pDev = pHba->channel[bus_no].device[scsi_id];
1589 pDev->next_lun; pDev = pDev->next_lun){
1590 }
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301591 pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 if(pDev->next_lun == NULL) {
1593 return -ENOMEM;
1594 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 pDev = pDev->next_lun;
1596 }
1597 pDev->tid = tid;
1598 pDev->scsi_channel = bus_no;
1599 pDev->scsi_id = scsi_id;
1600 pDev->scsi_lun = scsi_lun;
1601 pDev->pI2o_dev = d;
1602 d->owner = pDev;
1603 pDev->type = (buf[0])&0xff;
1604 pDev->flags = (buf[0]>>8)&0xff;
1605 if(scsi_id > pHba->top_scsi_id){
1606 pHba->top_scsi_id = scsi_id;
1607 }
1608 if(scsi_lun > pHba->top_scsi_lun){
1609 pHba->top_scsi_lun = scsi_lun;
1610 }
1611 }
1612 if(scsi_id == -1){
1613 printk(KERN_WARNING"Could not find SCSI ID for %s\n",
1614 d->lct_data.identity_tag);
1615 }
1616 }
1617 }
1618 return 0;
1619}
1620
1621
1622/*
1623 * Each I2O controller has a chain of devices on it - these match
1624 * the useful parts of the LCT of the board.
1625 */
1626
1627static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d)
1628{
Arjan van de Ven0b950672006-01-11 13:16:10 +01001629 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 d->controller=pHba;
1631 d->owner=NULL;
1632 d->next=pHba->devices;
1633 d->prev=NULL;
1634 if (pHba->devices != NULL){
1635 pHba->devices->prev=d;
1636 }
1637 pHba->devices=d;
1638 *d->dev_name = 0;
1639
Arjan van de Ven0b950672006-01-11 13:16:10 +01001640 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 return 0;
1642}
1643
1644static int adpt_open(struct inode *inode, struct file *file)
1645{
1646 int minor;
1647 adpt_hba* pHba;
1648
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02001649 mutex_lock(&adpt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 //TODO check for root access
1651 //
1652 minor = iminor(inode);
1653 if (minor >= hba_count) {
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02001654 mutex_unlock(&adpt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 return -ENXIO;
1656 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001657 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1659 if (pHba->unit == minor) {
1660 break; /* found adapter */
1661 }
1662 }
1663 if (pHba == NULL) {
Arjan van de Ven0b950672006-01-11 13:16:10 +01001664 mutex_unlock(&adpt_configuration_lock);
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02001665 mutex_unlock(&adpt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 return -ENXIO;
1667 }
1668
1669// if(pHba->in_use){
Arjan van de Ven0b950672006-01-11 13:16:10 +01001670 // mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671// return -EBUSY;
1672// }
1673
1674 pHba->in_use = 1;
Arjan van de Ven0b950672006-01-11 13:16:10 +01001675 mutex_unlock(&adpt_configuration_lock);
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02001676 mutex_unlock(&adpt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677
1678 return 0;
1679}
1680
1681static int adpt_close(struct inode *inode, struct file *file)
1682{
1683 int minor;
1684 adpt_hba* pHba;
1685
1686 minor = iminor(inode);
1687 if (minor >= hba_count) {
1688 return -ENXIO;
1689 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001690 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1692 if (pHba->unit == minor) {
1693 break; /* found adapter */
1694 }
1695 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001696 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 if (pHba == NULL) {
1698 return -ENXIO;
1699 }
1700
1701 pHba->in_use = 0;
1702
1703 return 0;
1704}
1705
1706
1707static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
1708{
1709 u32 msg[MAX_MESSAGE_SIZE];
1710 u32* reply = NULL;
1711 u32 size = 0;
1712 u32 reply_size = 0;
1713 u32 __user *user_msg = arg;
1714 u32 __user * user_reply = NULL;
1715 void *sg_list[pHba->sg_tablesize];
1716 u32 sg_offset = 0;
1717 u32 sg_count = 0;
1718 int sg_index = 0;
1719 u32 i = 0;
1720 u32 rcode = 0;
1721 void *p = NULL;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001722 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 ulong flags = 0;
1724
1725 memset(&msg, 0, MAX_MESSAGE_SIZE*4);
1726 // get user msg size in u32s
1727 if(get_user(size, &user_msg[0])){
1728 return -EFAULT;
1729 }
1730 size = size>>16;
1731
1732 user_reply = &user_msg[size];
1733 if(size > MAX_MESSAGE_SIZE){
1734 return -EFAULT;
1735 }
1736 size *= 4; // Convert to bytes
1737
1738 /* Copy in the user's I2O command */
1739 if(copy_from_user(msg, user_msg, size)) {
1740 return -EFAULT;
1741 }
1742 get_user(reply_size, &user_reply[0]);
1743 reply_size = reply_size>>16;
1744 if(reply_size > REPLY_FRAME_SIZE){
1745 reply_size = REPLY_FRAME_SIZE;
1746 }
1747 reply_size *= 4;
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301748 reply = kzalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 if(reply == NULL) {
1750 printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name);
1751 return -ENOMEM;
1752 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 sg_offset = (msg[0]>>4)&0xf;
1754 msg[2] = 0x40000000; // IOCTL context
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001755 msg[3] = adpt_ioctl_to_context(pHba, reply);
Quentin Lambert021e2922016-11-19 18:42:34 +01001756 if (msg[3] == (u32)-1) {
1757 kfree(reply);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001758 return -EBUSY;
Quentin Lambert021e2922016-11-19 18:42:34 +01001759 }
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001760
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 memset(sg_list,0, sizeof(sg_list[0])*pHba->sg_tablesize);
1762 if(sg_offset) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001763 // TODO add 64 bit API
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 struct sg_simple_element *sg = (struct sg_simple_element*) (msg+sg_offset);
1765 sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
1766 if (sg_count > pHba->sg_tablesize){
1767 printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", pHba->name,sg_count);
1768 kfree (reply);
1769 return -EINVAL;
1770 }
1771
1772 for(i = 0; i < sg_count; i++) {
1773 int sg_size;
1774
1775 if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) {
1776 printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",pHba->name,i, sg[i].flag_count);
1777 rcode = -EINVAL;
1778 goto cleanup;
1779 }
1780 sg_size = sg[i].flag_count & 0xffffff;
1781 /* Allocate memory for the transfer */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001782 p = dma_alloc_coherent(&pHba->pDev->dev, sg_size, &addr, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 if(!p) {
1784 printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
1785 pHba->name,sg_size,i,sg_count);
1786 rcode = -ENOMEM;
1787 goto cleanup;
1788 }
1789 sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
1790 /* Copy in the user's SG buffer if necessary */
1791 if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001792 // sg_simple_element API is 32 bit
1793 if (copy_from_user(p,(void __user *)(ulong)sg[i].addr_bus, sg_size)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",pHba->name,i);
1795 rcode = -EFAULT;
1796 goto cleanup;
1797 }
1798 }
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001799 /* sg_simple_element API is 32 bit, but addr < 4GB */
1800 sg[i].addr_bus = addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 }
1802 }
1803
1804 do {
Hannes Reinecke1f8c88c2013-10-23 10:51:15 +02001805 /*
1806 * Stop any new commands from enterring the
1807 * controller while processing the ioctl
1808 */
1809 if (pHba->host) {
1810 scsi_block_requests(pHba->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 spin_lock_irqsave(pHba->host->host_lock, flags);
Hannes Reinecke1f8c88c2013-10-23 10:51:15 +02001812 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER);
1814 if (rcode != 0)
1815 printk("adpt_i2o_passthru: post wait failed %d %p\n",
1816 rcode, reply);
Hannes Reinecke1f8c88c2013-10-23 10:51:15 +02001817 if (pHba->host) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 spin_unlock_irqrestore(pHba->host->host_lock, flags);
Hannes Reinecke1f8c88c2013-10-23 10:51:15 +02001819 scsi_unblock_requests(pHba->host);
1820 }
1821 } while (rcode == -ETIMEDOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822
1823 if(rcode){
1824 goto cleanup;
1825 }
1826
1827 if(sg_offset) {
1828 /* Copy back the Scatter Gather buffers back to user space */
1829 u32 j;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001830 // TODO add 64 bit API
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 struct sg_simple_element* sg;
1832 int sg_size;
1833
1834 // re-acquire the original message to handle correctly the sg copy operation
1835 memset(&msg, 0, MAX_MESSAGE_SIZE*4);
1836 // get user msg size in u32s
1837 if(get_user(size, &user_msg[0])){
1838 rcode = -EFAULT;
1839 goto cleanup;
1840 }
1841 size = size>>16;
1842 size *= 4;
Alan Coxef7562b2009-10-27 15:35:35 +00001843 if (size > MAX_MESSAGE_SIZE) {
OGAWA Hirofumiaefba412009-10-30 17:02:31 +09001844 rcode = -EINVAL;
Alan Coxef7562b2009-10-27 15:35:35 +00001845 goto cleanup;
1846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 /* Copy in the user's I2O command */
1848 if (copy_from_user (msg, user_msg, size)) {
1849 rcode = -EFAULT;
1850 goto cleanup;
1851 }
1852 sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
1853
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001854 // TODO add 64 bit API
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 sg = (struct sg_simple_element*)(msg + sg_offset);
1856 for (j = 0; j < sg_count; j++) {
1857 /* Copy out the SG list to user's buffer if necessary */
1858 if(! (sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) {
1859 sg_size = sg[j].flag_count & 0xffffff;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001860 // sg_simple_element API is 32 bit
1861 if (copy_to_user((void __user *)(ulong)sg[j].addr_bus,sg_list[j], sg_size)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",pHba->name, sg_list[j], sg[j].addr_bus);
1863 rcode = -EFAULT;
1864 goto cleanup;
1865 }
1866 }
1867 }
1868 }
1869
1870 /* Copy back the reply to user space */
1871 if (reply_size) {
1872 // we wrote our own values for context - now restore the user supplied ones
1873 if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) {
1874 printk(KERN_WARNING"%s: Could not copy message context FROM user\n",pHba->name);
1875 rcode = -EFAULT;
1876 }
1877 if(copy_to_user(user_reply, reply, reply_size)) {
1878 printk(KERN_WARNING"%s: Could not copy reply TO user\n",pHba->name);
1879 rcode = -EFAULT;
1880 }
1881 }
1882
1883
1884cleanup:
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001885 if (rcode != -ETIME && rcode != -EINTR) {
1886 struct sg_simple_element *sg =
1887 (struct sg_simple_element*) (msg +sg_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 kfree (reply);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001889 while(sg_index) {
1890 if(sg_list[--sg_index]) {
1891 dma_free_coherent(&pHba->pDev->dev,
1892 sg[sg_index].flag_count & 0xffffff,
1893 sg_list[sg_index],
1894 sg[sg_index].addr_bus);
1895 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 }
1897 }
1898 return rcode;
1899}
1900
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901#if defined __ia64__
1902static void adpt_ia64_info(sysInfo_S* si)
1903{
1904 // This is all the info we need for now
1905 // We will add more info as our new
1906 // managmenent utility requires it
1907 si->processorType = PROC_IA64;
1908}
1909#endif
1910
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911#if defined __sparc__
1912static void adpt_sparc_info(sysInfo_S* si)
1913{
1914 // This is all the info we need for now
1915 // We will add more info as our new
1916 // managmenent utility requires it
1917 si->processorType = PROC_ULTRASPARC;
1918}
1919#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920#if defined __alpha__
1921static void adpt_alpha_info(sysInfo_S* si)
1922{
1923 // This is all the info we need for now
1924 // We will add more info as our new
1925 // managmenent utility requires it
1926 si->processorType = PROC_ALPHA;
1927}
1928#endif
1929
1930#if defined __i386__
Brian Gerstba3e1272015-07-29 01:41:21 -04001931
1932#include <uapi/asm/vm86.h>
1933
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934static void adpt_i386_info(sysInfo_S* si)
1935{
1936 // This is all the info we need for now
1937 // We will add more info as our new
1938 // managmenent utility requires it
1939 switch (boot_cpu_data.x86) {
1940 case CPU_386:
1941 si->processorType = PROC_386;
1942 break;
1943 case CPU_486:
1944 si->processorType = PROC_486;
1945 break;
1946 case CPU_586:
1947 si->processorType = PROC_PENTIUM;
1948 break;
1949 default: // Just in case
1950 si->processorType = PROC_PENTIUM;
1951 break;
1952 }
1953}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954#endif
1955
Andrew Morton8b2cc912008-05-06 20:42:42 -07001956/*
1957 * This routine returns information about the system. This does not effect
1958 * any logic and if the info is wrong - it doesn't matter.
1959 */
1960
1961/* Get all the info we can not get from kernel services */
1962static int adpt_system_info(void __user *buffer)
1963{
1964 sysInfo_S si;
1965
1966 memset(&si, 0, sizeof(si));
1967
1968 si.osType = OS_LINUX;
1969 si.osMajorVersion = 0;
1970 si.osMinorVersion = 0;
1971 si.osRevision = 0;
1972 si.busType = SI_PCI_BUS;
1973 si.processorFamily = DPTI_sig.dsProcessorFamily;
1974
1975#if defined __i386__
1976 adpt_i386_info(&si);
1977#elif defined (__ia64__)
1978 adpt_ia64_info(&si);
1979#elif defined(__sparc__)
1980 adpt_sparc_info(&si);
1981#elif defined (__alpha__)
1982 adpt_alpha_info(&si);
1983#else
1984 si.processorType = 0xff ;
1985#endif
1986 if (copy_to_user(buffer, &si, sizeof(si))){
1987 printk(KERN_WARNING"dpti: Could not copy buffer TO user\n");
1988 return -EFAULT;
1989 }
1990
1991 return 0;
1992}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993
Arnd Bergmannf4927c42010-04-27 00:24:01 +02001994static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995{
1996 int minor;
1997 int error = 0;
1998 adpt_hba* pHba;
1999 ulong flags = 0;
2000 void __user *argp = (void __user *)arg;
2001
2002 minor = iminor(inode);
2003 if (minor >= DPTI_MAX_HBA){
2004 return -ENXIO;
2005 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01002006 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 for (pHba = hba_chain; pHba; pHba = pHba->next) {
2008 if (pHba->unit == minor) {
2009 break; /* found adapter */
2010 }
2011 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01002012 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 if(pHba == NULL){
2014 return -ENXIO;
2015 }
2016
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002017 while((volatile u32) pHba->state & DPTI_STATE_RESET )
2018 schedule_timeout_uninterruptible(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019
2020 switch (cmd) {
2021 // TODO: handle 3 cases
2022 case DPT_SIGNATURE:
2023 if (copy_to_user(argp, &DPTI_sig, sizeof(DPTI_sig))) {
2024 return -EFAULT;
2025 }
2026 break;
2027 case I2OUSRCMD:
2028 return adpt_i2o_passthru(pHba, argp);
2029
2030 case DPT_CTRLINFO:{
2031 drvrHBAinfo_S HbaInfo;
2032
2033#define FLG_OSD_PCI_VALID 0x0001
2034#define FLG_OSD_DMA 0x0002
2035#define FLG_OSD_I2O 0x0004
2036 memset(&HbaInfo, 0, sizeof(HbaInfo));
2037 HbaInfo.drvrHBAnum = pHba->unit;
2038 HbaInfo.baseAddr = (ulong) pHba->base_addr_phys;
2039 HbaInfo.blinkState = adpt_read_blink_led(pHba);
2040 HbaInfo.pciBusNum = pHba->pDev->bus->number;
2041 HbaInfo.pciDeviceNum=PCI_SLOT(pHba->pDev->devfn);
2042 HbaInfo.Interrupt = pHba->pDev->irq;
2043 HbaInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O;
2044 if(copy_to_user(argp, &HbaInfo, sizeof(HbaInfo))){
2045 printk(KERN_WARNING"%s: Could not copy HbaInfo TO user\n",pHba->name);
2046 return -EFAULT;
2047 }
2048 break;
2049 }
2050 case DPT_SYSINFO:
2051 return adpt_system_info(argp);
2052 case DPT_BLINKLED:{
2053 u32 value;
2054 value = (u32)adpt_read_blink_led(pHba);
2055 if (copy_to_user(argp, &value, sizeof(value))) {
2056 return -EFAULT;
2057 }
2058 break;
2059 }
2060 case I2ORESETCMD:
2061 if(pHba->host)
2062 spin_lock_irqsave(pHba->host->host_lock, flags);
2063 adpt_hba_reset(pHba);
2064 if(pHba->host)
2065 spin_unlock_irqrestore(pHba->host->host_lock, flags);
2066 break;
2067 case I2ORESCANCMD:
2068 adpt_rescan(pHba);
2069 break;
2070 default:
2071 return -EINVAL;
2072 }
2073
2074 return error;
2075}
2076
Arnd Bergmannf4927c42010-04-27 00:24:01 +02002077static long adpt_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
2078{
2079 struct inode *inode;
2080 long ret;
2081
Al Viro496ad9a2013-01-23 17:07:38 -05002082 inode = file_inode(file);
Arnd Bergmannf4927c42010-04-27 00:24:01 +02002083
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02002084 mutex_lock(&adpt_mutex);
Arnd Bergmannf4927c42010-04-27 00:24:01 +02002085 ret = adpt_ioctl(inode, file, cmd, arg);
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02002086 mutex_unlock(&adpt_mutex);
Arnd Bergmannf4927c42010-04-27 00:24:01 +02002087
2088 return ret;
2089}
2090
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002091#ifdef CONFIG_COMPAT
2092static long compat_adpt_ioctl(struct file *file,
2093 unsigned int cmd, unsigned long arg)
2094{
2095 struct inode *inode;
2096 long ret;
2097
Al Viro496ad9a2013-01-23 17:07:38 -05002098 inode = file_inode(file);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002099
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02002100 mutex_lock(&adpt_mutex);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002101
2102 switch(cmd) {
2103 case DPT_SIGNATURE:
2104 case I2OUSRCMD:
2105 case DPT_CTRLINFO:
2106 case DPT_SYSINFO:
2107 case DPT_BLINKLED:
2108 case I2ORESETCMD:
2109 case I2ORESCANCMD:
2110 case (DPT_TARGET_BUSY & 0xFFFF):
2111 case DPT_TARGET_BUSY:
2112 ret = adpt_ioctl(inode, file, cmd, arg);
2113 break;
2114 default:
2115 ret = -ENOIOCTLCMD;
2116 }
2117
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02002118 mutex_unlock(&adpt_mutex);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002119
2120 return ret;
2121}
2122#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123
David Howells7d12e782006-10-05 14:55:46 +01002124static irqreturn_t adpt_isr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125{
2126 struct scsi_cmnd* cmd;
2127 adpt_hba* pHba = dev_id;
2128 u32 m;
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002129 void __iomem *reply;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 u32 status=0;
2131 u32 context;
2132 ulong flags = 0;
2133 int handled = 0;
2134
2135 if (pHba == NULL){
2136 printk(KERN_WARNING"adpt_isr: NULL dev_id\n");
2137 return IRQ_NONE;
2138 }
2139 if(pHba->host)
2140 spin_lock_irqsave(pHba->host->host_lock, flags);
2141
2142 while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) {
2143 m = readl(pHba->reply_port);
2144 if(m == EMPTY_QUEUE){
2145 // Try twice then give up
2146 rmb();
2147 m = readl(pHba->reply_port);
2148 if(m == EMPTY_QUEUE){
2149 // This really should not happen
2150 printk(KERN_ERR"dpti: Could not get reply frame\n");
2151 goto out;
2152 }
2153 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002154 if (pHba->reply_pool_pa <= m &&
2155 m < pHba->reply_pool_pa +
2156 (pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4)) {
2157 reply = (u8 *)pHba->reply_pool +
2158 (m - pHba->reply_pool_pa);
2159 } else {
2160 /* Ick, we should *never* be here */
2161 printk(KERN_ERR "dpti: reply frame not from pool\n");
2162 reply = (u8 *)bus_to_virt(m);
2163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164
2165 if (readl(reply) & MSG_FAIL) {
2166 u32 old_m = readl(reply+28);
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002167 void __iomem *msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 u32 old_context;
2169 PDEBUG("%s: Failed message\n",pHba->name);
2170 if(old_m >= 0x100000){
2171 printk(KERN_ERR"%s: Bad preserved MFA (%x)- dropping frame\n",pHba->name,old_m);
2172 writel(m,pHba->reply_port);
2173 continue;
2174 }
2175 // Transaction context is 0 in failed reply frame
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002176 msg = pHba->msg_addr_virt + old_m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 old_context = readl(msg+12);
2178 writel(old_context, reply+12);
2179 adpt_send_nop(pHba, old_m);
2180 }
2181 context = readl(reply+8);
2182 if(context & 0x40000000){ // IOCTL
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002183 void *p = adpt_ioctl_from_context(pHba, readl(reply+12));
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002184 if( p != NULL) {
2185 memcpy_fromio(p, reply, REPLY_FRAME_SIZE * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 }
2187 // All IOCTLs will also be post wait
2188 }
2189 if(context & 0x80000000){ // Post wait message
2190 status = readl(reply+16);
2191 if(status >> 24){
2192 status &= 0xffff; /* Get detail status */
2193 } else {
2194 status = I2O_POST_WAIT_OK;
2195 }
2196 if(!(context & 0x40000000)) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002197 cmd = adpt_cmd_from_context(pHba,
2198 readl(reply+12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 if(cmd != NULL) {
2200 printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context);
2201 }
2202 }
2203 adpt_i2o_post_wait_complete(context, status);
2204 } else { // SCSI message
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002205 cmd = adpt_cmd_from_context (pHba, readl(reply+12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 if(cmd != NULL){
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002207 scsi_dma_unmap(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 if(cmd->serial_number != 0) { // If not timedout
2209 adpt_i2o_to_scsi(reply, cmd);
2210 }
2211 }
2212 }
2213 writel(m, pHba->reply_port);
2214 wmb();
2215 rmb();
2216 }
2217 handled = 1;
2218out: if(pHba->host)
2219 spin_unlock_irqrestore(pHba->host->host_lock, flags);
2220 return IRQ_RETVAL(handled);
2221}
2222
2223static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* d)
2224{
2225 int i;
2226 u32 msg[MAX_MESSAGE_SIZE];
2227 u32* mptr;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002228 u32* lptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 u32 *lenptr;
2230 int direction;
2231 int scsidir;
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002232 int nseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 u32 len;
2234 u32 reqlen;
2235 s32 rcode;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002236 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237
2238 memset(msg, 0 , sizeof(msg));
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002239 len = scsi_bufflen(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 direction = 0x00000000;
2241
2242 scsidir = 0x00000000; // DATA NO XFER
2243 if(len) {
2244 /*
2245 * Set SCBFlags to indicate if data is being transferred
2246 * in or out, or no data transfer
2247 * Note: Do not have to verify index is less than 0 since
2248 * cmd->cmnd[0] is an unsigned char
2249 */
2250 switch(cmd->sc_data_direction){
2251 case DMA_FROM_DEVICE:
2252 scsidir =0x40000000; // DATA IN (iop<--dev)
2253 break;
2254 case DMA_TO_DEVICE:
2255 direction=0x04000000; // SGL OUT
2256 scsidir =0x80000000; // DATA OUT (iop-->dev)
2257 break;
2258 case DMA_NONE:
2259 break;
2260 case DMA_BIDIRECTIONAL:
2261 scsidir =0x40000000; // DATA IN (iop<--dev)
2262 // Assume In - and continue;
2263 break;
2264 default:
2265 printk(KERN_WARNING"%s: scsi opcode 0x%x not supported.\n",
2266 pHba->name, cmd->cmnd[0]);
2267 cmd->result = (DID_OK <<16) | (INITIATOR_ERROR << 8);
2268 cmd->scsi_done(cmd);
2269 return 0;
2270 }
2271 }
2272 // msg[0] is set later
2273 // I2O_CMD_SCSI_EXEC
2274 msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid);
2275 msg[2] = 0;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002276 msg[3] = adpt_cmd_to_context(cmd); /* Want SCSI control block back */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 // Our cards use the transaction context as the tag for queueing
2278 // Adaptec/DPT Private stuff
2279 msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16);
2280 msg[5] = d->tid;
2281 /* Direction, disconnect ok | sense data | simple queue , CDBLen */
2282 // I2O_SCB_FLAG_ENABLE_DISCONNECT |
2283 // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG |
2284 // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;
2285 msg[6] = scsidir|0x20a00000|cmd->cmd_len;
2286
2287 mptr=msg+7;
2288
2289 // Write SCSI command into the message - always 16 byte block
2290 memset(mptr, 0, 16);
2291 memcpy(mptr, cmd->cmnd, cmd->cmd_len);
2292 mptr+=4;
2293 lenptr=mptr++; /* Remember me - fill in when we know */
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002294 if (dpt_dma64(pHba)) {
2295 reqlen = 16; // SINGLE SGE
2296 *mptr++ = (0x7C<<24)+(2<<16)+0x02; /* Enable 64 bit */
2297 *mptr++ = 1 << PAGE_SHIFT;
2298 } else {
2299 reqlen = 14; // SINGLE SGE
2300 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 /* Now fill in the SGList and command */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002303 nseg = scsi_dma_map(cmd);
2304 BUG_ON(nseg < 0);
2305 if (nseg) {
2306 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307
2308 len = 0;
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002309 scsi_for_each_sg(cmd, sg, nseg, i) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002310 lptr = mptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 *mptr++ = direction|0x10000000|sg_dma_len(sg);
2312 len+=sg_dma_len(sg);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002313 addr = sg_dma_address(sg);
2314 *mptr++ = dma_low(addr);
2315 if (dpt_dma64(pHba))
2316 *mptr++ = dma_high(addr);
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002317 /* Make this an end of list */
2318 if (i == nseg - 1)
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002319 *lptr = direction|0xD0000000|sg_dma_len(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 reqlen = mptr - msg;
2322 *lenptr = len;
2323
2324 if(cmd->underflow && len != cmd->underflow){
2325 printk(KERN_WARNING"Cmd len %08X Cmd underflow %08X\n",
2326 len, cmd->underflow);
2327 }
2328 } else {
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002329 *lenptr = len = 0;
2330 reqlen = 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 }
2332
2333 /* Stick the headers on */
2334 msg[0] = reqlen<<16 | ((reqlen > 12) ? SGL_OFFSET_12 : SGL_OFFSET_0);
2335
2336 // Send it on it's way
2337 rcode = adpt_i2o_post_this(pHba, msg, reqlen<<2);
2338 if (rcode == 0) {
2339 return 0;
2340 }
2341 return rcode;
2342}
2343
2344
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002345static s32 adpt_scsi_host_alloc(adpt_hba* pHba, struct scsi_host_template *sht)
Andrew Morton24601bb2007-12-10 15:49:20 -08002346{
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002347 struct Scsi_Host *host;
Andrew Morton24601bb2007-12-10 15:49:20 -08002348
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002349 host = scsi_host_alloc(sht, sizeof(adpt_hba*));
Andrew Morton24601bb2007-12-10 15:49:20 -08002350 if (host == NULL) {
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002351 printk("%s: scsi_host_alloc returned NULL\n", pHba->name);
Andrew Morton24601bb2007-12-10 15:49:20 -08002352 return -1;
2353 }
2354 host->hostdata[0] = (unsigned long)pHba;
2355 pHba->host = host;
2356
2357 host->irq = pHba->pDev->irq;
2358 /* no IO ports, so don't have to set host->io_port and
2359 * host->n_io_port
2360 */
2361 host->io_port = 0;
2362 host->n_io_port = 0;
2363 /* see comments in scsi_host.h */
2364 host->max_id = 16;
2365 host->max_lun = 256;
2366 host->max_channel = pHba->top_scsi_channel + 1;
2367 host->cmd_per_lun = 1;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002368 host->unique_id = (u32)sys_tbl_pa + pHba->unit;
Andrew Morton24601bb2007-12-10 15:49:20 -08002369 host->sg_tablesize = pHba->sg_tablesize;
2370 host->can_queue = pHba->post_fifo_size;
Kashyap.Desai@avagotech.com64bdcbc2014-08-20 19:24:33 +05302371 host->use_cmd_list = 1;
Andrew Morton24601bb2007-12-10 15:49:20 -08002372
2373 return 0;
2374}
2375
2376
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002377static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378{
2379 adpt_hba* pHba;
2380 u32 hba_status;
2381 u32 dev_status;
2382 u32 reply_flags = readl(reply) & 0xff00; // Leave it shifted up 8 bits
2383 // I know this would look cleaner if I just read bytes
2384 // but the model I have been using for all the rest of the
2385 // io is in 4 byte words - so I keep that model
2386 u16 detailed_status = readl(reply+16) &0xffff;
2387 dev_status = (detailed_status & 0xff);
2388 hba_status = detailed_status >> 8;
2389
2390 // calculate resid for sg
Miquel van Smoorenburgdf81d232008-11-05 00:09:12 +01002391 scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+20));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392
2393 pHba = (adpt_hba*) cmd->device->host->hostdata[0];
2394
2395 cmd->sense_buffer[0] = '\0'; // initialize sense valid flag to false
2396
2397 if(!(reply_flags & MSG_FAIL)) {
2398 switch(detailed_status & I2O_SCSI_DSC_MASK) {
2399 case I2O_SCSI_DSC_SUCCESS:
2400 cmd->result = (DID_OK << 16);
2401 // handle underflow
Miquel van Smoorenburgdf81d232008-11-05 00:09:12 +01002402 if (readl(reply+20) < cmd->underflow) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 cmd->result = (DID_ERROR <<16);
2404 printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name);
2405 }
2406 break;
2407 case I2O_SCSI_DSC_REQUEST_ABORTED:
2408 cmd->result = (DID_ABORT << 16);
2409 break;
2410 case I2O_SCSI_DSC_PATH_INVALID:
2411 case I2O_SCSI_DSC_DEVICE_NOT_PRESENT:
2412 case I2O_SCSI_DSC_SELECTION_TIMEOUT:
2413 case I2O_SCSI_DSC_COMMAND_TIMEOUT:
2414 case I2O_SCSI_DSC_NO_ADAPTER:
2415 case I2O_SCSI_DSC_RESOURCE_UNAVAILABLE:
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002416 printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%llu) hba status=0x%x, dev status=0x%x, cmd=0x%x\n",
2417 pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 cmd->result = (DID_TIME_OUT << 16);
2419 break;
2420 case I2O_SCSI_DSC_ADAPTER_BUSY:
2421 case I2O_SCSI_DSC_BUS_BUSY:
2422 cmd->result = (DID_BUS_BUSY << 16);
2423 break;
2424 case I2O_SCSI_DSC_SCSI_BUS_RESET:
2425 case I2O_SCSI_DSC_BDR_MESSAGE_SENT:
2426 cmd->result = (DID_RESET << 16);
2427 break;
2428 case I2O_SCSI_DSC_PARITY_ERROR_FAILURE:
2429 printk(KERN_WARNING"%s: SCSI CMD parity error\n",pHba->name);
2430 cmd->result = (DID_PARITY << 16);
2431 break;
2432 case I2O_SCSI_DSC_UNABLE_TO_ABORT:
2433 case I2O_SCSI_DSC_COMPLETE_WITH_ERROR:
2434 case I2O_SCSI_DSC_UNABLE_TO_TERMINATE:
2435 case I2O_SCSI_DSC_MR_MESSAGE_RECEIVED:
2436 case I2O_SCSI_DSC_AUTOSENSE_FAILED:
2437 case I2O_SCSI_DSC_DATA_OVERRUN:
2438 case I2O_SCSI_DSC_UNEXPECTED_BUS_FREE:
2439 case I2O_SCSI_DSC_SEQUENCE_FAILURE:
2440 case I2O_SCSI_DSC_REQUEST_LENGTH_ERROR:
2441 case I2O_SCSI_DSC_PROVIDE_FAILURE:
2442 case I2O_SCSI_DSC_REQUEST_TERMINATED:
2443 case I2O_SCSI_DSC_IDE_MESSAGE_SENT:
2444 case I2O_SCSI_DSC_UNACKNOWLEDGED_EVENT:
2445 case I2O_SCSI_DSC_MESSAGE_RECEIVED:
2446 case I2O_SCSI_DSC_INVALID_CDB:
2447 case I2O_SCSI_DSC_LUN_INVALID:
2448 case I2O_SCSI_DSC_SCSI_TID_INVALID:
2449 case I2O_SCSI_DSC_FUNCTION_UNAVAILABLE:
2450 case I2O_SCSI_DSC_NO_NEXUS:
2451 case I2O_SCSI_DSC_CDB_RECEIVED:
2452 case I2O_SCSI_DSC_LUN_ALREADY_ENABLED:
2453 case I2O_SCSI_DSC_QUEUE_FROZEN:
2454 case I2O_SCSI_DSC_REQUEST_INVALID:
2455 default:
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002456 printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
2457 pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 hba_status, dev_status, cmd->cmnd[0]);
2459 cmd->result = (DID_ERROR << 16);
2460 break;
2461 }
2462
2463 // copy over the request sense data if it was a check
2464 // condition status
Salyzyn, Markd814c512008-01-14 11:04:40 -08002465 if (dev_status == SAM_STAT_CHECK_CONDITION) {
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +09002466 u32 len = min(SCSI_SENSE_BUFFERSIZE, 40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 // Copy over the sense data
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002468 memcpy_fromio(cmd->sense_buffer, (reply+28) , len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 if(cmd->sense_buffer[0] == 0x70 /* class 7 */ &&
2470 cmd->sense_buffer[2] == DATA_PROTECT ){
2471 /* This is to handle an array failed */
2472 cmd->result = (DID_TIME_OUT << 16);
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002473 printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
2474 pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 hba_status, dev_status, cmd->cmnd[0]);
2476
2477 }
2478 }
2479 } else {
2480 /* In this condtion we could not talk to the tid
2481 * the card rejected it. We should signal a retry
2482 * for a limitted number of retries.
2483 */
2484 cmd->result = (DID_TIME_OUT << 16);
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002485 printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%llu) tid=%d, cmd=0x%x\n",
2486 pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 ((struct adpt_device*)(cmd->device->hostdata))->tid, cmd->cmnd[0]);
2488 }
2489
2490 cmd->result |= (dev_status);
2491
2492 if(cmd->scsi_done != NULL){
2493 cmd->scsi_done(cmd);
2494 }
2495 return cmd->result;
2496}
2497
2498
2499static s32 adpt_rescan(adpt_hba* pHba)
2500{
2501 s32 rcode;
2502 ulong flags = 0;
2503
2504 if(pHba->host)
2505 spin_lock_irqsave(pHba->host->host_lock, flags);
2506 if ((rcode=adpt_i2o_lct_get(pHba)) < 0)
2507 goto out;
2508 if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0)
2509 goto out;
2510 rcode = 0;
2511out: if(pHba->host)
2512 spin_unlock_irqrestore(pHba->host->host_lock, flags);
2513 return rcode;
2514}
2515
2516
2517static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
2518{
2519 int i;
2520 int max;
2521 int tid;
2522 struct i2o_device *d;
2523 i2o_lct *lct = pHba->lct;
2524 u8 bus_no = 0;
2525 s16 scsi_id;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002526 u64 scsi_lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 u32 buf[10]; // at least 8 u32's
2528 struct adpt_device* pDev = NULL;
2529 struct i2o_device* pI2o_dev = NULL;
2530
2531 if (lct == NULL) {
2532 printk(KERN_ERR "%s: LCT is empty???\n",pHba->name);
2533 return -1;
2534 }
2535
2536 max = lct->table_size;
2537 max -= 3;
2538 max /= 9;
2539
2540 // Mark each drive as unscanned
2541 for (d = pHba->devices; d; d = d->next) {
2542 pDev =(struct adpt_device*) d->owner;
2543 if(!pDev){
2544 continue;
2545 }
2546 pDev->state |= DPTI_DEV_UNSCANNED;
2547 }
2548
2549 printk(KERN_INFO "%s: LCT has %d entries.\n", pHba->name,max);
2550
2551 for(i=0;i<max;i++) {
2552 if( lct->lct_entry[i].user_tid != 0xfff){
2553 continue;
2554 }
2555
2556 if( lct->lct_entry[i].class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE ||
2557 lct->lct_entry[i].class_id == I2O_CLASS_SCSI_PERIPHERAL ||
2558 lct->lct_entry[i].class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
2559 tid = lct->lct_entry[i].tid;
2560 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) {
2561 printk(KERN_ERR"%s: Could not query device\n",pHba->name);
2562 continue;
2563 }
2564 bus_no = buf[0]>>16;
Dan Carpentere84d96d2010-07-15 10:20:19 +02002565 if (bus_no >= MAX_CHANNEL) { /* Something wrong skip it */
2566 printk(KERN_WARNING
2567 "%s: Channel number %d out of range\n",
2568 pHba->name, bus_no);
2569 continue;
2570 }
2571
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 scsi_id = buf[1];
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002573 scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 pDev = pHba->channel[bus_no].device[scsi_id];
2575 /* da lun */
2576 while(pDev) {
2577 if(pDev->scsi_lun == scsi_lun) {
2578 break;
2579 }
2580 pDev = pDev->next_lun;
2581 }
2582 if(!pDev ) { // Something new add it
Julia Lawallda2907f2010-05-30 15:49:22 +02002583 d = kmalloc(sizeof(struct i2o_device),
2584 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 if(d==NULL)
2586 {
2587 printk(KERN_CRIT "Out of memory for I2O device data.\n");
2588 return -ENOMEM;
2589 }
2590
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002591 d->controller = pHba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 d->next = NULL;
2593
2594 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
2595
2596 d->flags = 0;
2597 adpt_i2o_report_hba_unit(pHba, d);
2598 adpt_i2o_install_device(pHba, d);
2599
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 pDev = pHba->channel[bus_no].device[scsi_id];
2601 if( pDev == NULL){
Julia Lawallda2907f2010-05-30 15:49:22 +02002602 pDev =
2603 kzalloc(sizeof(struct adpt_device),
2604 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 if(pDev == NULL) {
2606 return -ENOMEM;
2607 }
2608 pHba->channel[bus_no].device[scsi_id] = pDev;
2609 } else {
2610 while (pDev->next_lun) {
2611 pDev = pDev->next_lun;
2612 }
Julia Lawallda2907f2010-05-30 15:49:22 +02002613 pDev = pDev->next_lun =
2614 kzalloc(sizeof(struct adpt_device),
2615 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 if(pDev == NULL) {
2617 return -ENOMEM;
2618 }
2619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 pDev->tid = d->lct_data.tid;
2621 pDev->scsi_channel = bus_no;
2622 pDev->scsi_id = scsi_id;
2623 pDev->scsi_lun = scsi_lun;
2624 pDev->pI2o_dev = d;
2625 d->owner = pDev;
2626 pDev->type = (buf[0])&0xff;
2627 pDev->flags = (buf[0]>>8)&0xff;
2628 // Too late, SCSI system has made up it's mind, but what the hey ...
2629 if(scsi_id > pHba->top_scsi_id){
2630 pHba->top_scsi_id = scsi_id;
2631 }
2632 if(scsi_lun > pHba->top_scsi_lun){
2633 pHba->top_scsi_lun = scsi_lun;
2634 }
2635 continue;
2636 } // end of new i2o device
2637
2638 // We found an old device - check it
2639 while(pDev) {
2640 if(pDev->scsi_lun == scsi_lun) {
2641 if(!scsi_device_online(pDev->pScsi_dev)) {
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002642 printk(KERN_WARNING"%s: Setting device (%d,%d,%llu) back online\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 pHba->name,bus_no,scsi_id,scsi_lun);
2644 if (pDev->pScsi_dev) {
2645 scsi_device_set_state(pDev->pScsi_dev, SDEV_RUNNING);
2646 }
2647 }
2648 d = pDev->pI2o_dev;
2649 if(d->lct_data.tid != tid) { // something changed
2650 pDev->tid = tid;
2651 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
2652 if (pDev->pScsi_dev) {
2653 pDev->pScsi_dev->changed = TRUE;
2654 pDev->pScsi_dev->removable = TRUE;
2655 }
2656 }
2657 // Found it - mark it scanned
2658 pDev->state = DPTI_DEV_ONLINE;
2659 break;
2660 }
2661 pDev = pDev->next_lun;
2662 }
2663 }
2664 }
2665 for (pI2o_dev = pHba->devices; pI2o_dev; pI2o_dev = pI2o_dev->next) {
2666 pDev =(struct adpt_device*) pI2o_dev->owner;
2667 if(!pDev){
2668 continue;
2669 }
2670 // Drive offline drives that previously existed but could not be found
2671 // in the LCT table
2672 if (pDev->state & DPTI_DEV_UNSCANNED){
2673 pDev->state = DPTI_DEV_OFFLINE;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002674 printk(KERN_WARNING"%s: Device (%d,%d,%llu) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 if (pDev->pScsi_dev) {
2676 scsi_device_set_state(pDev->pScsi_dev, SDEV_OFFLINE);
2677 }
2678 }
2679 }
2680 return 0;
2681}
2682
2683static void adpt_fail_posted_scbs(adpt_hba* pHba)
2684{
2685 struct scsi_cmnd* cmd = NULL;
2686 struct scsi_device* d = NULL;
2687
2688 shost_for_each_device(d, pHba->host) {
2689 unsigned long flags;
2690 spin_lock_irqsave(&d->list_lock, flags);
2691 list_for_each_entry(cmd, &d->cmd_list, list) {
2692 if(cmd->serial_number == 0){
2693 continue;
2694 }
2695 cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1);
2696 cmd->scsi_done(cmd);
2697 }
2698 spin_unlock_irqrestore(&d->list_lock, flags);
2699 }
2700}
2701
2702
2703/*============================================================================
2704 * Routines from i2o subsystem
2705 *============================================================================
2706 */
2707
2708
2709
2710/*
2711 * Bring an I2O controller into HOLD state. See the spec.
2712 */
2713static int adpt_i2o_activate_hba(adpt_hba* pHba)
2714{
2715 int rcode;
2716
2717 if(pHba->initialized ) {
2718 if (adpt_i2o_status_get(pHba) < 0) {
2719 if((rcode = adpt_i2o_reset_hba(pHba)) != 0){
2720 printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name);
2721 return rcode;
2722 }
2723 if (adpt_i2o_status_get(pHba) < 0) {
2724 printk(KERN_INFO "HBA not responding.\n");
2725 return -1;
2726 }
2727 }
2728
2729 if(pHba->status_block->iop_state == ADAPTER_STATE_FAULTED) {
2730 printk(KERN_CRIT "%s: hardware fault\n", pHba->name);
2731 return -1;
2732 }
2733
2734 if (pHba->status_block->iop_state == ADAPTER_STATE_READY ||
2735 pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
2736 pHba->status_block->iop_state == ADAPTER_STATE_HOLD ||
2737 pHba->status_block->iop_state == ADAPTER_STATE_FAILED) {
2738 adpt_i2o_reset_hba(pHba);
2739 if (adpt_i2o_status_get(pHba) < 0 || pHba->status_block->iop_state != ADAPTER_STATE_RESET) {
2740 printk(KERN_ERR "%s: Failed to initialize.\n", pHba->name);
2741 return -1;
2742 }
2743 }
2744 } else {
2745 if((rcode = adpt_i2o_reset_hba(pHba)) != 0){
2746 printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name);
2747 return rcode;
2748 }
2749
2750 }
2751
2752 if (adpt_i2o_init_outbound_q(pHba) < 0) {
2753 return -1;
2754 }
2755
2756 /* In HOLD state */
2757
2758 if (adpt_i2o_hrt_get(pHba) < 0) {
2759 return -1;
2760 }
2761
2762 return 0;
2763}
2764
2765/*
2766 * Bring a controller online into OPERATIONAL state.
2767 */
2768
2769static int adpt_i2o_online_hba(adpt_hba* pHba)
2770{
Dan Carpenter19099dc2016-12-16 12:35:39 +03002771 if (adpt_i2o_systab_send(pHba) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 /* In READY state */
2774
Dan Carpenter19099dc2016-12-16 12:35:39 +03002775 if (adpt_i2o_enable_hba(pHba) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777
2778 /* In OPERATIONAL state */
2779 return 0;
2780}
2781
2782static s32 adpt_send_nop(adpt_hba*pHba,u32 m)
2783{
2784 u32 __iomem *msg;
2785 ulong timeout = jiffies + 5*HZ;
2786
2787 while(m == EMPTY_QUEUE){
2788 rmb();
2789 m = readl(pHba->post_port);
2790 if(m != EMPTY_QUEUE){
2791 break;
2792 }
2793 if(time_after(jiffies,timeout)){
2794 printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name);
2795 return 2;
2796 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002797 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 }
2799 msg = (u32 __iomem *)(pHba->msg_addr_virt + m);
2800 writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]);
2801 writel( I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0,&msg[1]);
2802 writel( 0,&msg[2]);
2803 wmb();
2804
2805 writel(m, pHba->post_port);
2806 wmb();
2807 return 0;
2808}
2809
2810static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba)
2811{
2812 u8 *status;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002813 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 u32 __iomem *msg = NULL;
2815 int i;
2816 ulong timeout = jiffies + TMOUT_INITOUTBOUND*HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 u32 m;
2818
2819 do {
2820 rmb();
2821 m = readl(pHba->post_port);
2822 if (m != EMPTY_QUEUE) {
2823 break;
2824 }
2825
2826 if(time_after(jiffies,timeout)){
2827 printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name);
2828 return -ETIMEDOUT;
2829 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002830 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831 } while(m == EMPTY_QUEUE);
2832
2833 msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
2834
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002835 status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002836 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 adpt_send_nop(pHba, m);
2838 printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n",
2839 pHba->name);
2840 return -ENOMEM;
2841 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002842 memset(status, 0, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843
2844 writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]);
2845 writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]);
2846 writel(0, &msg[2]);
2847 writel(0x0106, &msg[3]); /* Transaction context */
2848 writel(4096, &msg[4]); /* Host page frame size */
2849 writel((REPLY_FRAME_SIZE)<<16|0x80, &msg[5]); /* Outbound msg frame size and Initcode */
2850 writel(0xD0000004, &msg[6]); /* Simple SG LE, EOB */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002851 writel((u32)addr, &msg[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852
2853 writel(m, pHba->post_port);
2854 wmb();
2855
2856 // Wait for the reply status to come back
2857 do {
2858 if (*status) {
2859 if (*status != 0x01 /*I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS*/) {
2860 break;
2861 }
2862 }
2863 rmb();
2864 if(time_after(jiffies,timeout)){
2865 printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002866 /* We lose 4 bytes of "status" here, but we
2867 cannot free these because controller may
2868 awake and corrupt those bytes at any time */
2869 /* dma_free_coherent(&pHba->pDev->dev, 4, status, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 return -ETIMEDOUT;
2871 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002872 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873 } while (1);
2874
2875 // If the command was successful, fill the fifo with our reply
2876 // message packets
2877 if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002878 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 return -2;
2880 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002881 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002883 if(pHba->reply_pool != NULL) {
2884 dma_free_coherent(&pHba->pDev->dev,
2885 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
2886 pHba->reply_pool, pHba->reply_pool_pa);
2887 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002889 pHba->reply_pool = dma_alloc_coherent(&pHba->pDev->dev,
2890 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
2891 &pHba->reply_pool_pa, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002892 if (!pHba->reply_pool) {
2893 printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name);
2894 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002896 memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 for(i = 0; i < pHba->reply_fifo_size; i++) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002899 writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4),
2900 pHba->reply_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 }
2903 adpt_i2o_status_get(pHba);
2904 return 0;
2905}
2906
2907
2908/*
2909 * I2O System Table. Contains information about
2910 * all the IOPs in the system. Used to inform IOPs
2911 * about each other's existence.
2912 *
2913 * sys_tbl_ver is the CurrentChangeIndicator that is
2914 * used by IOPs to track changes.
2915 */
2916
2917
2918
2919static s32 adpt_i2o_status_get(adpt_hba* pHba)
2920{
2921 ulong timeout;
2922 u32 m;
2923 u32 __iomem *msg;
2924 u8 *status_block=NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925
2926 if(pHba->status_block == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002927 pHba->status_block = dma_alloc_coherent(&pHba->pDev->dev,
2928 sizeof(i2o_status_block),
2929 &pHba->status_block_pa, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930 if(pHba->status_block == NULL) {
2931 printk(KERN_ERR
2932 "dpti%d: Get Status Block failed; Out of memory. \n",
2933 pHba->unit);
2934 return -ENOMEM;
2935 }
2936 }
2937 memset(pHba->status_block, 0, sizeof(i2o_status_block));
2938 status_block = (u8*)(pHba->status_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939 timeout = jiffies+TMOUT_GETSTATUS*HZ;
2940 do {
2941 rmb();
2942 m = readl(pHba->post_port);
2943 if (m != EMPTY_QUEUE) {
2944 break;
2945 }
2946 if(time_after(jiffies,timeout)){
2947 printk(KERN_ERR "%s: Timeout waiting for message !\n",
2948 pHba->name);
2949 return -ETIMEDOUT;
2950 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002951 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952 } while(m==EMPTY_QUEUE);
2953
2954
2955 msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
2956
2957 writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]);
2958 writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]);
2959 writel(1, &msg[2]);
2960 writel(0, &msg[3]);
2961 writel(0, &msg[4]);
2962 writel(0, &msg[5]);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002963 writel( dma_low(pHba->status_block_pa), &msg[6]);
2964 writel( dma_high(pHba->status_block_pa), &msg[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965 writel(sizeof(i2o_status_block), &msg[8]); // 88 bytes
2966
2967 //post message
2968 writel(m, pHba->post_port);
2969 wmb();
2970
2971 while(status_block[87]!=0xff){
2972 if(time_after(jiffies,timeout)){
2973 printk(KERN_ERR"dpti%d: Get status timeout.\n",
2974 pHba->unit);
2975 return -ETIMEDOUT;
2976 }
2977 rmb();
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002978 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 }
2980
2981 // Set up our number of outbound and inbound messages
2982 pHba->post_fifo_size = pHba->status_block->max_inbound_frames;
2983 if (pHba->post_fifo_size > MAX_TO_IOP_MESSAGES) {
2984 pHba->post_fifo_size = MAX_TO_IOP_MESSAGES;
2985 }
2986
2987 pHba->reply_fifo_size = pHba->status_block->max_outbound_frames;
2988 if (pHba->reply_fifo_size > MAX_FROM_IOP_MESSAGES) {
2989 pHba->reply_fifo_size = MAX_FROM_IOP_MESSAGES;
2990 }
2991
2992 // Calculate the Scatter Gather list size
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002993 if (dpt_dma64(pHba)) {
2994 pHba->sg_tablesize
2995 = ((pHba->status_block->inbound_frame_size * 4
2996 - 14 * sizeof(u32))
2997 / (sizeof(struct sg_simple_element) + sizeof(u32)));
2998 } else {
2999 pHba->sg_tablesize
3000 = ((pHba->status_block->inbound_frame_size * 4
3001 - 12 * sizeof(u32))
3002 / sizeof(struct sg_simple_element));
3003 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 if (pHba->sg_tablesize > SG_LIST_ELEMENTS) {
3005 pHba->sg_tablesize = SG_LIST_ELEMENTS;
3006 }
3007
3008
3009#ifdef DEBUG
3010 printk("dpti%d: State = ",pHba->unit);
3011 switch(pHba->status_block->iop_state) {
3012 case 0x01:
3013 printk("INIT\n");
3014 break;
3015 case 0x02:
3016 printk("RESET\n");
3017 break;
3018 case 0x04:
3019 printk("HOLD\n");
3020 break;
3021 case 0x05:
3022 printk("READY\n");
3023 break;
3024 case 0x08:
3025 printk("OPERATIONAL\n");
3026 break;
3027 case 0x10:
3028 printk("FAILED\n");
3029 break;
3030 case 0x11:
3031 printk("FAULTED\n");
3032 break;
3033 default:
3034 printk("%x (unknown!!)\n",pHba->status_block->iop_state);
3035 }
3036#endif
3037 return 0;
3038}
3039
3040/*
3041 * Get the IOP's Logical Configuration Table
3042 */
3043static int adpt_i2o_lct_get(adpt_hba* pHba)
3044{
3045 u32 msg[8];
3046 int ret;
3047 u32 buf[16];
3048
3049 if ((pHba->lct_size == 0) || (pHba->lct == NULL)){
3050 pHba->lct_size = pHba->status_block->expected_lct_size;
3051 }
3052 do {
3053 if (pHba->lct == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003054 pHba->lct = dma_alloc_coherent(&pHba->pDev->dev,
3055 pHba->lct_size, &pHba->lct_pa,
Julia Lawallda2907f2010-05-30 15:49:22 +02003056 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 if(pHba->lct == NULL) {
3058 printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n",
3059 pHba->name);
3060 return -ENOMEM;
3061 }
3062 }
3063 memset(pHba->lct, 0, pHba->lct_size);
3064
3065 msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
3066 msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
3067 msg[2] = 0;
3068 msg[3] = 0;
3069 msg[4] = 0xFFFFFFFF; /* All devices */
3070 msg[5] = 0x00000000; /* Report now */
3071 msg[6] = 0xD0000000|pHba->lct_size;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003072 msg[7] = (u32)pHba->lct_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073
3074 if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 360))) {
3075 printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n",
3076 pHba->name, ret);
3077 printk(KERN_ERR"Adaptec: Error Reading Hardware.\n");
3078 return ret;
3079 }
3080
3081 if ((pHba->lct->table_size << 2) > pHba->lct_size) {
3082 pHba->lct_size = pHba->lct->table_size << 2;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003083 dma_free_coherent(&pHba->pDev->dev, pHba->lct_size,
3084 pHba->lct, pHba->lct_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085 pHba->lct = NULL;
3086 }
3087 } while (pHba->lct == NULL);
3088
3089 PDEBUG("%s: Hardware resource table read.\n", pHba->name);
3090
3091
3092 // I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO;
3093 if(adpt_i2o_query_scalar(pHba, 0 , 0x8000, -1, buf, sizeof(buf))>=0) {
3094 pHba->FwDebugBufferSize = buf[1];
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02003095 pHba->FwDebugBuffer_P = ioremap(pHba->base_addr_phys + buf[0],
3096 pHba->FwDebugBufferSize);
3097 if (pHba->FwDebugBuffer_P) {
3098 pHba->FwDebugFlags_P = pHba->FwDebugBuffer_P +
3099 FW_DEBUG_FLAGS_OFFSET;
3100 pHba->FwDebugBLEDvalue_P = pHba->FwDebugBuffer_P +
3101 FW_DEBUG_BLED_OFFSET;
3102 pHba->FwDebugBLEDflag_P = pHba->FwDebugBLEDvalue_P + 1;
3103 pHba->FwDebugStrLength_P = pHba->FwDebugBuffer_P +
3104 FW_DEBUG_STR_LENGTH_OFFSET;
3105 pHba->FwDebugBuffer_P += buf[2];
3106 pHba->FwDebugFlags = 0;
3107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108 }
3109
3110 return 0;
3111}
3112
3113static int adpt_i2o_build_sys_table(void)
3114{
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003115 adpt_hba* pHba = hba_chain;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 int count = 0;
3117
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003118 if (sys_tbl)
3119 dma_free_coherent(&pHba->pDev->dev, sys_tbl_len,
3120 sys_tbl, sys_tbl_pa);
3121
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122 sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs
3123 (hba_count) * sizeof(struct i2o_sys_tbl_entry);
3124
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003125 sys_tbl = dma_alloc_coherent(&pHba->pDev->dev,
3126 sys_tbl_len, &sys_tbl_pa, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02003127 if (!sys_tbl) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 printk(KERN_WARNING "SysTab Set failed. Out of memory.\n");
3129 return -ENOMEM;
3130 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003131 memset(sys_tbl, 0, sys_tbl_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132
3133 sys_tbl->num_entries = hba_count;
3134 sys_tbl->version = I2OVERSION;
3135 sys_tbl->change_ind = sys_tbl_ind++;
3136
3137 for(pHba = hba_chain; pHba; pHba = pHba->next) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003138 u64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 // Get updated Status Block so we have the latest information
3140 if (adpt_i2o_status_get(pHba)) {
3141 sys_tbl->num_entries--;
3142 continue; // try next one
3143 }
3144
3145 sys_tbl->iops[count].org_id = pHba->status_block->org_id;
3146 sys_tbl->iops[count].iop_id = pHba->unit + 2;
3147 sys_tbl->iops[count].seg_num = 0;
3148 sys_tbl->iops[count].i2o_version = pHba->status_block->i2o_version;
3149 sys_tbl->iops[count].iop_state = pHba->status_block->iop_state;
3150 sys_tbl->iops[count].msg_type = pHba->status_block->msg_type;
3151 sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size;
3152 sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
3153 sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003154 addr = pHba->base_addr_phys + 0x40;
3155 sys_tbl->iops[count].inbound_low = dma_low(addr);
3156 sys_tbl->iops[count].inbound_high = dma_high(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157
3158 count++;
3159 }
3160
3161#ifdef DEBUG
3162{
3163 u32 *table = (u32*)sys_tbl;
3164 printk(KERN_DEBUG"sys_tbl_len=%d in 32bit words\n",(sys_tbl_len >>2));
3165 for(count = 0; count < (sys_tbl_len >>2); count++) {
3166 printk(KERN_INFO "sys_tbl[%d] = %0#10x\n",
3167 count, table[count]);
3168 }
3169}
3170#endif
3171
3172 return 0;
3173}
3174
3175
3176/*
3177 * Dump the information block associated with a given unit (TID)
3178 */
3179
3180static void adpt_i2o_report_hba_unit(adpt_hba* pHba, struct i2o_device *d)
3181{
3182 char buf[64];
3183 int unit = d->lct_data.tid;
3184
3185 printk(KERN_INFO "TID %3.3d ", unit);
3186
3187 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 3, buf, 16)>=0)
3188 {
3189 buf[16]=0;
3190 printk(" Vendor: %-12.12s", buf);
3191 }
3192 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 4, buf, 16)>=0)
3193 {
3194 buf[16]=0;
3195 printk(" Device: %-12.12s", buf);
3196 }
3197 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 6, buf, 8)>=0)
3198 {
3199 buf[8]=0;
3200 printk(" Rev: %-12.12s\n", buf);
3201 }
3202#ifdef DEBUG
3203 printk(KERN_INFO "\tClass: %.21s\n", adpt_i2o_get_class_name(d->lct_data.class_id));
3204 printk(KERN_INFO "\tSubclass: 0x%04X\n", d->lct_data.sub_class);
3205 printk(KERN_INFO "\tFlags: ");
3206
3207 if(d->lct_data.device_flags&(1<<0))
3208 printk("C"); // ConfigDialog requested
3209 if(d->lct_data.device_flags&(1<<1))
3210 printk("U"); // Multi-user capable
3211 if(!(d->lct_data.device_flags&(1<<4)))
3212 printk("P"); // Peer service enabled!
3213 if(!(d->lct_data.device_flags&(1<<5)))
3214 printk("M"); // Mgmt service enabled!
3215 printk("\n");
3216#endif
3217}
3218
3219#ifdef DEBUG
3220/*
3221 * Do i2o class name lookup
3222 */
3223static const char *adpt_i2o_get_class_name(int class)
3224{
3225 int idx = 16;
3226 static char *i2o_class_name[] = {
3227 "Executive",
3228 "Device Driver Module",
3229 "Block Device",
3230 "Tape Device",
3231 "LAN Interface",
3232 "WAN Interface",
3233 "Fibre Channel Port",
3234 "Fibre Channel Device",
3235 "SCSI Device",
3236 "ATE Port",
3237 "ATE Device",
3238 "Floppy Controller",
3239 "Floppy Device",
3240 "Secondary Bus Port",
3241 "Peer Transport Agent",
3242 "Peer Transport",
3243 "Unknown"
3244 };
3245
3246 switch(class&0xFFF) {
3247 case I2O_CLASS_EXECUTIVE:
3248 idx = 0; break;
3249 case I2O_CLASS_DDM:
3250 idx = 1; break;
3251 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
3252 idx = 2; break;
3253 case I2O_CLASS_SEQUENTIAL_STORAGE:
3254 idx = 3; break;
3255 case I2O_CLASS_LAN:
3256 idx = 4; break;
3257 case I2O_CLASS_WAN:
3258 idx = 5; break;
3259 case I2O_CLASS_FIBRE_CHANNEL_PORT:
3260 idx = 6; break;
3261 case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
3262 idx = 7; break;
3263 case I2O_CLASS_SCSI_PERIPHERAL:
3264 idx = 8; break;
3265 case I2O_CLASS_ATE_PORT:
3266 idx = 9; break;
3267 case I2O_CLASS_ATE_PERIPHERAL:
3268 idx = 10; break;
3269 case I2O_CLASS_FLOPPY_CONTROLLER:
3270 idx = 11; break;
3271 case I2O_CLASS_FLOPPY_DEVICE:
3272 idx = 12; break;
3273 case I2O_CLASS_BUS_ADAPTER_PORT:
3274 idx = 13; break;
3275 case I2O_CLASS_PEER_TRANSPORT_AGENT:
3276 idx = 14; break;
3277 case I2O_CLASS_PEER_TRANSPORT:
3278 idx = 15; break;
3279 }
3280 return i2o_class_name[idx];
3281}
3282#endif
3283
3284
3285static s32 adpt_i2o_hrt_get(adpt_hba* pHba)
3286{
3287 u32 msg[6];
3288 int ret, size = sizeof(i2o_hrt);
3289
3290 do {
3291 if (pHba->hrt == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003292 pHba->hrt = dma_alloc_coherent(&pHba->pDev->dev,
3293 size, &pHba->hrt_pa, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294 if (pHba->hrt == NULL) {
3295 printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", pHba->name);
3296 return -ENOMEM;
3297 }
3298 }
3299
3300 msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
3301 msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
3302 msg[2]= 0;
3303 msg[3]= 0;
3304 msg[4]= (0xD0000000 | size); /* Simple transaction */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003305 msg[5]= (u32)pHba->hrt_pa; /* Dump it here */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306
3307 if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg),20))) {
3308 printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n", pHba->name, ret);
3309 return ret;
3310 }
3311
3312 if (pHba->hrt->num_entries * pHba->hrt->entry_len << 2 > size) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003313 int newsize = pHba->hrt->num_entries * pHba->hrt->entry_len << 2;
3314 dma_free_coherent(&pHba->pDev->dev, size,
3315 pHba->hrt, pHba->hrt_pa);
3316 size = newsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317 pHba->hrt = NULL;
3318 }
3319 } while(pHba->hrt == NULL);
3320 return 0;
3321}
3322
3323/*
3324 * Query one scalar group value or a whole scalar group.
3325 */
3326static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid,
3327 int group, int field, void *buf, int buflen)
3328{
3329 u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003330 u8 *opblk_va;
3331 dma_addr_t opblk_pa;
3332 u8 *resblk_va;
3333 dma_addr_t resblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334
3335 int size;
3336
3337 /* 8 bytes for header */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003338 resblk_va = dma_alloc_coherent(&pHba->pDev->dev,
3339 sizeof(u8) * (8 + buflen), &resblk_pa, GFP_KERNEL);
3340 if (resblk_va == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341 printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name);
3342 return -ENOMEM;
3343 }
3344
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003345 opblk_va = dma_alloc_coherent(&pHba->pDev->dev,
3346 sizeof(opblk), &opblk_pa, GFP_KERNEL);
3347 if (opblk_va == NULL) {
3348 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3349 resblk_va, resblk_pa);
Colin Ian Kingd0799622016-11-07 16:38:57 +00003350 printk(KERN_CRIT "%s: query operation failed; Out of memory.\n",
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003351 pHba->name);
3352 return -ENOMEM;
3353 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 if (field == -1) /* whole group */
3355 opblk[4] = -1;
3356
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003357 memcpy(opblk_va, opblk, sizeof(opblk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358 size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid,
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003359 opblk_va, opblk_pa, sizeof(opblk),
3360 resblk_va, resblk_pa, sizeof(u8)*(8+buflen));
3361 dma_free_coherent(&pHba->pDev->dev, sizeof(opblk), opblk_va, opblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362 if (size == -ETIME) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003363 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3364 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 printk(KERN_WARNING "%s: issue params failed; Timed out.\n", pHba->name);
3366 return -ETIME;
3367 } else if (size == -EINTR) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003368 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3369 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370 printk(KERN_WARNING "%s: issue params failed; Interrupted.\n", pHba->name);
3371 return -EINTR;
3372 }
3373
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003374 memcpy(buf, resblk_va+8, buflen); /* cut off header */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003376 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3377 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378 if (size < 0)
3379 return size;
3380
3381 return buflen;
3382}
3383
3384
3385/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
3386 *
3387 * This function can be used for all UtilParamsGet/Set operations.
3388 * The OperationBlock is given in opblk-buffer,
3389 * and results are returned in resblk-buffer.
3390 * Note that the minimum sized resblk is 8 bytes and contains
3391 * ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
3392 */
3393static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid,
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003394 void *opblk_va, dma_addr_t opblk_pa, int oplen,
3395 void *resblk_va, dma_addr_t resblk_pa, int reslen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396{
3397 u32 msg[9];
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003398 u32 *res = (u32 *)resblk_va;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 int wait_status;
3400
3401 msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
3402 msg[1] = cmd << 24 | HOST_TID << 12 | tid;
3403 msg[2] = 0;
3404 msg[3] = 0;
3405 msg[4] = 0;
3406 msg[5] = 0x54000000 | oplen; /* OperationBlock */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003407 msg[6] = (u32)opblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408 msg[7] = 0xD0000000 | reslen; /* ResultBlock */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003409 msg[8] = (u32)resblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410
3411 if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003412 printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk_va);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413 return wait_status; /* -DetailedStatus */
3414 }
3415
3416 if (res[1]&0x00FF0000) { /* BlockStatus != SUCCESS */
3417 printk(KERN_WARNING "%s: %s - Error:\n ErrorInfoSize = 0x%02x, "
3418 "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
3419 pHba->name,
3420 (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"
3421 : "PARAMS_GET",
3422 res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
3423 return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
3424 }
3425
3426 return 4 + ((res[1] & 0x0000FFFF) << 2); /* bytes used in resblk */
3427}
3428
3429
3430static s32 adpt_i2o_quiesce_hba(adpt_hba* pHba)
3431{
3432 u32 msg[4];
3433 int ret;
3434
3435 adpt_i2o_status_get(pHba);
3436
3437 /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */
3438
3439 if((pHba->status_block->iop_state != ADAPTER_STATE_READY) &&
3440 (pHba->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)){
3441 return 0;
3442 }
3443
3444 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
3445 msg[1] = I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
3446 msg[2] = 0;
3447 msg[3] = 0;
3448
3449 if((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) {
3450 printk(KERN_INFO"dpti%d: Unable to quiesce (status=%#x).\n",
3451 pHba->unit, -ret);
3452 } else {
3453 printk(KERN_INFO"dpti%d: Quiesced.\n",pHba->unit);
3454 }
3455
3456 adpt_i2o_status_get(pHba);
3457 return ret;
3458}
3459
3460
3461/*
3462 * Enable IOP. Allows the IOP to resume external operations.
3463 */
3464static int adpt_i2o_enable_hba(adpt_hba* pHba)
3465{
3466 u32 msg[4];
3467 int ret;
3468
3469 adpt_i2o_status_get(pHba);
3470 if(!pHba->status_block){
3471 return -ENOMEM;
3472 }
3473 /* Enable only allowed on READY state */
3474 if(pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)
3475 return 0;
3476
3477 if(pHba->status_block->iop_state != ADAPTER_STATE_READY)
3478 return -EINVAL;
3479
3480 msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
3481 msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
3482 msg[2]= 0;
3483 msg[3]= 0;
3484
3485 if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) {
3486 printk(KERN_WARNING"%s: Could not enable (status=%#10x).\n",
3487 pHba->name, ret);
3488 } else {
3489 PDEBUG("%s: Enabled.\n", pHba->name);
3490 }
3491
3492 adpt_i2o_status_get(pHba);
3493 return ret;
3494}
3495
3496
3497static int adpt_i2o_systab_send(adpt_hba* pHba)
3498{
3499 u32 msg[12];
3500 int ret;
3501
3502 msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
3503 msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
3504 msg[2] = 0;
3505 msg[3] = 0;
3506 msg[4] = (0<<16) | ((pHba->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */
3507 msg[5] = 0; /* Segment 0 */
3508
3509 /*
3510 * Provide three SGL-elements:
3511 * System table (SysTab), Private memory space declaration and
3512 * Private i/o space declaration
3513 */
3514 msg[6] = 0x54000000 | sys_tbl_len;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003515 msg[7] = (u32)sys_tbl_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516 msg[8] = 0x54000000 | 0;
3517 msg[9] = 0;
3518 msg[10] = 0xD4000000 | 0;
3519 msg[11] = 0;
3520
3521 if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 120))) {
3522 printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n",
3523 pHba->name, ret);
3524 }
3525#ifdef DEBUG
3526 else {
3527 PINFO("%s: SysTab set.\n", pHba->name);
3528 }
3529#endif
3530
3531 return ret;
3532 }
3533
3534
3535/*============================================================================
3536 *
3537 *============================================================================
3538 */
3539
3540
3541#ifdef UARTDELAY
3542
3543static static void adpt_delay(int millisec)
3544{
3545 int i;
3546 for (i = 0; i < millisec; i++) {
3547 udelay(1000); /* delay for one millisecond */
3548 }
3549}
3550
3551#endif
3552
Andrew Morton24601bb2007-12-10 15:49:20 -08003553static struct scsi_host_template driver_template = {
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02003554 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555 .name = "dpt_i2o",
3556 .proc_name = "dpt_i2o",
Al Viroff98f7c2013-03-31 03:21:50 -04003557 .show_info = adpt_show_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558 .info = adpt_info,
3559 .queuecommand = adpt_queue,
3560 .eh_abort_handler = adpt_abort,
3561 .eh_device_reset_handler = adpt_device_reset,
3562 .eh_bus_reset_handler = adpt_bus_reset,
3563 .eh_host_reset_handler = adpt_reset,
3564 .bios_param = adpt_bios_param,
3565 .slave_configure = adpt_slave_configure,
3566 .can_queue = MAX_TO_IOP_MESSAGES,
3567 .this_id = 7,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568 .use_clustering = ENABLE_CLUSTERING,
3569};
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02003570
3571static int __init adpt_init(void)
3572{
3573 int error;
3574 adpt_hba *pHba, *next;
3575
3576 printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n");
3577
3578 error = adpt_detect(&driver_template);
3579 if (error < 0)
3580 return error;
3581 if (hba_chain == NULL)
3582 return -ENODEV;
3583
3584 for (pHba = hba_chain; pHba; pHba = pHba->next) {
3585 error = scsi_add_host(pHba->host, &pHba->pDev->dev);
3586 if (error)
3587 goto fail;
3588 scsi_scan_host(pHba->host);
3589 }
3590 return 0;
3591fail:
3592 for (pHba = hba_chain; pHba; pHba = next) {
3593 next = pHba->next;
3594 scsi_remove_host(pHba->host);
3595 }
3596 return error;
3597}
3598
3599static void __exit adpt_exit(void)
3600{
3601 adpt_hba *pHba, *next;
3602
3603 for (pHba = hba_chain; pHba; pHba = pHba->next)
3604 scsi_remove_host(pHba->host);
3605 for (pHba = hba_chain; pHba; pHba = next) {
3606 next = pHba->next;
3607 adpt_release(pHba->host);
3608 }
3609}
3610
3611module_init(adpt_init);
3612module_exit(adpt_exit);
3613
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614MODULE_LICENSE("GPL");