blob: f88b3d216a88bb15b5c556f0e205226df592f18d [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 */
40#include <asm/uaccess.h>
41
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) {
654 kfree (reply);
655 printk(KERN_WARNING"%s: Too many outstanding "
656 "ioctl commands\n", pHba->name);
657 return (u32)-1;
658 }
659
660 return i;
661#endif
662}
663
664/*
665 * Go from an u32 'context' to a pointer to ioctl reply data.
666 */
667static void *adpt_ioctl_from_context(adpt_hba *pHba, u32 context)
668{
669#if BITS_PER_LONG == 32
670 return (void *)(unsigned long)context;
671#else
672 void *p = pHba->ioctl_reply_context[context];
673 pHba->ioctl_reply_context[context] = NULL;
674
675 return p;
676#endif
677}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
679/*===========================================================================
680 * Error Handling routines
681 *===========================================================================
682 */
683
684static int adpt_abort(struct scsi_cmnd * cmd)
685{
686 adpt_hba* pHba = NULL; /* host bus adapter structure */
687 struct adpt_device* dptdevice; /* dpt per device information */
688 u32 msg[5];
689 int rcode;
690
691 if(cmd->serial_number == 0){
692 return FAILED;
693 }
694 pHba = (adpt_hba*) cmd->device->host->hostdata[0];
Christoph Hellwig5cd049a2011-04-04 09:42:14 -0400695 printk(KERN_INFO"%s: Trying to Abort\n",pHba->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 if ((dptdevice = (void*) (cmd->device->hostdata)) == NULL) {
697 printk(KERN_ERR "%s: Unable to abort: No device in cmnd\n",pHba->name);
698 return FAILED;
699 }
700
701 memset(msg, 0, sizeof(msg));
702 msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
703 msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|dptdevice->tid;
704 msg[2] = 0;
705 msg[3]= 0;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200706 msg[4] = adpt_cmd_to_context(cmd);
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800707 if (pHba->host)
708 spin_lock_irq(pHba->host->host_lock);
709 rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER);
710 if (pHba->host)
711 spin_unlock_irq(pHba->host->host_lock);
712 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 if(rcode == -EOPNOTSUPP ){
714 printk(KERN_INFO"%s: Abort cmd not supported\n",pHba->name);
715 return FAILED;
716 }
Christoph Hellwig5cd049a2011-04-04 09:42:14 -0400717 printk(KERN_INFO"%s: Abort failed.\n",pHba->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 return FAILED;
719 }
Christoph Hellwig5cd049a2011-04-04 09:42:14 -0400720 printk(KERN_INFO"%s: Abort complete.\n",pHba->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 return SUCCESS;
722}
723
724
725#define I2O_DEVICE_RESET 0x27
726// This is the same for BLK and SCSI devices
727// NOTE this is wrong in the i2o.h definitions
728// This is not currently supported by our adapter but we issue it anyway
729static int adpt_device_reset(struct scsi_cmnd* cmd)
730{
731 adpt_hba* pHba;
732 u32 msg[4];
733 u32 rcode;
734 int old_state;
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -0700735 struct adpt_device* d = cmd->device->hostdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
737 pHba = (void*) cmd->device->host->hostdata[0];
738 printk(KERN_INFO"%s: Trying to reset device\n",pHba->name);
739 if (!d) {
740 printk(KERN_INFO"%s: Reset Device: Device Not found\n",pHba->name);
741 return FAILED;
742 }
743 memset(msg, 0, sizeof(msg));
744 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
745 msg[1] = (I2O_DEVICE_RESET<<24|HOST_TID<<12|d->tid);
746 msg[2] = 0;
747 msg[3] = 0;
748
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800749 if (pHba->host)
750 spin_lock_irq(pHba->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 old_state = d->state;
752 d->state |= DPTI_DEV_RESET;
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800753 rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
754 d->state = old_state;
755 if (pHba->host)
756 spin_unlock_irq(pHba->host->host_lock);
757 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 if(rcode == -EOPNOTSUPP ){
759 printk(KERN_INFO"%s: Device reset not supported\n",pHba->name);
760 return FAILED;
761 }
762 printk(KERN_INFO"%s: Device reset failed\n",pHba->name);
763 return FAILED;
764 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 printk(KERN_INFO"%s: Device reset successful\n",pHba->name);
766 return SUCCESS;
767 }
768}
769
770
771#define I2O_HBA_BUS_RESET 0x87
772// This version of bus reset is called by the eh_error handler
773static int adpt_bus_reset(struct scsi_cmnd* cmd)
774{
775 adpt_hba* pHba;
776 u32 msg[4];
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800777 u32 rcode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778
779 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
780 memset(msg, 0, sizeof(msg));
781 printk(KERN_WARNING"%s: Bus reset: SCSI Bus %d: tid: %d\n",pHba->name, cmd->device->channel,pHba->channel[cmd->device->channel].tid );
782 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
783 msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->device->channel].tid);
784 msg[2] = 0;
785 msg[3] = 0;
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800786 if (pHba->host)
787 spin_lock_irq(pHba->host->host_lock);
788 rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
789 if (pHba->host)
790 spin_unlock_irq(pHba->host->host_lock);
791 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name);
793 return FAILED;
794 } else {
795 printk(KERN_WARNING"%s: Bus reset success.\n",pHba->name);
796 return SUCCESS;
797 }
798}
799
800// This version of reset is called by the eh_error_handler
Jeff Garzik df0ae242005-05-28 07:57:14 -0400801static int __adpt_reset(struct scsi_cmnd* cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802{
803 adpt_hba* pHba;
804 int rcode;
805 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
806 printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n",pHba->name,cmd->device->channel,pHba->channel[cmd->device->channel].tid );
807 rcode = adpt_hba_reset(pHba);
808 if(rcode == 0){
809 printk(KERN_WARNING"%s: HBA reset complete\n",pHba->name);
810 return SUCCESS;
811 } else {
812 printk(KERN_WARNING"%s: HBA reset failed (%x)\n",pHba->name, rcode);
813 return FAILED;
814 }
815}
816
Jeff Garzik df0ae242005-05-28 07:57:14 -0400817static int adpt_reset(struct scsi_cmnd* cmd)
818{
819 int rc;
820
821 spin_lock_irq(cmd->device->host->host_lock);
822 rc = __adpt_reset(cmd);
823 spin_unlock_irq(cmd->device->host->host_lock);
824
825 return rc;
826}
827
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828// This version of reset is called by the ioctls and indirectly from eh_error_handler via adpt_reset
829static int adpt_hba_reset(adpt_hba* pHba)
830{
831 int rcode;
832
833 pHba->state |= DPTI_STATE_RESET;
834
835 // Activate does get status , init outbound, and get hrt
836 if ((rcode=adpt_i2o_activate_hba(pHba)) < 0) {
837 printk(KERN_ERR "%s: Could not activate\n", pHba->name);
838 adpt_i2o_delete_hba(pHba);
839 return rcode;
840 }
841
842 if ((rcode=adpt_i2o_build_sys_table()) < 0) {
843 adpt_i2o_delete_hba(pHba);
844 return rcode;
845 }
846 PDEBUG("%s: in HOLD state\n",pHba->name);
847
848 if ((rcode=adpt_i2o_online_hba(pHba)) < 0) {
849 adpt_i2o_delete_hba(pHba);
850 return rcode;
851 }
852 PDEBUG("%s: in OPERATIONAL state\n",pHba->name);
853
854 if ((rcode=adpt_i2o_lct_get(pHba)) < 0){
855 adpt_i2o_delete_hba(pHba);
856 return rcode;
857 }
858
859 if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){
860 adpt_i2o_delete_hba(pHba);
861 return rcode;
862 }
863 pHba->state &= ~DPTI_STATE_RESET;
864
865 adpt_fail_posted_scbs(pHba);
866 return 0; /* return success */
867}
868
869/*===========================================================================
870 *
871 *===========================================================================
872 */
873
874
875static void adpt_i2o_sys_shutdown(void)
876{
877 adpt_hba *pHba, *pNext;
Adrian Bunk458af542005-11-27 00:36:37 +0100878 struct adpt_i2o_post_wait_data *p1, *old;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879
880 printk(KERN_INFO"Shutting down Adaptec I2O controllers.\n");
881 printk(KERN_INFO" This could take a few minutes if there are many devices attached\n");
882 /* Delete all IOPs from the controller chain */
883 /* They should have already been released by the
884 * scsi-core
885 */
886 for (pHba = hba_chain; pHba; pHba = pNext) {
887 pNext = pHba->next;
888 adpt_i2o_delete_hba(pHba);
889 }
890
891 /* Remove any timedout entries from the wait queue. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892// spin_lock_irqsave(&adpt_post_wait_lock, flags);
893 /* Nothing should be outstanding at this point so just
894 * free them
895 */
Adrian Bunk458af542005-11-27 00:36:37 +0100896 for(p1 = adpt_post_wait_queue; p1;) {
897 old = p1;
898 p1 = p1->next;
899 kfree(old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 }
901// spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
902 adpt_post_wait_queue = NULL;
903
904 printk(KERN_INFO "Adaptec I2O controllers down.\n");
905}
906
Andrew Morton24601bb2007-12-10 15:49:20 -0800907static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908{
909
910 adpt_hba* pHba = NULL;
911 adpt_hba* p = NULL;
912 ulong base_addr0_phys = 0;
913 ulong base_addr1_phys = 0;
914 u32 hba_map0_area_size = 0;
915 u32 hba_map1_area_size = 0;
916 void __iomem *base_addr_virt = NULL;
917 void __iomem *msg_addr_virt = NULL;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200918 int dma64 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
920 int raptorFlag = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921
922 if(pci_enable_device(pDev)) {
923 return -EINVAL;
924 }
Salyzyn, Mark9638d892006-01-12 08:31:57 -0500925
926 if (pci_request_regions(pDev, "dpt_i2o")) {
927 PERROR("dpti: adpt_config_hba: pci request region failed\n");
928 return -EINVAL;
929 }
930
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 pci_set_master(pDev);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200932
933 /*
934 * See if we should enable dma64 mode.
935 */
936 if (sizeof(dma_addr_t) > 4 &&
Yang Hongyang6a355282009-04-06 19:01:13 -0700937 pci_set_dma_mask(pDev, DMA_BIT_MASK(64)) == 0) {
Yang Hongyang284901a2009-04-06 19:01:15 -0700938 if (dma_get_required_mask(&pDev->dev) > DMA_BIT_MASK(32))
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200939 dma64 = 1;
940 }
Yang Hongyang284901a2009-04-06 19:01:15 -0700941 if (!dma64 && pci_set_dma_mask(pDev, DMA_BIT_MASK(32)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 return -EINVAL;
943
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200944 /* adapter only supports message blocks below 4GB */
Yang Hongyang284901a2009-04-06 19:01:15 -0700945 pci_set_consistent_dma_mask(pDev, DMA_BIT_MASK(32));
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200946
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 base_addr0_phys = pci_resource_start(pDev,0);
948 hba_map0_area_size = pci_resource_len(pDev,0);
949
950 // Check if standard PCI card or single BAR Raptor
951 if(pDev->device == PCI_DPT_DEVICE_ID){
952 if(pDev->subsystem_device >=0xc032 && pDev->subsystem_device <= 0xc03b){
953 // Raptor card with this device id needs 4M
954 hba_map0_area_size = 0x400000;
955 } else { // Not Raptor - it is a PCI card
956 if(hba_map0_area_size > 0x100000 ){
957 hba_map0_area_size = 0x100000;
958 }
959 }
960 } else {// Raptor split BAR config
961 // Use BAR1 in this configuration
962 base_addr1_phys = pci_resource_start(pDev,1);
963 hba_map1_area_size = pci_resource_len(pDev,1);
964 raptorFlag = TRUE;
965 }
966
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200967#if BITS_PER_LONG == 64
968 /*
969 * The original Adaptec 64 bit driver has this comment here:
970 * "x86_64 machines need more optimal mappings"
971 *
972 * I assume some HBAs report ridiculously large mappings
973 * and we need to limit them on platforms with IOMMUs.
974 */
975 if (raptorFlag == TRUE) {
976 if (hba_map0_area_size > 128)
977 hba_map0_area_size = 128;
978 if (hba_map1_area_size > 524288)
979 hba_map1_area_size = 524288;
980 } else {
981 if (hba_map0_area_size > 524288)
982 hba_map0_area_size = 524288;
983 }
984#endif
985
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size);
987 if (!base_addr_virt) {
James Bottomley9c472dd2005-08-08 11:51:38 -0500988 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 PERROR("dpti: adpt_config_hba: io remap failed\n");
990 return -EINVAL;
991 }
992
993 if(raptorFlag == TRUE) {
994 msg_addr_virt = ioremap(base_addr1_phys, hba_map1_area_size );
995 if (!msg_addr_virt) {
996 PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n");
997 iounmap(base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -0500998 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 return -EINVAL;
1000 }
1001 } else {
1002 msg_addr_virt = base_addr_virt;
1003 }
1004
1005 // Allocate and zero the data structure
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02001006 pHba = kzalloc(sizeof(adpt_hba), GFP_KERNEL);
1007 if (!pHba) {
1008 if (msg_addr_virt != base_addr_virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 iounmap(msg_addr_virt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 iounmap(base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -05001011 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 return -ENOMEM;
1013 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014
Arjan van de Ven0b950672006-01-11 13:16:10 +01001015 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016
1017 if(hba_chain != NULL){
1018 for(p = hba_chain; p->next; p = p->next);
1019 p->next = pHba;
1020 } else {
1021 hba_chain = pHba;
1022 }
1023 pHba->next = NULL;
1024 pHba->unit = hba_count;
Benoit Boissinot 23a2bc22005-04-25 19:46:30 -07001025 sprintf(pHba->name, "dpti%d", hba_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 hba_count++;
1027
Arjan van de Ven0b950672006-01-11 13:16:10 +01001028 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
1030 pHba->pDev = pDev;
1031 pHba->base_addr_phys = base_addr0_phys;
1032
1033 // Set up the Virtual Base Address of the I2O Device
1034 pHba->base_addr_virt = base_addr_virt;
1035 pHba->msg_addr_virt = msg_addr_virt;
1036 pHba->irq_mask = base_addr_virt+0x30;
1037 pHba->post_port = base_addr_virt+0x40;
1038 pHba->reply_port = base_addr_virt+0x44;
1039
1040 pHba->hrt = NULL;
1041 pHba->lct = NULL;
1042 pHba->lct_size = 0;
1043 pHba->status_block = NULL;
1044 pHba->post_count = 0;
1045 pHba->state = DPTI_STATE_RESET;
1046 pHba->pDev = pDev;
1047 pHba->devices = NULL;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001048 pHba->dma64 = dma64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
1050 // Initializing the spinlocks
1051 spin_lock_init(&pHba->state_lock);
1052 spin_lock_init(&adpt_post_wait_lock);
1053
1054 if(raptorFlag == 0){
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001055 printk(KERN_INFO "Adaptec I2O RAID controller"
1056 " %d at %p size=%x irq=%d%s\n",
1057 hba_count-1, base_addr_virt,
1058 hba_map0_area_size, pDev->irq,
1059 dma64 ? " (64-bit DMA)" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 } else {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001061 printk(KERN_INFO"Adaptec I2O RAID controller %d irq=%d%s\n",
1062 hba_count-1, pDev->irq,
1063 dma64 ? " (64-bit DMA)" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 printk(KERN_INFO" BAR0 %p - size= %x\n",base_addr_virt,hba_map0_area_size);
1065 printk(KERN_INFO" BAR1 %p - size= %x\n",msg_addr_virt,hba_map1_area_size);
1066 }
1067
Thomas Gleixner1d6f3592006-07-01 19:29:42 -07001068 if (request_irq (pDev->irq, adpt_isr, IRQF_SHARED, pHba->name, pHba)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 printk(KERN_ERR"%s: Couldn't register IRQ %d\n", pHba->name, pDev->irq);
1070 adpt_i2o_delete_hba(pHba);
1071 return -EINVAL;
1072 }
1073
1074 return 0;
1075}
1076
1077
1078static void adpt_i2o_delete_hba(adpt_hba* pHba)
1079{
1080 adpt_hba* p1;
1081 adpt_hba* p2;
1082 struct i2o_device* d;
1083 struct i2o_device* next;
1084 int i;
1085 int j;
1086 struct adpt_device* pDev;
1087 struct adpt_device* pNext;
1088
1089
Arjan van de Ven0b950672006-01-11 13:16:10 +01001090 mutex_lock(&adpt_configuration_lock);
Andrew Morton24601bb2007-12-10 15:49:20 -08001091 // scsi_unregister calls our adpt_release which
1092 // does a quiese
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 if(pHba->host){
1094 free_irq(pHba->host->irq, pHba);
1095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 p2 = NULL;
1097 for( p1 = hba_chain; p1; p2 = p1,p1=p1->next){
1098 if(p1 == pHba) {
1099 if(p2) {
1100 p2->next = p1->next;
1101 } else {
1102 hba_chain = p1->next;
1103 }
1104 break;
1105 }
1106 }
1107
1108 hba_count--;
Arjan van de Ven0b950672006-01-11 13:16:10 +01001109 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
1111 iounmap(pHba->base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -05001112 pci_release_regions(pHba->pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 if(pHba->msg_addr_virt != pHba->base_addr_virt){
1114 iounmap(pHba->msg_addr_virt);
1115 }
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001116 if(pHba->FwDebugBuffer_P)
1117 iounmap(pHba->FwDebugBuffer_P);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001118 if(pHba->hrt) {
1119 dma_free_coherent(&pHba->pDev->dev,
1120 pHba->hrt->num_entries * pHba->hrt->entry_len << 2,
1121 pHba->hrt, pHba->hrt_pa);
1122 }
1123 if(pHba->lct) {
1124 dma_free_coherent(&pHba->pDev->dev, pHba->lct_size,
1125 pHba->lct, pHba->lct_pa);
1126 }
1127 if(pHba->status_block) {
1128 dma_free_coherent(&pHba->pDev->dev, sizeof(i2o_status_block),
1129 pHba->status_block, pHba->status_block_pa);
1130 }
1131 if(pHba->reply_pool) {
1132 dma_free_coherent(&pHba->pDev->dev,
1133 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
1134 pHba->reply_pool, pHba->reply_pool_pa);
1135 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136
1137 for(d = pHba->devices; d ; d = next){
1138 next = d->next;
1139 kfree(d);
1140 }
1141 for(i = 0 ; i < pHba->top_scsi_channel ; i++){
1142 for(j = 0; j < MAX_ID; j++){
1143 if(pHba->channel[i].device[j] != NULL){
1144 for(pDev = pHba->channel[i].device[j]; pDev; pDev = pNext){
1145 pNext = pDev->next_lun;
1146 kfree(pDev);
1147 }
1148 }
1149 }
1150 }
Alan Coxa07f3532006-09-15 15:34:32 +01001151 pci_dev_put(pHba->pDev);
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +02001152 if (adpt_sysfs_class)
1153 device_destroy(adpt_sysfs_class,
1154 MKDEV(DPTI_I2O_MAJOR, pHba->unit));
Dan Carpenter229bab62010-03-15 11:26:56 +03001155 kfree(pHba);
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +02001156
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 if(hba_count <= 0){
1158 unregister_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER);
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +02001159 if (adpt_sysfs_class) {
1160 class_destroy(adpt_sysfs_class);
1161 adpt_sysfs_class = NULL;
1162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 }
1164}
1165
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02001166static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167{
1168 struct adpt_device* d;
1169
1170 if(chan < 0 || chan >= MAX_CHANNEL)
1171 return NULL;
1172
1173 if( pHba->channel[chan].device == NULL){
1174 printk(KERN_DEBUG"Adaptec I2O RAID: Trying to find device before they are allocated\n");
1175 return NULL;
1176 }
1177
1178 d = pHba->channel[chan].device[id];
1179 if(!d || d->tid == 0) {
1180 return NULL;
1181 }
1182
1183 /* If it is the only lun at that address then this should match*/
1184 if(d->scsi_lun == lun){
1185 return d;
1186 }
1187
1188 /* else we need to look through all the luns */
1189 for(d=d->next_lun ; d ; d = d->next_lun){
1190 if(d->scsi_lun == lun){
1191 return d;
1192 }
1193 }
1194 return NULL;
1195}
1196
1197
1198static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout)
1199{
1200 // I used my own version of the WAIT_QUEUE_HEAD
1201 // to handle some version differences
1202 // When embedded in the kernel this could go back to the vanilla one
1203 ADPT_DECLARE_WAIT_QUEUE_HEAD(adpt_wq_i2o_post);
1204 int status = 0;
1205 ulong flags = 0;
1206 struct adpt_i2o_post_wait_data *p1, *p2;
1207 struct adpt_i2o_post_wait_data *wait_data =
Julia Lawallda2907f2010-05-30 15:49:22 +02001208 kmalloc(sizeof(struct adpt_i2o_post_wait_data), GFP_ATOMIC);
Andrew Morton4452ea52005-06-23 00:10:26 -07001209 DECLARE_WAITQUEUE(wait, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
Andrew Morton4452ea52005-06-23 00:10:26 -07001211 if (!wait_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 return -ENOMEM;
Andrew Morton4452ea52005-06-23 00:10:26 -07001213
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 /*
1215 * The spin locking is needed to keep anyone from playing
1216 * with the queue pointers and id while we do the same
1217 */
1218 spin_lock_irqsave(&adpt_post_wait_lock, flags);
1219 // TODO we need a MORE unique way of getting ids
1220 // to support async LCT get
1221 wait_data->next = adpt_post_wait_queue;
1222 adpt_post_wait_queue = wait_data;
1223 adpt_post_wait_id++;
1224 adpt_post_wait_id &= 0x7fff;
1225 wait_data->id = adpt_post_wait_id;
1226 spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
1227
1228 wait_data->wq = &adpt_wq_i2o_post;
1229 wait_data->status = -ETIMEDOUT;
1230
Andrew Morton4452ea52005-06-23 00:10:26 -07001231 add_wait_queue(&adpt_wq_i2o_post, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
1233 msg[2] |= 0x80000000 | ((u32)wait_data->id);
1234 timeout *= HZ;
1235 if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){
1236 set_current_state(TASK_INTERRUPTIBLE);
1237 if(pHba->host)
1238 spin_unlock_irq(pHba->host->host_lock);
1239 if (!timeout)
1240 schedule();
1241 else{
1242 timeout = schedule_timeout(timeout);
1243 if (timeout == 0) {
1244 // I/O issued, but cannot get result in
1245 // specified time. Freeing resorces is
1246 // dangerous.
1247 status = -ETIME;
1248 }
1249 }
1250 if(pHba->host)
1251 spin_lock_irq(pHba->host->host_lock);
1252 }
Andrew Morton4452ea52005-06-23 00:10:26 -07001253 remove_wait_queue(&adpt_wq_i2o_post, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254
1255 if(status == -ETIMEDOUT){
1256 printk(KERN_INFO"dpti%d: POST WAIT TIMEOUT\n",pHba->unit);
1257 // We will have to free the wait_data memory during shutdown
1258 return status;
1259 }
1260
1261 /* Remove the entry from the queue. */
1262 p2 = NULL;
1263 spin_lock_irqsave(&adpt_post_wait_lock, flags);
1264 for(p1 = adpt_post_wait_queue; p1; p2 = p1, p1 = p1->next) {
1265 if(p1 == wait_data) {
1266 if(p1->status == I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION ) {
1267 status = -EOPNOTSUPP;
1268 }
1269 if(p2) {
1270 p2->next = p1->next;
1271 } else {
1272 adpt_post_wait_queue = p1->next;
1273 }
1274 break;
1275 }
1276 }
1277 spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
1278
1279 kfree(wait_data);
1280
1281 return status;
1282}
1283
1284
1285static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len)
1286{
1287
1288 u32 m = EMPTY_QUEUE;
1289 u32 __iomem *msg;
1290 ulong timeout = jiffies + 30*HZ;
1291 do {
1292 rmb();
1293 m = readl(pHba->post_port);
1294 if (m != EMPTY_QUEUE) {
1295 break;
1296 }
1297 if(time_after(jiffies,timeout)){
1298 printk(KERN_WARNING"dpti%d: Timeout waiting for message frame!\n", pHba->unit);
1299 return -ETIMEDOUT;
1300 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001301 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 } while(m == EMPTY_QUEUE);
1303
1304 msg = pHba->msg_addr_virt + m;
1305 memcpy_toio(msg, data, len);
1306 wmb();
1307
1308 //post message
1309 writel(m, pHba->post_port);
1310 wmb();
1311
1312 return 0;
1313}
1314
1315
1316static void adpt_i2o_post_wait_complete(u32 context, int status)
1317{
1318 struct adpt_i2o_post_wait_data *p1 = NULL;
1319 /*
1320 * We need to search through the adpt_post_wait
1321 * queue to see if the given message is still
1322 * outstanding. If not, it means that the IOP
1323 * took longer to respond to the message than we
1324 * had allowed and timer has already expired.
1325 * Not much we can do about that except log
1326 * it for debug purposes, increase timeout, and recompile
1327 *
1328 * Lock needed to keep anyone from moving queue pointers
1329 * around while we're looking through them.
1330 */
1331
1332 context &= 0x7fff;
1333
1334 spin_lock(&adpt_post_wait_lock);
1335 for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) {
1336 if(p1->id == context) {
1337 p1->status = status;
1338 spin_unlock(&adpt_post_wait_lock);
1339 wake_up_interruptible(p1->wq);
1340 return;
1341 }
1342 }
1343 spin_unlock(&adpt_post_wait_lock);
1344 // If this happens we lose commands that probably really completed
1345 printk(KERN_DEBUG"dpti: Could Not find task %d in wait queue\n",context);
1346 printk(KERN_DEBUG" Tasks in wait queue:\n");
1347 for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) {
1348 printk(KERN_DEBUG" %d\n",p1->id);
1349 }
1350 return;
1351}
1352
1353static s32 adpt_i2o_reset_hba(adpt_hba* pHba)
1354{
1355 u32 msg[8];
1356 u8* status;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001357 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 u32 m = EMPTY_QUEUE ;
1359 ulong timeout = jiffies + (TMOUT_IOPRESET*HZ);
1360
1361 if(pHba->initialized == FALSE) { // First time reset should be quick
1362 timeout = jiffies + (25*HZ);
1363 } else {
1364 adpt_i2o_quiesce_hba(pHba);
1365 }
1366
1367 do {
1368 rmb();
1369 m = readl(pHba->post_port);
1370 if (m != EMPTY_QUEUE) {
1371 break;
1372 }
1373 if(time_after(jiffies,timeout)){
1374 printk(KERN_WARNING"Timeout waiting for message!\n");
1375 return -ETIMEDOUT;
1376 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001377 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 } while (m == EMPTY_QUEUE);
1379
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001380 status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 if(status == NULL) {
1382 adpt_send_nop(pHba, m);
1383 printk(KERN_ERR"IOP reset failed - no free memory.\n");
1384 return -ENOMEM;
1385 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001386 memset(status,0,4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
1388 msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
1389 msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
1390 msg[2]=0;
1391 msg[3]=0;
1392 msg[4]=0;
1393 msg[5]=0;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001394 msg[6]=dma_low(addr);
1395 msg[7]=dma_high(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
1397 memcpy_toio(pHba->msg_addr_virt+m, msg, sizeof(msg));
1398 wmb();
1399 writel(m, pHba->post_port);
1400 wmb();
1401
1402 while(*status == 0){
1403 if(time_after(jiffies,timeout)){
1404 printk(KERN_WARNING"%s: IOP Reset Timeout\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001405 /* We lose 4 bytes of "status" here, but we cannot
1406 free these because controller may awake and corrupt
1407 those bytes at any time */
1408 /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 return -ETIMEDOUT;
1410 }
1411 rmb();
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001412 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 }
1414
1415 if(*status == 0x01 /*I2O_EXEC_IOP_RESET_IN_PROGRESS*/) {
1416 PDEBUG("%s: Reset in progress...\n", pHba->name);
1417 // Here we wait for message frame to become available
1418 // indicated that reset has finished
1419 do {
1420 rmb();
1421 m = readl(pHba->post_port);
1422 if (m != EMPTY_QUEUE) {
1423 break;
1424 }
1425 if(time_after(jiffies,timeout)){
1426 printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001427 /* We lose 4 bytes of "status" here, but we
1428 cannot free these because controller may
1429 awake and corrupt those bytes at any time */
1430 /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 return -ETIMEDOUT;
1432 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001433 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 } while (m == EMPTY_QUEUE);
1435 // Flush the offset
1436 adpt_send_nop(pHba, m);
1437 }
1438 adpt_i2o_status_get(pHba);
1439 if(*status == 0x02 ||
1440 pHba->status_block->iop_state != ADAPTER_STATE_RESET) {
1441 printk(KERN_WARNING"%s: Reset reject, trying to clear\n",
1442 pHba->name);
1443 } else {
1444 PDEBUG("%s: Reset completed.\n", pHba->name);
1445 }
1446
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001447 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448#ifdef UARTDELAY
1449 // This delay is to allow someone attached to the card through the debug UART to
1450 // set up the dump levels that they want before the rest of the initialization sequence
1451 adpt_delay(20000);
1452#endif
1453 return 0;
1454}
1455
1456
1457static int adpt_i2o_parse_lct(adpt_hba* pHba)
1458{
1459 int i;
1460 int max;
1461 int tid;
1462 struct i2o_device *d;
1463 i2o_lct *lct = pHba->lct;
1464 u8 bus_no = 0;
1465 s16 scsi_id;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02001466 u64 scsi_lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 u32 buf[10]; // larger than 7, or 8 ...
1468 struct adpt_device* pDev;
1469
1470 if (lct == NULL) {
1471 printk(KERN_ERR "%s: LCT is empty???\n",pHba->name);
1472 return -1;
1473 }
1474
1475 max = lct->table_size;
1476 max -= 3;
1477 max /= 9;
1478
1479 for(i=0;i<max;i++) {
1480 if( lct->lct_entry[i].user_tid != 0xfff){
1481 /*
1482 * If we have hidden devices, we need to inform the upper layers about
1483 * the possible maximum id reference to handle device access when
1484 * an array is disassembled. This code has no other purpose but to
1485 * allow us future access to devices that are currently hidden
1486 * behind arrays, hotspares or have not been configured (JBOD mode).
1487 */
1488 if( lct->lct_entry[i].class_id != I2O_CLASS_RANDOM_BLOCK_STORAGE &&
1489 lct->lct_entry[i].class_id != I2O_CLASS_SCSI_PERIPHERAL &&
1490 lct->lct_entry[i].class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
1491 continue;
1492 }
1493 tid = lct->lct_entry[i].tid;
1494 // I2O_DPT_DEVICE_INFO_GROUP_NO;
1495 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) {
1496 continue;
1497 }
1498 bus_no = buf[0]>>16;
1499 scsi_id = buf[1];
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02001500 scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1502 printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no);
1503 continue;
1504 }
1505 if (scsi_id >= MAX_ID){
1506 printk(KERN_WARNING"%s: SCSI ID %d out of range \n", pHba->name, bus_no);
1507 continue;
1508 }
1509 if(bus_no > pHba->top_scsi_channel){
1510 pHba->top_scsi_channel = bus_no;
1511 }
1512 if(scsi_id > pHba->top_scsi_id){
1513 pHba->top_scsi_id = scsi_id;
1514 }
1515 if(scsi_lun > pHba->top_scsi_lun){
1516 pHba->top_scsi_lun = scsi_lun;
1517 }
1518 continue;
1519 }
Robert P. J. Day5cbded52006-12-13 00:35:56 -08001520 d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 if(d==NULL)
1522 {
1523 printk(KERN_CRIT"%s: Out of memory for I2O device data.\n",pHba->name);
1524 return -ENOMEM;
1525 }
1526
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07001527 d->controller = pHba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 d->next = NULL;
1529
1530 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
1531
1532 d->flags = 0;
1533 tid = d->lct_data.tid;
1534 adpt_i2o_report_hba_unit(pHba, d);
1535 adpt_i2o_install_device(pHba, d);
1536 }
1537 bus_no = 0;
1538 for(d = pHba->devices; d ; d = d->next) {
1539 if(d->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT ||
1540 d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PORT){
1541 tid = d->lct_data.tid;
1542 // TODO get the bus_no from hrt-but for now they are in order
1543 //bus_no =
1544 if(bus_no > pHba->top_scsi_channel){
1545 pHba->top_scsi_channel = bus_no;
1546 }
1547 pHba->channel[bus_no].type = d->lct_data.class_id;
1548 pHba->channel[bus_no].tid = tid;
1549 if(adpt_i2o_query_scalar(pHba, tid, 0x0200, -1, buf, 28)>=0)
1550 {
1551 pHba->channel[bus_no].scsi_id = buf[1];
1552 PDEBUG("Bus %d - SCSI ID %d.\n", bus_no, buf[1]);
1553 }
1554 // TODO remove - this is just until we get from hrt
1555 bus_no++;
1556 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1557 printk(KERN_WARNING"%s: Channel number %d out of range - LCT\n", pHba->name, bus_no);
1558 break;
1559 }
1560 }
1561 }
1562
1563 // Setup adpt_device table
1564 for(d = pHba->devices; d ; d = d->next) {
1565 if(d->lct_data.class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE ||
1566 d->lct_data.class_id == I2O_CLASS_SCSI_PERIPHERAL ||
1567 d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
1568
1569 tid = d->lct_data.tid;
1570 scsi_id = -1;
1571 // I2O_DPT_DEVICE_INFO_GROUP_NO;
1572 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)>=0) {
1573 bus_no = buf[0]>>16;
1574 scsi_id = buf[1];
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02001575 scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1577 continue;
1578 }
1579 if (scsi_id >= MAX_ID) {
1580 continue;
1581 }
1582 if( pHba->channel[bus_no].device[scsi_id] == NULL){
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301583 pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 if(pDev == NULL) {
1585 return -ENOMEM;
1586 }
1587 pHba->channel[bus_no].device[scsi_id] = pDev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 } else {
1589 for( pDev = pHba->channel[bus_no].device[scsi_id];
1590 pDev->next_lun; pDev = pDev->next_lun){
1591 }
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301592 pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 if(pDev->next_lun == NULL) {
1594 return -ENOMEM;
1595 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 pDev = pDev->next_lun;
1597 }
1598 pDev->tid = tid;
1599 pDev->scsi_channel = bus_no;
1600 pDev->scsi_id = scsi_id;
1601 pDev->scsi_lun = scsi_lun;
1602 pDev->pI2o_dev = d;
1603 d->owner = pDev;
1604 pDev->type = (buf[0])&0xff;
1605 pDev->flags = (buf[0]>>8)&0xff;
1606 if(scsi_id > pHba->top_scsi_id){
1607 pHba->top_scsi_id = scsi_id;
1608 }
1609 if(scsi_lun > pHba->top_scsi_lun){
1610 pHba->top_scsi_lun = scsi_lun;
1611 }
1612 }
1613 if(scsi_id == -1){
1614 printk(KERN_WARNING"Could not find SCSI ID for %s\n",
1615 d->lct_data.identity_tag);
1616 }
1617 }
1618 }
1619 return 0;
1620}
1621
1622
1623/*
1624 * Each I2O controller has a chain of devices on it - these match
1625 * the useful parts of the LCT of the board.
1626 */
1627
1628static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d)
1629{
Arjan van de Ven0b950672006-01-11 13:16:10 +01001630 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 d->controller=pHba;
1632 d->owner=NULL;
1633 d->next=pHba->devices;
1634 d->prev=NULL;
1635 if (pHba->devices != NULL){
1636 pHba->devices->prev=d;
1637 }
1638 pHba->devices=d;
1639 *d->dev_name = 0;
1640
Arjan van de Ven0b950672006-01-11 13:16:10 +01001641 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 return 0;
1643}
1644
1645static int adpt_open(struct inode *inode, struct file *file)
1646{
1647 int minor;
1648 adpt_hba* pHba;
1649
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02001650 mutex_lock(&adpt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 //TODO check for root access
1652 //
1653 minor = iminor(inode);
1654 if (minor >= hba_count) {
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02001655 mutex_unlock(&adpt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 return -ENXIO;
1657 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001658 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1660 if (pHba->unit == minor) {
1661 break; /* found adapter */
1662 }
1663 }
1664 if (pHba == NULL) {
Arjan van de Ven0b950672006-01-11 13:16:10 +01001665 mutex_unlock(&adpt_configuration_lock);
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02001666 mutex_unlock(&adpt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 return -ENXIO;
1668 }
1669
1670// if(pHba->in_use){
Arjan van de Ven0b950672006-01-11 13:16:10 +01001671 // mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672// return -EBUSY;
1673// }
1674
1675 pHba->in_use = 1;
Arjan van de Ven0b950672006-01-11 13:16:10 +01001676 mutex_unlock(&adpt_configuration_lock);
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02001677 mutex_unlock(&adpt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
1679 return 0;
1680}
1681
1682static int adpt_close(struct inode *inode, struct file *file)
1683{
1684 int minor;
1685 adpt_hba* pHba;
1686
1687 minor = iminor(inode);
1688 if (minor >= hba_count) {
1689 return -ENXIO;
1690 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001691 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1693 if (pHba->unit == minor) {
1694 break; /* found adapter */
1695 }
1696 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001697 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 if (pHba == NULL) {
1699 return -ENXIO;
1700 }
1701
1702 pHba->in_use = 0;
1703
1704 return 0;
1705}
1706
1707
1708static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
1709{
1710 u32 msg[MAX_MESSAGE_SIZE];
1711 u32* reply = NULL;
1712 u32 size = 0;
1713 u32 reply_size = 0;
1714 u32 __user *user_msg = arg;
1715 u32 __user * user_reply = NULL;
1716 void *sg_list[pHba->sg_tablesize];
1717 u32 sg_offset = 0;
1718 u32 sg_count = 0;
1719 int sg_index = 0;
1720 u32 i = 0;
1721 u32 rcode = 0;
1722 void *p = NULL;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001723 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 ulong flags = 0;
1725
1726 memset(&msg, 0, MAX_MESSAGE_SIZE*4);
1727 // get user msg size in u32s
1728 if(get_user(size, &user_msg[0])){
1729 return -EFAULT;
1730 }
1731 size = size>>16;
1732
1733 user_reply = &user_msg[size];
1734 if(size > MAX_MESSAGE_SIZE){
1735 return -EFAULT;
1736 }
1737 size *= 4; // Convert to bytes
1738
1739 /* Copy in the user's I2O command */
1740 if(copy_from_user(msg, user_msg, size)) {
1741 return -EFAULT;
1742 }
1743 get_user(reply_size, &user_reply[0]);
1744 reply_size = reply_size>>16;
1745 if(reply_size > REPLY_FRAME_SIZE){
1746 reply_size = REPLY_FRAME_SIZE;
1747 }
1748 reply_size *= 4;
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301749 reply = kzalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 if(reply == NULL) {
1751 printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name);
1752 return -ENOMEM;
1753 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 sg_offset = (msg[0]>>4)&0xf;
1755 msg[2] = 0x40000000; // IOCTL context
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001756 msg[3] = adpt_ioctl_to_context(pHba, reply);
Quentin Lambert021e2922016-11-19 18:42:34 +01001757 if (msg[3] == (u32)-1) {
1758 kfree(reply);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001759 return -EBUSY;
Quentin Lambert021e2922016-11-19 18:42:34 +01001760 }
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001761
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 memset(sg_list,0, sizeof(sg_list[0])*pHba->sg_tablesize);
1763 if(sg_offset) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001764 // TODO add 64 bit API
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 struct sg_simple_element *sg = (struct sg_simple_element*) (msg+sg_offset);
1766 sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
1767 if (sg_count > pHba->sg_tablesize){
1768 printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", pHba->name,sg_count);
1769 kfree (reply);
1770 return -EINVAL;
1771 }
1772
1773 for(i = 0; i < sg_count; i++) {
1774 int sg_size;
1775
1776 if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) {
1777 printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",pHba->name,i, sg[i].flag_count);
1778 rcode = -EINVAL;
1779 goto cleanup;
1780 }
1781 sg_size = sg[i].flag_count & 0xffffff;
1782 /* Allocate memory for the transfer */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001783 p = dma_alloc_coherent(&pHba->pDev->dev, sg_size, &addr, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 if(!p) {
1785 printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
1786 pHba->name,sg_size,i,sg_count);
1787 rcode = -ENOMEM;
1788 goto cleanup;
1789 }
1790 sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
1791 /* Copy in the user's SG buffer if necessary */
1792 if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001793 // sg_simple_element API is 32 bit
1794 if (copy_from_user(p,(void __user *)(ulong)sg[i].addr_bus, sg_size)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",pHba->name,i);
1796 rcode = -EFAULT;
1797 goto cleanup;
1798 }
1799 }
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001800 /* sg_simple_element API is 32 bit, but addr < 4GB */
1801 sg[i].addr_bus = addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 }
1803 }
1804
1805 do {
Hannes Reinecke1f8c88c2013-10-23 10:51:15 +02001806 /*
1807 * Stop any new commands from enterring the
1808 * controller while processing the ioctl
1809 */
1810 if (pHba->host) {
1811 scsi_block_requests(pHba->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 spin_lock_irqsave(pHba->host->host_lock, flags);
Hannes Reinecke1f8c88c2013-10-23 10:51:15 +02001813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER);
1815 if (rcode != 0)
1816 printk("adpt_i2o_passthru: post wait failed %d %p\n",
1817 rcode, reply);
Hannes Reinecke1f8c88c2013-10-23 10:51:15 +02001818 if (pHba->host) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 spin_unlock_irqrestore(pHba->host->host_lock, flags);
Hannes Reinecke1f8c88c2013-10-23 10:51:15 +02001820 scsi_unblock_requests(pHba->host);
1821 }
1822 } while (rcode == -ETIMEDOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
1824 if(rcode){
1825 goto cleanup;
1826 }
1827
1828 if(sg_offset) {
1829 /* Copy back the Scatter Gather buffers back to user space */
1830 u32 j;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001831 // TODO add 64 bit API
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 struct sg_simple_element* sg;
1833 int sg_size;
1834
1835 // re-acquire the original message to handle correctly the sg copy operation
1836 memset(&msg, 0, MAX_MESSAGE_SIZE*4);
1837 // get user msg size in u32s
1838 if(get_user(size, &user_msg[0])){
1839 rcode = -EFAULT;
1840 goto cleanup;
1841 }
1842 size = size>>16;
1843 size *= 4;
Alan Coxef7562b2009-10-27 15:35:35 +00001844 if (size > MAX_MESSAGE_SIZE) {
OGAWA Hirofumiaefba412009-10-30 17:02:31 +09001845 rcode = -EINVAL;
Alan Coxef7562b2009-10-27 15:35:35 +00001846 goto cleanup;
1847 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 /* Copy in the user's I2O command */
1849 if (copy_from_user (msg, user_msg, size)) {
1850 rcode = -EFAULT;
1851 goto cleanup;
1852 }
1853 sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
1854
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001855 // TODO add 64 bit API
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 sg = (struct sg_simple_element*)(msg + sg_offset);
1857 for (j = 0; j < sg_count; j++) {
1858 /* Copy out the SG list to user's buffer if necessary */
1859 if(! (sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) {
1860 sg_size = sg[j].flag_count & 0xffffff;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001861 // sg_simple_element API is 32 bit
1862 if (copy_to_user((void __user *)(ulong)sg[j].addr_bus,sg_list[j], sg_size)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",pHba->name, sg_list[j], sg[j].addr_bus);
1864 rcode = -EFAULT;
1865 goto cleanup;
1866 }
1867 }
1868 }
1869 }
1870
1871 /* Copy back the reply to user space */
1872 if (reply_size) {
1873 // we wrote our own values for context - now restore the user supplied ones
1874 if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) {
1875 printk(KERN_WARNING"%s: Could not copy message context FROM user\n",pHba->name);
1876 rcode = -EFAULT;
1877 }
1878 if(copy_to_user(user_reply, reply, reply_size)) {
1879 printk(KERN_WARNING"%s: Could not copy reply TO user\n",pHba->name);
1880 rcode = -EFAULT;
1881 }
1882 }
1883
1884
1885cleanup:
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001886 if (rcode != -ETIME && rcode != -EINTR) {
1887 struct sg_simple_element *sg =
1888 (struct sg_simple_element*) (msg +sg_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 kfree (reply);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001890 while(sg_index) {
1891 if(sg_list[--sg_index]) {
1892 dma_free_coherent(&pHba->pDev->dev,
1893 sg[sg_index].flag_count & 0xffffff,
1894 sg_list[sg_index],
1895 sg[sg_index].addr_bus);
1896 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 }
1898 }
1899 return rcode;
1900}
1901
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902#if defined __ia64__
1903static void adpt_ia64_info(sysInfo_S* si)
1904{
1905 // This is all the info we need for now
1906 // We will add more info as our new
1907 // managmenent utility requires it
1908 si->processorType = PROC_IA64;
1909}
1910#endif
1911
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912#if defined __sparc__
1913static void adpt_sparc_info(sysInfo_S* si)
1914{
1915 // This is all the info we need for now
1916 // We will add more info as our new
1917 // managmenent utility requires it
1918 si->processorType = PROC_ULTRASPARC;
1919}
1920#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921#if defined __alpha__
1922static void adpt_alpha_info(sysInfo_S* si)
1923{
1924 // This is all the info we need for now
1925 // We will add more info as our new
1926 // managmenent utility requires it
1927 si->processorType = PROC_ALPHA;
1928}
1929#endif
1930
1931#if defined __i386__
Brian Gerstba3e1272015-07-29 01:41:21 -04001932
1933#include <uapi/asm/vm86.h>
1934
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935static void adpt_i386_info(sysInfo_S* si)
1936{
1937 // This is all the info we need for now
1938 // We will add more info as our new
1939 // managmenent utility requires it
1940 switch (boot_cpu_data.x86) {
1941 case CPU_386:
1942 si->processorType = PROC_386;
1943 break;
1944 case CPU_486:
1945 si->processorType = PROC_486;
1946 break;
1947 case CPU_586:
1948 si->processorType = PROC_PENTIUM;
1949 break;
1950 default: // Just in case
1951 si->processorType = PROC_PENTIUM;
1952 break;
1953 }
1954}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955#endif
1956
Andrew Morton8b2cc912008-05-06 20:42:42 -07001957/*
1958 * This routine returns information about the system. This does not effect
1959 * any logic and if the info is wrong - it doesn't matter.
1960 */
1961
1962/* Get all the info we can not get from kernel services */
1963static int adpt_system_info(void __user *buffer)
1964{
1965 sysInfo_S si;
1966
1967 memset(&si, 0, sizeof(si));
1968
1969 si.osType = OS_LINUX;
1970 si.osMajorVersion = 0;
1971 si.osMinorVersion = 0;
1972 si.osRevision = 0;
1973 si.busType = SI_PCI_BUS;
1974 si.processorFamily = DPTI_sig.dsProcessorFamily;
1975
1976#if defined __i386__
1977 adpt_i386_info(&si);
1978#elif defined (__ia64__)
1979 adpt_ia64_info(&si);
1980#elif defined(__sparc__)
1981 adpt_sparc_info(&si);
1982#elif defined (__alpha__)
1983 adpt_alpha_info(&si);
1984#else
1985 si.processorType = 0xff ;
1986#endif
1987 if (copy_to_user(buffer, &si, sizeof(si))){
1988 printk(KERN_WARNING"dpti: Could not copy buffer TO user\n");
1989 return -EFAULT;
1990 }
1991
1992 return 0;
1993}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
Arnd Bergmannf4927c42010-04-27 00:24:01 +02001995static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996{
1997 int minor;
1998 int error = 0;
1999 adpt_hba* pHba;
2000 ulong flags = 0;
2001 void __user *argp = (void __user *)arg;
2002
2003 minor = iminor(inode);
2004 if (minor >= DPTI_MAX_HBA){
2005 return -ENXIO;
2006 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01002007 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 for (pHba = hba_chain; pHba; pHba = pHba->next) {
2009 if (pHba->unit == minor) {
2010 break; /* found adapter */
2011 }
2012 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01002013 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 if(pHba == NULL){
2015 return -ENXIO;
2016 }
2017
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002018 while((volatile u32) pHba->state & DPTI_STATE_RESET )
2019 schedule_timeout_uninterruptible(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
2021 switch (cmd) {
2022 // TODO: handle 3 cases
2023 case DPT_SIGNATURE:
2024 if (copy_to_user(argp, &DPTI_sig, sizeof(DPTI_sig))) {
2025 return -EFAULT;
2026 }
2027 break;
2028 case I2OUSRCMD:
2029 return adpt_i2o_passthru(pHba, argp);
2030
2031 case DPT_CTRLINFO:{
2032 drvrHBAinfo_S HbaInfo;
2033
2034#define FLG_OSD_PCI_VALID 0x0001
2035#define FLG_OSD_DMA 0x0002
2036#define FLG_OSD_I2O 0x0004
2037 memset(&HbaInfo, 0, sizeof(HbaInfo));
2038 HbaInfo.drvrHBAnum = pHba->unit;
2039 HbaInfo.baseAddr = (ulong) pHba->base_addr_phys;
2040 HbaInfo.blinkState = adpt_read_blink_led(pHba);
2041 HbaInfo.pciBusNum = pHba->pDev->bus->number;
2042 HbaInfo.pciDeviceNum=PCI_SLOT(pHba->pDev->devfn);
2043 HbaInfo.Interrupt = pHba->pDev->irq;
2044 HbaInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O;
2045 if(copy_to_user(argp, &HbaInfo, sizeof(HbaInfo))){
2046 printk(KERN_WARNING"%s: Could not copy HbaInfo TO user\n",pHba->name);
2047 return -EFAULT;
2048 }
2049 break;
2050 }
2051 case DPT_SYSINFO:
2052 return adpt_system_info(argp);
2053 case DPT_BLINKLED:{
2054 u32 value;
2055 value = (u32)adpt_read_blink_led(pHba);
2056 if (copy_to_user(argp, &value, sizeof(value))) {
2057 return -EFAULT;
2058 }
2059 break;
2060 }
2061 case I2ORESETCMD:
2062 if(pHba->host)
2063 spin_lock_irqsave(pHba->host->host_lock, flags);
2064 adpt_hba_reset(pHba);
2065 if(pHba->host)
2066 spin_unlock_irqrestore(pHba->host->host_lock, flags);
2067 break;
2068 case I2ORESCANCMD:
2069 adpt_rescan(pHba);
2070 break;
2071 default:
2072 return -EINVAL;
2073 }
2074
2075 return error;
2076}
2077
Arnd Bergmannf4927c42010-04-27 00:24:01 +02002078static long adpt_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
2079{
2080 struct inode *inode;
2081 long ret;
2082
Al Viro496ad9a2013-01-23 17:07:38 -05002083 inode = file_inode(file);
Arnd Bergmannf4927c42010-04-27 00:24:01 +02002084
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02002085 mutex_lock(&adpt_mutex);
Arnd Bergmannf4927c42010-04-27 00:24:01 +02002086 ret = adpt_ioctl(inode, file, cmd, arg);
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02002087 mutex_unlock(&adpt_mutex);
Arnd Bergmannf4927c42010-04-27 00:24:01 +02002088
2089 return ret;
2090}
2091
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002092#ifdef CONFIG_COMPAT
2093static long compat_adpt_ioctl(struct file *file,
2094 unsigned int cmd, unsigned long arg)
2095{
2096 struct inode *inode;
2097 long ret;
2098
Al Viro496ad9a2013-01-23 17:07:38 -05002099 inode = file_inode(file);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002100
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02002101 mutex_lock(&adpt_mutex);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002102
2103 switch(cmd) {
2104 case DPT_SIGNATURE:
2105 case I2OUSRCMD:
2106 case DPT_CTRLINFO:
2107 case DPT_SYSINFO:
2108 case DPT_BLINKLED:
2109 case I2ORESETCMD:
2110 case I2ORESCANCMD:
2111 case (DPT_TARGET_BUSY & 0xFFFF):
2112 case DPT_TARGET_BUSY:
2113 ret = adpt_ioctl(inode, file, cmd, arg);
2114 break;
2115 default:
2116 ret = -ENOIOCTLCMD;
2117 }
2118
Arnd Bergmannc45d15d2010-06-02 14:28:52 +02002119 mutex_unlock(&adpt_mutex);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002120
2121 return ret;
2122}
2123#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124
David Howells7d12e782006-10-05 14:55:46 +01002125static irqreturn_t adpt_isr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126{
2127 struct scsi_cmnd* cmd;
2128 adpt_hba* pHba = dev_id;
2129 u32 m;
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002130 void __iomem *reply;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 u32 status=0;
2132 u32 context;
2133 ulong flags = 0;
2134 int handled = 0;
2135
2136 if (pHba == NULL){
2137 printk(KERN_WARNING"adpt_isr: NULL dev_id\n");
2138 return IRQ_NONE;
2139 }
2140 if(pHba->host)
2141 spin_lock_irqsave(pHba->host->host_lock, flags);
2142
2143 while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) {
2144 m = readl(pHba->reply_port);
2145 if(m == EMPTY_QUEUE){
2146 // Try twice then give up
2147 rmb();
2148 m = readl(pHba->reply_port);
2149 if(m == EMPTY_QUEUE){
2150 // This really should not happen
2151 printk(KERN_ERR"dpti: Could not get reply frame\n");
2152 goto out;
2153 }
2154 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002155 if (pHba->reply_pool_pa <= m &&
2156 m < pHba->reply_pool_pa +
2157 (pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4)) {
2158 reply = (u8 *)pHba->reply_pool +
2159 (m - pHba->reply_pool_pa);
2160 } else {
2161 /* Ick, we should *never* be here */
2162 printk(KERN_ERR "dpti: reply frame not from pool\n");
2163 reply = (u8 *)bus_to_virt(m);
2164 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165
2166 if (readl(reply) & MSG_FAIL) {
2167 u32 old_m = readl(reply+28);
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002168 void __iomem *msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 u32 old_context;
2170 PDEBUG("%s: Failed message\n",pHba->name);
2171 if(old_m >= 0x100000){
2172 printk(KERN_ERR"%s: Bad preserved MFA (%x)- dropping frame\n",pHba->name,old_m);
2173 writel(m,pHba->reply_port);
2174 continue;
2175 }
2176 // Transaction context is 0 in failed reply frame
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002177 msg = pHba->msg_addr_virt + old_m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 old_context = readl(msg+12);
2179 writel(old_context, reply+12);
2180 adpt_send_nop(pHba, old_m);
2181 }
2182 context = readl(reply+8);
2183 if(context & 0x40000000){ // IOCTL
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002184 void *p = adpt_ioctl_from_context(pHba, readl(reply+12));
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002185 if( p != NULL) {
2186 memcpy_fromio(p, reply, REPLY_FRAME_SIZE * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 }
2188 // All IOCTLs will also be post wait
2189 }
2190 if(context & 0x80000000){ // Post wait message
2191 status = readl(reply+16);
2192 if(status >> 24){
2193 status &= 0xffff; /* Get detail status */
2194 } else {
2195 status = I2O_POST_WAIT_OK;
2196 }
2197 if(!(context & 0x40000000)) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002198 cmd = adpt_cmd_from_context(pHba,
2199 readl(reply+12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 if(cmd != NULL) {
2201 printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context);
2202 }
2203 }
2204 adpt_i2o_post_wait_complete(context, status);
2205 } else { // SCSI message
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002206 cmd = adpt_cmd_from_context (pHba, readl(reply+12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 if(cmd != NULL){
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002208 scsi_dma_unmap(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 if(cmd->serial_number != 0) { // If not timedout
2210 adpt_i2o_to_scsi(reply, cmd);
2211 }
2212 }
2213 }
2214 writel(m, pHba->reply_port);
2215 wmb();
2216 rmb();
2217 }
2218 handled = 1;
2219out: if(pHba->host)
2220 spin_unlock_irqrestore(pHba->host->host_lock, flags);
2221 return IRQ_RETVAL(handled);
2222}
2223
2224static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* d)
2225{
2226 int i;
2227 u32 msg[MAX_MESSAGE_SIZE];
2228 u32* mptr;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002229 u32* lptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 u32 *lenptr;
2231 int direction;
2232 int scsidir;
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002233 int nseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 u32 len;
2235 u32 reqlen;
2236 s32 rcode;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002237 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238
2239 memset(msg, 0 , sizeof(msg));
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002240 len = scsi_bufflen(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 direction = 0x00000000;
2242
2243 scsidir = 0x00000000; // DATA NO XFER
2244 if(len) {
2245 /*
2246 * Set SCBFlags to indicate if data is being transferred
2247 * in or out, or no data transfer
2248 * Note: Do not have to verify index is less than 0 since
2249 * cmd->cmnd[0] is an unsigned char
2250 */
2251 switch(cmd->sc_data_direction){
2252 case DMA_FROM_DEVICE:
2253 scsidir =0x40000000; // DATA IN (iop<--dev)
2254 break;
2255 case DMA_TO_DEVICE:
2256 direction=0x04000000; // SGL OUT
2257 scsidir =0x80000000; // DATA OUT (iop-->dev)
2258 break;
2259 case DMA_NONE:
2260 break;
2261 case DMA_BIDIRECTIONAL:
2262 scsidir =0x40000000; // DATA IN (iop<--dev)
2263 // Assume In - and continue;
2264 break;
2265 default:
2266 printk(KERN_WARNING"%s: scsi opcode 0x%x not supported.\n",
2267 pHba->name, cmd->cmnd[0]);
2268 cmd->result = (DID_OK <<16) | (INITIATOR_ERROR << 8);
2269 cmd->scsi_done(cmd);
2270 return 0;
2271 }
2272 }
2273 // msg[0] is set later
2274 // I2O_CMD_SCSI_EXEC
2275 msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid);
2276 msg[2] = 0;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002277 msg[3] = adpt_cmd_to_context(cmd); /* Want SCSI control block back */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 // Our cards use the transaction context as the tag for queueing
2279 // Adaptec/DPT Private stuff
2280 msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16);
2281 msg[5] = d->tid;
2282 /* Direction, disconnect ok | sense data | simple queue , CDBLen */
2283 // I2O_SCB_FLAG_ENABLE_DISCONNECT |
2284 // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG |
2285 // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;
2286 msg[6] = scsidir|0x20a00000|cmd->cmd_len;
2287
2288 mptr=msg+7;
2289
2290 // Write SCSI command into the message - always 16 byte block
2291 memset(mptr, 0, 16);
2292 memcpy(mptr, cmd->cmnd, cmd->cmd_len);
2293 mptr+=4;
2294 lenptr=mptr++; /* Remember me - fill in when we know */
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002295 if (dpt_dma64(pHba)) {
2296 reqlen = 16; // SINGLE SGE
2297 *mptr++ = (0x7C<<24)+(2<<16)+0x02; /* Enable 64 bit */
2298 *mptr++ = 1 << PAGE_SHIFT;
2299 } else {
2300 reqlen = 14; // SINGLE SGE
2301 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 /* Now fill in the SGList and command */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002304 nseg = scsi_dma_map(cmd);
2305 BUG_ON(nseg < 0);
2306 if (nseg) {
2307 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
2309 len = 0;
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002310 scsi_for_each_sg(cmd, sg, nseg, i) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002311 lptr = mptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 *mptr++ = direction|0x10000000|sg_dma_len(sg);
2313 len+=sg_dma_len(sg);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002314 addr = sg_dma_address(sg);
2315 *mptr++ = dma_low(addr);
2316 if (dpt_dma64(pHba))
2317 *mptr++ = dma_high(addr);
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002318 /* Make this an end of list */
2319 if (i == nseg - 1)
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002320 *lptr = direction|0xD0000000|sg_dma_len(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 reqlen = mptr - msg;
2323 *lenptr = len;
2324
2325 if(cmd->underflow && len != cmd->underflow){
2326 printk(KERN_WARNING"Cmd len %08X Cmd underflow %08X\n",
2327 len, cmd->underflow);
2328 }
2329 } else {
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002330 *lenptr = len = 0;
2331 reqlen = 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 }
2333
2334 /* Stick the headers on */
2335 msg[0] = reqlen<<16 | ((reqlen > 12) ? SGL_OFFSET_12 : SGL_OFFSET_0);
2336
2337 // Send it on it's way
2338 rcode = adpt_i2o_post_this(pHba, msg, reqlen<<2);
2339 if (rcode == 0) {
2340 return 0;
2341 }
2342 return rcode;
2343}
2344
2345
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002346static s32 adpt_scsi_host_alloc(adpt_hba* pHba, struct scsi_host_template *sht)
Andrew Morton24601bb2007-12-10 15:49:20 -08002347{
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002348 struct Scsi_Host *host;
Andrew Morton24601bb2007-12-10 15:49:20 -08002349
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002350 host = scsi_host_alloc(sht, sizeof(adpt_hba*));
Andrew Morton24601bb2007-12-10 15:49:20 -08002351 if (host == NULL) {
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002352 printk("%s: scsi_host_alloc returned NULL\n", pHba->name);
Andrew Morton24601bb2007-12-10 15:49:20 -08002353 return -1;
2354 }
2355 host->hostdata[0] = (unsigned long)pHba;
2356 pHba->host = host;
2357
2358 host->irq = pHba->pDev->irq;
2359 /* no IO ports, so don't have to set host->io_port and
2360 * host->n_io_port
2361 */
2362 host->io_port = 0;
2363 host->n_io_port = 0;
2364 /* see comments in scsi_host.h */
2365 host->max_id = 16;
2366 host->max_lun = 256;
2367 host->max_channel = pHba->top_scsi_channel + 1;
2368 host->cmd_per_lun = 1;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002369 host->unique_id = (u32)sys_tbl_pa + pHba->unit;
Andrew Morton24601bb2007-12-10 15:49:20 -08002370 host->sg_tablesize = pHba->sg_tablesize;
2371 host->can_queue = pHba->post_fifo_size;
Kashyap.Desai@avagotech.com64bdcbc2014-08-20 19:24:33 +05302372 host->use_cmd_list = 1;
Andrew Morton24601bb2007-12-10 15:49:20 -08002373
2374 return 0;
2375}
2376
2377
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002378static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379{
2380 adpt_hba* pHba;
2381 u32 hba_status;
2382 u32 dev_status;
2383 u32 reply_flags = readl(reply) & 0xff00; // Leave it shifted up 8 bits
2384 // I know this would look cleaner if I just read bytes
2385 // but the model I have been using for all the rest of the
2386 // io is in 4 byte words - so I keep that model
2387 u16 detailed_status = readl(reply+16) &0xffff;
2388 dev_status = (detailed_status & 0xff);
2389 hba_status = detailed_status >> 8;
2390
2391 // calculate resid for sg
Miquel van Smoorenburgdf81d232008-11-05 00:09:12 +01002392 scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+20));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393
2394 pHba = (adpt_hba*) cmd->device->host->hostdata[0];
2395
2396 cmd->sense_buffer[0] = '\0'; // initialize sense valid flag to false
2397
2398 if(!(reply_flags & MSG_FAIL)) {
2399 switch(detailed_status & I2O_SCSI_DSC_MASK) {
2400 case I2O_SCSI_DSC_SUCCESS:
2401 cmd->result = (DID_OK << 16);
2402 // handle underflow
Miquel van Smoorenburgdf81d232008-11-05 00:09:12 +01002403 if (readl(reply+20) < cmd->underflow) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 cmd->result = (DID_ERROR <<16);
2405 printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name);
2406 }
2407 break;
2408 case I2O_SCSI_DSC_REQUEST_ABORTED:
2409 cmd->result = (DID_ABORT << 16);
2410 break;
2411 case I2O_SCSI_DSC_PATH_INVALID:
2412 case I2O_SCSI_DSC_DEVICE_NOT_PRESENT:
2413 case I2O_SCSI_DSC_SELECTION_TIMEOUT:
2414 case I2O_SCSI_DSC_COMMAND_TIMEOUT:
2415 case I2O_SCSI_DSC_NO_ADAPTER:
2416 case I2O_SCSI_DSC_RESOURCE_UNAVAILABLE:
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002417 printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%llu) hba status=0x%x, dev status=0x%x, cmd=0x%x\n",
2418 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 -07002419 cmd->result = (DID_TIME_OUT << 16);
2420 break;
2421 case I2O_SCSI_DSC_ADAPTER_BUSY:
2422 case I2O_SCSI_DSC_BUS_BUSY:
2423 cmd->result = (DID_BUS_BUSY << 16);
2424 break;
2425 case I2O_SCSI_DSC_SCSI_BUS_RESET:
2426 case I2O_SCSI_DSC_BDR_MESSAGE_SENT:
2427 cmd->result = (DID_RESET << 16);
2428 break;
2429 case I2O_SCSI_DSC_PARITY_ERROR_FAILURE:
2430 printk(KERN_WARNING"%s: SCSI CMD parity error\n",pHba->name);
2431 cmd->result = (DID_PARITY << 16);
2432 break;
2433 case I2O_SCSI_DSC_UNABLE_TO_ABORT:
2434 case I2O_SCSI_DSC_COMPLETE_WITH_ERROR:
2435 case I2O_SCSI_DSC_UNABLE_TO_TERMINATE:
2436 case I2O_SCSI_DSC_MR_MESSAGE_RECEIVED:
2437 case I2O_SCSI_DSC_AUTOSENSE_FAILED:
2438 case I2O_SCSI_DSC_DATA_OVERRUN:
2439 case I2O_SCSI_DSC_UNEXPECTED_BUS_FREE:
2440 case I2O_SCSI_DSC_SEQUENCE_FAILURE:
2441 case I2O_SCSI_DSC_REQUEST_LENGTH_ERROR:
2442 case I2O_SCSI_DSC_PROVIDE_FAILURE:
2443 case I2O_SCSI_DSC_REQUEST_TERMINATED:
2444 case I2O_SCSI_DSC_IDE_MESSAGE_SENT:
2445 case I2O_SCSI_DSC_UNACKNOWLEDGED_EVENT:
2446 case I2O_SCSI_DSC_MESSAGE_RECEIVED:
2447 case I2O_SCSI_DSC_INVALID_CDB:
2448 case I2O_SCSI_DSC_LUN_INVALID:
2449 case I2O_SCSI_DSC_SCSI_TID_INVALID:
2450 case I2O_SCSI_DSC_FUNCTION_UNAVAILABLE:
2451 case I2O_SCSI_DSC_NO_NEXUS:
2452 case I2O_SCSI_DSC_CDB_RECEIVED:
2453 case I2O_SCSI_DSC_LUN_ALREADY_ENABLED:
2454 case I2O_SCSI_DSC_QUEUE_FROZEN:
2455 case I2O_SCSI_DSC_REQUEST_INVALID:
2456 default:
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002457 printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
2458 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 -07002459 hba_status, dev_status, cmd->cmnd[0]);
2460 cmd->result = (DID_ERROR << 16);
2461 break;
2462 }
2463
2464 // copy over the request sense data if it was a check
2465 // condition status
Salyzyn, Markd814c512008-01-14 11:04:40 -08002466 if (dev_status == SAM_STAT_CHECK_CONDITION) {
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +09002467 u32 len = min(SCSI_SENSE_BUFFERSIZE, 40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 // Copy over the sense data
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002469 memcpy_fromio(cmd->sense_buffer, (reply+28) , len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 if(cmd->sense_buffer[0] == 0x70 /* class 7 */ &&
2471 cmd->sense_buffer[2] == DATA_PROTECT ){
2472 /* This is to handle an array failed */
2473 cmd->result = (DID_TIME_OUT << 16);
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002474 printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
2475 pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 hba_status, dev_status, cmd->cmnd[0]);
2477
2478 }
2479 }
2480 } else {
2481 /* In this condtion we could not talk to the tid
2482 * the card rejected it. We should signal a retry
2483 * for a limitted number of retries.
2484 */
2485 cmd->result = (DID_TIME_OUT << 16);
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002486 printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%llu) tid=%d, cmd=0x%x\n",
2487 pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 ((struct adpt_device*)(cmd->device->hostdata))->tid, cmd->cmnd[0]);
2489 }
2490
2491 cmd->result |= (dev_status);
2492
2493 if(cmd->scsi_done != NULL){
2494 cmd->scsi_done(cmd);
2495 }
2496 return cmd->result;
2497}
2498
2499
2500static s32 adpt_rescan(adpt_hba* pHba)
2501{
2502 s32 rcode;
2503 ulong flags = 0;
2504
2505 if(pHba->host)
2506 spin_lock_irqsave(pHba->host->host_lock, flags);
2507 if ((rcode=adpt_i2o_lct_get(pHba)) < 0)
2508 goto out;
2509 if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0)
2510 goto out;
2511 rcode = 0;
2512out: if(pHba->host)
2513 spin_unlock_irqrestore(pHba->host->host_lock, flags);
2514 return rcode;
2515}
2516
2517
2518static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
2519{
2520 int i;
2521 int max;
2522 int tid;
2523 struct i2o_device *d;
2524 i2o_lct *lct = pHba->lct;
2525 u8 bus_no = 0;
2526 s16 scsi_id;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002527 u64 scsi_lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 u32 buf[10]; // at least 8 u32's
2529 struct adpt_device* pDev = NULL;
2530 struct i2o_device* pI2o_dev = NULL;
2531
2532 if (lct == NULL) {
2533 printk(KERN_ERR "%s: LCT is empty???\n",pHba->name);
2534 return -1;
2535 }
2536
2537 max = lct->table_size;
2538 max -= 3;
2539 max /= 9;
2540
2541 // Mark each drive as unscanned
2542 for (d = pHba->devices; d; d = d->next) {
2543 pDev =(struct adpt_device*) d->owner;
2544 if(!pDev){
2545 continue;
2546 }
2547 pDev->state |= DPTI_DEV_UNSCANNED;
2548 }
2549
2550 printk(KERN_INFO "%s: LCT has %d entries.\n", pHba->name,max);
2551
2552 for(i=0;i<max;i++) {
2553 if( lct->lct_entry[i].user_tid != 0xfff){
2554 continue;
2555 }
2556
2557 if( lct->lct_entry[i].class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE ||
2558 lct->lct_entry[i].class_id == I2O_CLASS_SCSI_PERIPHERAL ||
2559 lct->lct_entry[i].class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
2560 tid = lct->lct_entry[i].tid;
2561 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) {
2562 printk(KERN_ERR"%s: Could not query device\n",pHba->name);
2563 continue;
2564 }
2565 bus_no = buf[0]>>16;
Dan Carpentere84d96d2010-07-15 10:20:19 +02002566 if (bus_no >= MAX_CHANNEL) { /* Something wrong skip it */
2567 printk(KERN_WARNING
2568 "%s: Channel number %d out of range\n",
2569 pHba->name, bus_no);
2570 continue;
2571 }
2572
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 scsi_id = buf[1];
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002574 scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 pDev = pHba->channel[bus_no].device[scsi_id];
2576 /* da lun */
2577 while(pDev) {
2578 if(pDev->scsi_lun == scsi_lun) {
2579 break;
2580 }
2581 pDev = pDev->next_lun;
2582 }
2583 if(!pDev ) { // Something new add it
Julia Lawallda2907f2010-05-30 15:49:22 +02002584 d = kmalloc(sizeof(struct i2o_device),
2585 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 if(d==NULL)
2587 {
2588 printk(KERN_CRIT "Out of memory for I2O device data.\n");
2589 return -ENOMEM;
2590 }
2591
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002592 d->controller = pHba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 d->next = NULL;
2594
2595 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
2596
2597 d->flags = 0;
2598 adpt_i2o_report_hba_unit(pHba, d);
2599 adpt_i2o_install_device(pHba, d);
2600
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 pDev = pHba->channel[bus_no].device[scsi_id];
2602 if( pDev == NULL){
Julia Lawallda2907f2010-05-30 15:49:22 +02002603 pDev =
2604 kzalloc(sizeof(struct adpt_device),
2605 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 if(pDev == NULL) {
2607 return -ENOMEM;
2608 }
2609 pHba->channel[bus_no].device[scsi_id] = pDev;
2610 } else {
2611 while (pDev->next_lun) {
2612 pDev = pDev->next_lun;
2613 }
Julia Lawallda2907f2010-05-30 15:49:22 +02002614 pDev = pDev->next_lun =
2615 kzalloc(sizeof(struct adpt_device),
2616 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 if(pDev == NULL) {
2618 return -ENOMEM;
2619 }
2620 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 pDev->tid = d->lct_data.tid;
2622 pDev->scsi_channel = bus_no;
2623 pDev->scsi_id = scsi_id;
2624 pDev->scsi_lun = scsi_lun;
2625 pDev->pI2o_dev = d;
2626 d->owner = pDev;
2627 pDev->type = (buf[0])&0xff;
2628 pDev->flags = (buf[0]>>8)&0xff;
2629 // Too late, SCSI system has made up it's mind, but what the hey ...
2630 if(scsi_id > pHba->top_scsi_id){
2631 pHba->top_scsi_id = scsi_id;
2632 }
2633 if(scsi_lun > pHba->top_scsi_lun){
2634 pHba->top_scsi_lun = scsi_lun;
2635 }
2636 continue;
2637 } // end of new i2o device
2638
2639 // We found an old device - check it
2640 while(pDev) {
2641 if(pDev->scsi_lun == scsi_lun) {
2642 if(!scsi_device_online(pDev->pScsi_dev)) {
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002643 printk(KERN_WARNING"%s: Setting device (%d,%d,%llu) back online\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 pHba->name,bus_no,scsi_id,scsi_lun);
2645 if (pDev->pScsi_dev) {
2646 scsi_device_set_state(pDev->pScsi_dev, SDEV_RUNNING);
2647 }
2648 }
2649 d = pDev->pI2o_dev;
2650 if(d->lct_data.tid != tid) { // something changed
2651 pDev->tid = tid;
2652 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
2653 if (pDev->pScsi_dev) {
2654 pDev->pScsi_dev->changed = TRUE;
2655 pDev->pScsi_dev->removable = TRUE;
2656 }
2657 }
2658 // Found it - mark it scanned
2659 pDev->state = DPTI_DEV_ONLINE;
2660 break;
2661 }
2662 pDev = pDev->next_lun;
2663 }
2664 }
2665 }
2666 for (pI2o_dev = pHba->devices; pI2o_dev; pI2o_dev = pI2o_dev->next) {
2667 pDev =(struct adpt_device*) pI2o_dev->owner;
2668 if(!pDev){
2669 continue;
2670 }
2671 // Drive offline drives that previously existed but could not be found
2672 // in the LCT table
2673 if (pDev->state & DPTI_DEV_UNSCANNED){
2674 pDev->state = DPTI_DEV_OFFLINE;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002675 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 -07002676 if (pDev->pScsi_dev) {
2677 scsi_device_set_state(pDev->pScsi_dev, SDEV_OFFLINE);
2678 }
2679 }
2680 }
2681 return 0;
2682}
2683
2684static void adpt_fail_posted_scbs(adpt_hba* pHba)
2685{
2686 struct scsi_cmnd* cmd = NULL;
2687 struct scsi_device* d = NULL;
2688
2689 shost_for_each_device(d, pHba->host) {
2690 unsigned long flags;
2691 spin_lock_irqsave(&d->list_lock, flags);
2692 list_for_each_entry(cmd, &d->cmd_list, list) {
2693 if(cmd->serial_number == 0){
2694 continue;
2695 }
2696 cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1);
2697 cmd->scsi_done(cmd);
2698 }
2699 spin_unlock_irqrestore(&d->list_lock, flags);
2700 }
2701}
2702
2703
2704/*============================================================================
2705 * Routines from i2o subsystem
2706 *============================================================================
2707 */
2708
2709
2710
2711/*
2712 * Bring an I2O controller into HOLD state. See the spec.
2713 */
2714static int adpt_i2o_activate_hba(adpt_hba* pHba)
2715{
2716 int rcode;
2717
2718 if(pHba->initialized ) {
2719 if (adpt_i2o_status_get(pHba) < 0) {
2720 if((rcode = adpt_i2o_reset_hba(pHba)) != 0){
2721 printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name);
2722 return rcode;
2723 }
2724 if (adpt_i2o_status_get(pHba) < 0) {
2725 printk(KERN_INFO "HBA not responding.\n");
2726 return -1;
2727 }
2728 }
2729
2730 if(pHba->status_block->iop_state == ADAPTER_STATE_FAULTED) {
2731 printk(KERN_CRIT "%s: hardware fault\n", pHba->name);
2732 return -1;
2733 }
2734
2735 if (pHba->status_block->iop_state == ADAPTER_STATE_READY ||
2736 pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
2737 pHba->status_block->iop_state == ADAPTER_STATE_HOLD ||
2738 pHba->status_block->iop_state == ADAPTER_STATE_FAILED) {
2739 adpt_i2o_reset_hba(pHba);
2740 if (adpt_i2o_status_get(pHba) < 0 || pHba->status_block->iop_state != ADAPTER_STATE_RESET) {
2741 printk(KERN_ERR "%s: Failed to initialize.\n", pHba->name);
2742 return -1;
2743 }
2744 }
2745 } else {
2746 if((rcode = adpt_i2o_reset_hba(pHba)) != 0){
2747 printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name);
2748 return rcode;
2749 }
2750
2751 }
2752
2753 if (adpt_i2o_init_outbound_q(pHba) < 0) {
2754 return -1;
2755 }
2756
2757 /* In HOLD state */
2758
2759 if (adpt_i2o_hrt_get(pHba) < 0) {
2760 return -1;
2761 }
2762
2763 return 0;
2764}
2765
2766/*
2767 * Bring a controller online into OPERATIONAL state.
2768 */
2769
2770static int adpt_i2o_online_hba(adpt_hba* pHba)
2771{
2772 if (adpt_i2o_systab_send(pHba) < 0) {
2773 adpt_i2o_delete_hba(pHba);
2774 return -1;
2775 }
2776 /* In READY state */
2777
2778 if (adpt_i2o_enable_hba(pHba) < 0) {
2779 adpt_i2o_delete_hba(pHba);
2780 return -1;
2781 }
2782
2783 /* In OPERATIONAL state */
2784 return 0;
2785}
2786
2787static s32 adpt_send_nop(adpt_hba*pHba,u32 m)
2788{
2789 u32 __iomem *msg;
2790 ulong timeout = jiffies + 5*HZ;
2791
2792 while(m == EMPTY_QUEUE){
2793 rmb();
2794 m = readl(pHba->post_port);
2795 if(m != EMPTY_QUEUE){
2796 break;
2797 }
2798 if(time_after(jiffies,timeout)){
2799 printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name);
2800 return 2;
2801 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002802 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 }
2804 msg = (u32 __iomem *)(pHba->msg_addr_virt + m);
2805 writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]);
2806 writel( I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0,&msg[1]);
2807 writel( 0,&msg[2]);
2808 wmb();
2809
2810 writel(m, pHba->post_port);
2811 wmb();
2812 return 0;
2813}
2814
2815static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba)
2816{
2817 u8 *status;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002818 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 u32 __iomem *msg = NULL;
2820 int i;
2821 ulong timeout = jiffies + TMOUT_INITOUTBOUND*HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 u32 m;
2823
2824 do {
2825 rmb();
2826 m = readl(pHba->post_port);
2827 if (m != EMPTY_QUEUE) {
2828 break;
2829 }
2830
2831 if(time_after(jiffies,timeout)){
2832 printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name);
2833 return -ETIMEDOUT;
2834 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002835 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 } while(m == EMPTY_QUEUE);
2837
2838 msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
2839
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002840 status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002841 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 adpt_send_nop(pHba, m);
2843 printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n",
2844 pHba->name);
2845 return -ENOMEM;
2846 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002847 memset(status, 0, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848
2849 writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]);
2850 writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]);
2851 writel(0, &msg[2]);
2852 writel(0x0106, &msg[3]); /* Transaction context */
2853 writel(4096, &msg[4]); /* Host page frame size */
2854 writel((REPLY_FRAME_SIZE)<<16|0x80, &msg[5]); /* Outbound msg frame size and Initcode */
2855 writel(0xD0000004, &msg[6]); /* Simple SG LE, EOB */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002856 writel((u32)addr, &msg[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857
2858 writel(m, pHba->post_port);
2859 wmb();
2860
2861 // Wait for the reply status to come back
2862 do {
2863 if (*status) {
2864 if (*status != 0x01 /*I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS*/) {
2865 break;
2866 }
2867 }
2868 rmb();
2869 if(time_after(jiffies,timeout)){
2870 printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002871 /* We lose 4 bytes of "status" here, but we
2872 cannot free these because controller may
2873 awake and corrupt those bytes at any time */
2874 /* dma_free_coherent(&pHba->pDev->dev, 4, status, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875 return -ETIMEDOUT;
2876 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002877 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878 } while (1);
2879
2880 // If the command was successful, fill the fifo with our reply
2881 // message packets
2882 if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002883 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884 return -2;
2885 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002886 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002888 if(pHba->reply_pool != NULL) {
2889 dma_free_coherent(&pHba->pDev->dev,
2890 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
2891 pHba->reply_pool, pHba->reply_pool_pa);
2892 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002894 pHba->reply_pool = dma_alloc_coherent(&pHba->pDev->dev,
2895 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
2896 &pHba->reply_pool_pa, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002897 if (!pHba->reply_pool) {
2898 printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name);
2899 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002901 memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903 for(i = 0; i < pHba->reply_fifo_size; i++) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002904 writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4),
2905 pHba->reply_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907 }
2908 adpt_i2o_status_get(pHba);
2909 return 0;
2910}
2911
2912
2913/*
2914 * I2O System Table. Contains information about
2915 * all the IOPs in the system. Used to inform IOPs
2916 * about each other's existence.
2917 *
2918 * sys_tbl_ver is the CurrentChangeIndicator that is
2919 * used by IOPs to track changes.
2920 */
2921
2922
2923
2924static s32 adpt_i2o_status_get(adpt_hba* pHba)
2925{
2926 ulong timeout;
2927 u32 m;
2928 u32 __iomem *msg;
2929 u8 *status_block=NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
2931 if(pHba->status_block == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002932 pHba->status_block = dma_alloc_coherent(&pHba->pDev->dev,
2933 sizeof(i2o_status_block),
2934 &pHba->status_block_pa, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 if(pHba->status_block == NULL) {
2936 printk(KERN_ERR
2937 "dpti%d: Get Status Block failed; Out of memory. \n",
2938 pHba->unit);
2939 return -ENOMEM;
2940 }
2941 }
2942 memset(pHba->status_block, 0, sizeof(i2o_status_block));
2943 status_block = (u8*)(pHba->status_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 timeout = jiffies+TMOUT_GETSTATUS*HZ;
2945 do {
2946 rmb();
2947 m = readl(pHba->post_port);
2948 if (m != EMPTY_QUEUE) {
2949 break;
2950 }
2951 if(time_after(jiffies,timeout)){
2952 printk(KERN_ERR "%s: Timeout waiting for message !\n",
2953 pHba->name);
2954 return -ETIMEDOUT;
2955 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002956 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 } while(m==EMPTY_QUEUE);
2958
2959
2960 msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
2961
2962 writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]);
2963 writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]);
2964 writel(1, &msg[2]);
2965 writel(0, &msg[3]);
2966 writel(0, &msg[4]);
2967 writel(0, &msg[5]);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002968 writel( dma_low(pHba->status_block_pa), &msg[6]);
2969 writel( dma_high(pHba->status_block_pa), &msg[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970 writel(sizeof(i2o_status_block), &msg[8]); // 88 bytes
2971
2972 //post message
2973 writel(m, pHba->post_port);
2974 wmb();
2975
2976 while(status_block[87]!=0xff){
2977 if(time_after(jiffies,timeout)){
2978 printk(KERN_ERR"dpti%d: Get status timeout.\n",
2979 pHba->unit);
2980 return -ETIMEDOUT;
2981 }
2982 rmb();
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002983 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984 }
2985
2986 // Set up our number of outbound and inbound messages
2987 pHba->post_fifo_size = pHba->status_block->max_inbound_frames;
2988 if (pHba->post_fifo_size > MAX_TO_IOP_MESSAGES) {
2989 pHba->post_fifo_size = MAX_TO_IOP_MESSAGES;
2990 }
2991
2992 pHba->reply_fifo_size = pHba->status_block->max_outbound_frames;
2993 if (pHba->reply_fifo_size > MAX_FROM_IOP_MESSAGES) {
2994 pHba->reply_fifo_size = MAX_FROM_IOP_MESSAGES;
2995 }
2996
2997 // Calculate the Scatter Gather list size
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002998 if (dpt_dma64(pHba)) {
2999 pHba->sg_tablesize
3000 = ((pHba->status_block->inbound_frame_size * 4
3001 - 14 * sizeof(u32))
3002 / (sizeof(struct sg_simple_element) + sizeof(u32)));
3003 } else {
3004 pHba->sg_tablesize
3005 = ((pHba->status_block->inbound_frame_size * 4
3006 - 12 * sizeof(u32))
3007 / sizeof(struct sg_simple_element));
3008 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 if (pHba->sg_tablesize > SG_LIST_ELEMENTS) {
3010 pHba->sg_tablesize = SG_LIST_ELEMENTS;
3011 }
3012
3013
3014#ifdef DEBUG
3015 printk("dpti%d: State = ",pHba->unit);
3016 switch(pHba->status_block->iop_state) {
3017 case 0x01:
3018 printk("INIT\n");
3019 break;
3020 case 0x02:
3021 printk("RESET\n");
3022 break;
3023 case 0x04:
3024 printk("HOLD\n");
3025 break;
3026 case 0x05:
3027 printk("READY\n");
3028 break;
3029 case 0x08:
3030 printk("OPERATIONAL\n");
3031 break;
3032 case 0x10:
3033 printk("FAILED\n");
3034 break;
3035 case 0x11:
3036 printk("FAULTED\n");
3037 break;
3038 default:
3039 printk("%x (unknown!!)\n",pHba->status_block->iop_state);
3040 }
3041#endif
3042 return 0;
3043}
3044
3045/*
3046 * Get the IOP's Logical Configuration Table
3047 */
3048static int adpt_i2o_lct_get(adpt_hba* pHba)
3049{
3050 u32 msg[8];
3051 int ret;
3052 u32 buf[16];
3053
3054 if ((pHba->lct_size == 0) || (pHba->lct == NULL)){
3055 pHba->lct_size = pHba->status_block->expected_lct_size;
3056 }
3057 do {
3058 if (pHba->lct == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003059 pHba->lct = dma_alloc_coherent(&pHba->pDev->dev,
3060 pHba->lct_size, &pHba->lct_pa,
Julia Lawallda2907f2010-05-30 15:49:22 +02003061 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 if(pHba->lct == NULL) {
3063 printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n",
3064 pHba->name);
3065 return -ENOMEM;
3066 }
3067 }
3068 memset(pHba->lct, 0, pHba->lct_size);
3069
3070 msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
3071 msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
3072 msg[2] = 0;
3073 msg[3] = 0;
3074 msg[4] = 0xFFFFFFFF; /* All devices */
3075 msg[5] = 0x00000000; /* Report now */
3076 msg[6] = 0xD0000000|pHba->lct_size;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003077 msg[7] = (u32)pHba->lct_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078
3079 if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 360))) {
3080 printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n",
3081 pHba->name, ret);
3082 printk(KERN_ERR"Adaptec: Error Reading Hardware.\n");
3083 return ret;
3084 }
3085
3086 if ((pHba->lct->table_size << 2) > pHba->lct_size) {
3087 pHba->lct_size = pHba->lct->table_size << 2;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003088 dma_free_coherent(&pHba->pDev->dev, pHba->lct_size,
3089 pHba->lct, pHba->lct_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090 pHba->lct = NULL;
3091 }
3092 } while (pHba->lct == NULL);
3093
3094 PDEBUG("%s: Hardware resource table read.\n", pHba->name);
3095
3096
3097 // I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO;
3098 if(adpt_i2o_query_scalar(pHba, 0 , 0x8000, -1, buf, sizeof(buf))>=0) {
3099 pHba->FwDebugBufferSize = buf[1];
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02003100 pHba->FwDebugBuffer_P = ioremap(pHba->base_addr_phys + buf[0],
3101 pHba->FwDebugBufferSize);
3102 if (pHba->FwDebugBuffer_P) {
3103 pHba->FwDebugFlags_P = pHba->FwDebugBuffer_P +
3104 FW_DEBUG_FLAGS_OFFSET;
3105 pHba->FwDebugBLEDvalue_P = pHba->FwDebugBuffer_P +
3106 FW_DEBUG_BLED_OFFSET;
3107 pHba->FwDebugBLEDflag_P = pHba->FwDebugBLEDvalue_P + 1;
3108 pHba->FwDebugStrLength_P = pHba->FwDebugBuffer_P +
3109 FW_DEBUG_STR_LENGTH_OFFSET;
3110 pHba->FwDebugBuffer_P += buf[2];
3111 pHba->FwDebugFlags = 0;
3112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113 }
3114
3115 return 0;
3116}
3117
3118static int adpt_i2o_build_sys_table(void)
3119{
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003120 adpt_hba* pHba = hba_chain;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121 int count = 0;
3122
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003123 if (sys_tbl)
3124 dma_free_coherent(&pHba->pDev->dev, sys_tbl_len,
3125 sys_tbl, sys_tbl_pa);
3126
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127 sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs
3128 (hba_count) * sizeof(struct i2o_sys_tbl_entry);
3129
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003130 sys_tbl = dma_alloc_coherent(&pHba->pDev->dev,
3131 sys_tbl_len, &sys_tbl_pa, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02003132 if (!sys_tbl) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 printk(KERN_WARNING "SysTab Set failed. Out of memory.\n");
3134 return -ENOMEM;
3135 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003136 memset(sys_tbl, 0, sys_tbl_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137
3138 sys_tbl->num_entries = hba_count;
3139 sys_tbl->version = I2OVERSION;
3140 sys_tbl->change_ind = sys_tbl_ind++;
3141
3142 for(pHba = hba_chain; pHba; pHba = pHba->next) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003143 u64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 // Get updated Status Block so we have the latest information
3145 if (adpt_i2o_status_get(pHba)) {
3146 sys_tbl->num_entries--;
3147 continue; // try next one
3148 }
3149
3150 sys_tbl->iops[count].org_id = pHba->status_block->org_id;
3151 sys_tbl->iops[count].iop_id = pHba->unit + 2;
3152 sys_tbl->iops[count].seg_num = 0;
3153 sys_tbl->iops[count].i2o_version = pHba->status_block->i2o_version;
3154 sys_tbl->iops[count].iop_state = pHba->status_block->iop_state;
3155 sys_tbl->iops[count].msg_type = pHba->status_block->msg_type;
3156 sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size;
3157 sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
3158 sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003159 addr = pHba->base_addr_phys + 0x40;
3160 sys_tbl->iops[count].inbound_low = dma_low(addr);
3161 sys_tbl->iops[count].inbound_high = dma_high(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162
3163 count++;
3164 }
3165
3166#ifdef DEBUG
3167{
3168 u32 *table = (u32*)sys_tbl;
3169 printk(KERN_DEBUG"sys_tbl_len=%d in 32bit words\n",(sys_tbl_len >>2));
3170 for(count = 0; count < (sys_tbl_len >>2); count++) {
3171 printk(KERN_INFO "sys_tbl[%d] = %0#10x\n",
3172 count, table[count]);
3173 }
3174}
3175#endif
3176
3177 return 0;
3178}
3179
3180
3181/*
3182 * Dump the information block associated with a given unit (TID)
3183 */
3184
3185static void adpt_i2o_report_hba_unit(adpt_hba* pHba, struct i2o_device *d)
3186{
3187 char buf[64];
3188 int unit = d->lct_data.tid;
3189
3190 printk(KERN_INFO "TID %3.3d ", unit);
3191
3192 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 3, buf, 16)>=0)
3193 {
3194 buf[16]=0;
3195 printk(" Vendor: %-12.12s", buf);
3196 }
3197 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 4, buf, 16)>=0)
3198 {
3199 buf[16]=0;
3200 printk(" Device: %-12.12s", buf);
3201 }
3202 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 6, buf, 8)>=0)
3203 {
3204 buf[8]=0;
3205 printk(" Rev: %-12.12s\n", buf);
3206 }
3207#ifdef DEBUG
3208 printk(KERN_INFO "\tClass: %.21s\n", adpt_i2o_get_class_name(d->lct_data.class_id));
3209 printk(KERN_INFO "\tSubclass: 0x%04X\n", d->lct_data.sub_class);
3210 printk(KERN_INFO "\tFlags: ");
3211
3212 if(d->lct_data.device_flags&(1<<0))
3213 printk("C"); // ConfigDialog requested
3214 if(d->lct_data.device_flags&(1<<1))
3215 printk("U"); // Multi-user capable
3216 if(!(d->lct_data.device_flags&(1<<4)))
3217 printk("P"); // Peer service enabled!
3218 if(!(d->lct_data.device_flags&(1<<5)))
3219 printk("M"); // Mgmt service enabled!
3220 printk("\n");
3221#endif
3222}
3223
3224#ifdef DEBUG
3225/*
3226 * Do i2o class name lookup
3227 */
3228static const char *adpt_i2o_get_class_name(int class)
3229{
3230 int idx = 16;
3231 static char *i2o_class_name[] = {
3232 "Executive",
3233 "Device Driver Module",
3234 "Block Device",
3235 "Tape Device",
3236 "LAN Interface",
3237 "WAN Interface",
3238 "Fibre Channel Port",
3239 "Fibre Channel Device",
3240 "SCSI Device",
3241 "ATE Port",
3242 "ATE Device",
3243 "Floppy Controller",
3244 "Floppy Device",
3245 "Secondary Bus Port",
3246 "Peer Transport Agent",
3247 "Peer Transport",
3248 "Unknown"
3249 };
3250
3251 switch(class&0xFFF) {
3252 case I2O_CLASS_EXECUTIVE:
3253 idx = 0; break;
3254 case I2O_CLASS_DDM:
3255 idx = 1; break;
3256 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
3257 idx = 2; break;
3258 case I2O_CLASS_SEQUENTIAL_STORAGE:
3259 idx = 3; break;
3260 case I2O_CLASS_LAN:
3261 idx = 4; break;
3262 case I2O_CLASS_WAN:
3263 idx = 5; break;
3264 case I2O_CLASS_FIBRE_CHANNEL_PORT:
3265 idx = 6; break;
3266 case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
3267 idx = 7; break;
3268 case I2O_CLASS_SCSI_PERIPHERAL:
3269 idx = 8; break;
3270 case I2O_CLASS_ATE_PORT:
3271 idx = 9; break;
3272 case I2O_CLASS_ATE_PERIPHERAL:
3273 idx = 10; break;
3274 case I2O_CLASS_FLOPPY_CONTROLLER:
3275 idx = 11; break;
3276 case I2O_CLASS_FLOPPY_DEVICE:
3277 idx = 12; break;
3278 case I2O_CLASS_BUS_ADAPTER_PORT:
3279 idx = 13; break;
3280 case I2O_CLASS_PEER_TRANSPORT_AGENT:
3281 idx = 14; break;
3282 case I2O_CLASS_PEER_TRANSPORT:
3283 idx = 15; break;
3284 }
3285 return i2o_class_name[idx];
3286}
3287#endif
3288
3289
3290static s32 adpt_i2o_hrt_get(adpt_hba* pHba)
3291{
3292 u32 msg[6];
3293 int ret, size = sizeof(i2o_hrt);
3294
3295 do {
3296 if (pHba->hrt == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003297 pHba->hrt = dma_alloc_coherent(&pHba->pDev->dev,
3298 size, &pHba->hrt_pa, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299 if (pHba->hrt == NULL) {
3300 printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", pHba->name);
3301 return -ENOMEM;
3302 }
3303 }
3304
3305 msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
3306 msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
3307 msg[2]= 0;
3308 msg[3]= 0;
3309 msg[4]= (0xD0000000 | size); /* Simple transaction */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003310 msg[5]= (u32)pHba->hrt_pa; /* Dump it here */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
3312 if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg),20))) {
3313 printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n", pHba->name, ret);
3314 return ret;
3315 }
3316
3317 if (pHba->hrt->num_entries * pHba->hrt->entry_len << 2 > size) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003318 int newsize = pHba->hrt->num_entries * pHba->hrt->entry_len << 2;
3319 dma_free_coherent(&pHba->pDev->dev, size,
3320 pHba->hrt, pHba->hrt_pa);
3321 size = newsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322 pHba->hrt = NULL;
3323 }
3324 } while(pHba->hrt == NULL);
3325 return 0;
3326}
3327
3328/*
3329 * Query one scalar group value or a whole scalar group.
3330 */
3331static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid,
3332 int group, int field, void *buf, int buflen)
3333{
3334 u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003335 u8 *opblk_va;
3336 dma_addr_t opblk_pa;
3337 u8 *resblk_va;
3338 dma_addr_t resblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339
3340 int size;
3341
3342 /* 8 bytes for header */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003343 resblk_va = dma_alloc_coherent(&pHba->pDev->dev,
3344 sizeof(u8) * (8 + buflen), &resblk_pa, GFP_KERNEL);
3345 if (resblk_va == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name);
3347 return -ENOMEM;
3348 }
3349
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003350 opblk_va = dma_alloc_coherent(&pHba->pDev->dev,
3351 sizeof(opblk), &opblk_pa, GFP_KERNEL);
3352 if (opblk_va == NULL) {
3353 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3354 resblk_va, resblk_pa);
Colin Ian Kingd0799622016-11-07 16:38:57 +00003355 printk(KERN_CRIT "%s: query operation failed; Out of memory.\n",
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003356 pHba->name);
3357 return -ENOMEM;
3358 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 if (field == -1) /* whole group */
3360 opblk[4] = -1;
3361
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003362 memcpy(opblk_va, opblk, sizeof(opblk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363 size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid,
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003364 opblk_va, opblk_pa, sizeof(opblk),
3365 resblk_va, resblk_pa, sizeof(u8)*(8+buflen));
3366 dma_free_coherent(&pHba->pDev->dev, sizeof(opblk), opblk_va, opblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367 if (size == -ETIME) {
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; Timed out.\n", pHba->name);
3371 return -ETIME;
3372 } else if (size == -EINTR) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003373 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3374 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375 printk(KERN_WARNING "%s: issue params failed; Interrupted.\n", pHba->name);
3376 return -EINTR;
3377 }
3378
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003379 memcpy(buf, resblk_va+8, buflen); /* cut off header */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003381 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3382 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 if (size < 0)
3384 return size;
3385
3386 return buflen;
3387}
3388
3389
3390/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
3391 *
3392 * This function can be used for all UtilParamsGet/Set operations.
3393 * The OperationBlock is given in opblk-buffer,
3394 * and results are returned in resblk-buffer.
3395 * Note that the minimum sized resblk is 8 bytes and contains
3396 * ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
3397 */
3398static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid,
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003399 void *opblk_va, dma_addr_t opblk_pa, int oplen,
3400 void *resblk_va, dma_addr_t resblk_pa, int reslen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401{
3402 u32 msg[9];
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003403 u32 *res = (u32 *)resblk_va;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404 int wait_status;
3405
3406 msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
3407 msg[1] = cmd << 24 | HOST_TID << 12 | tid;
3408 msg[2] = 0;
3409 msg[3] = 0;
3410 msg[4] = 0;
3411 msg[5] = 0x54000000 | oplen; /* OperationBlock */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003412 msg[6] = (u32)opblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413 msg[7] = 0xD0000000 | reslen; /* ResultBlock */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003414 msg[8] = (u32)resblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415
3416 if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003417 printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk_va);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418 return wait_status; /* -DetailedStatus */
3419 }
3420
3421 if (res[1]&0x00FF0000) { /* BlockStatus != SUCCESS */
3422 printk(KERN_WARNING "%s: %s - Error:\n ErrorInfoSize = 0x%02x, "
3423 "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
3424 pHba->name,
3425 (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"
3426 : "PARAMS_GET",
3427 res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
3428 return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
3429 }
3430
3431 return 4 + ((res[1] & 0x0000FFFF) << 2); /* bytes used in resblk */
3432}
3433
3434
3435static s32 adpt_i2o_quiesce_hba(adpt_hba* pHba)
3436{
3437 u32 msg[4];
3438 int ret;
3439
3440 adpt_i2o_status_get(pHba);
3441
3442 /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */
3443
3444 if((pHba->status_block->iop_state != ADAPTER_STATE_READY) &&
3445 (pHba->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)){
3446 return 0;
3447 }
3448
3449 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
3450 msg[1] = I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
3451 msg[2] = 0;
3452 msg[3] = 0;
3453
3454 if((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) {
3455 printk(KERN_INFO"dpti%d: Unable to quiesce (status=%#x).\n",
3456 pHba->unit, -ret);
3457 } else {
3458 printk(KERN_INFO"dpti%d: Quiesced.\n",pHba->unit);
3459 }
3460
3461 adpt_i2o_status_get(pHba);
3462 return ret;
3463}
3464
3465
3466/*
3467 * Enable IOP. Allows the IOP to resume external operations.
3468 */
3469static int adpt_i2o_enable_hba(adpt_hba* pHba)
3470{
3471 u32 msg[4];
3472 int ret;
3473
3474 adpt_i2o_status_get(pHba);
3475 if(!pHba->status_block){
3476 return -ENOMEM;
3477 }
3478 /* Enable only allowed on READY state */
3479 if(pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)
3480 return 0;
3481
3482 if(pHba->status_block->iop_state != ADAPTER_STATE_READY)
3483 return -EINVAL;
3484
3485 msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
3486 msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
3487 msg[2]= 0;
3488 msg[3]= 0;
3489
3490 if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) {
3491 printk(KERN_WARNING"%s: Could not enable (status=%#10x).\n",
3492 pHba->name, ret);
3493 } else {
3494 PDEBUG("%s: Enabled.\n", pHba->name);
3495 }
3496
3497 adpt_i2o_status_get(pHba);
3498 return ret;
3499}
3500
3501
3502static int adpt_i2o_systab_send(adpt_hba* pHba)
3503{
3504 u32 msg[12];
3505 int ret;
3506
3507 msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
3508 msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
3509 msg[2] = 0;
3510 msg[3] = 0;
3511 msg[4] = (0<<16) | ((pHba->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */
3512 msg[5] = 0; /* Segment 0 */
3513
3514 /*
3515 * Provide three SGL-elements:
3516 * System table (SysTab), Private memory space declaration and
3517 * Private i/o space declaration
3518 */
3519 msg[6] = 0x54000000 | sys_tbl_len;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003520 msg[7] = (u32)sys_tbl_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521 msg[8] = 0x54000000 | 0;
3522 msg[9] = 0;
3523 msg[10] = 0xD4000000 | 0;
3524 msg[11] = 0;
3525
3526 if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 120))) {
3527 printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n",
3528 pHba->name, ret);
3529 }
3530#ifdef DEBUG
3531 else {
3532 PINFO("%s: SysTab set.\n", pHba->name);
3533 }
3534#endif
3535
3536 return ret;
3537 }
3538
3539
3540/*============================================================================
3541 *
3542 *============================================================================
3543 */
3544
3545
3546#ifdef UARTDELAY
3547
3548static static void adpt_delay(int millisec)
3549{
3550 int i;
3551 for (i = 0; i < millisec; i++) {
3552 udelay(1000); /* delay for one millisecond */
3553 }
3554}
3555
3556#endif
3557
Andrew Morton24601bb2007-12-10 15:49:20 -08003558static struct scsi_host_template driver_template = {
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02003559 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560 .name = "dpt_i2o",
3561 .proc_name = "dpt_i2o",
Al Viroff98f7c2013-03-31 03:21:50 -04003562 .show_info = adpt_show_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003563 .info = adpt_info,
3564 .queuecommand = adpt_queue,
3565 .eh_abort_handler = adpt_abort,
3566 .eh_device_reset_handler = adpt_device_reset,
3567 .eh_bus_reset_handler = adpt_bus_reset,
3568 .eh_host_reset_handler = adpt_reset,
3569 .bios_param = adpt_bios_param,
3570 .slave_configure = adpt_slave_configure,
3571 .can_queue = MAX_TO_IOP_MESSAGES,
3572 .this_id = 7,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573 .use_clustering = ENABLE_CLUSTERING,
3574};
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02003575
3576static int __init adpt_init(void)
3577{
3578 int error;
3579 adpt_hba *pHba, *next;
3580
3581 printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n");
3582
3583 error = adpt_detect(&driver_template);
3584 if (error < 0)
3585 return error;
3586 if (hba_chain == NULL)
3587 return -ENODEV;
3588
3589 for (pHba = hba_chain; pHba; pHba = pHba->next) {
3590 error = scsi_add_host(pHba->host, &pHba->pDev->dev);
3591 if (error)
3592 goto fail;
3593 scsi_scan_host(pHba->host);
3594 }
3595 return 0;
3596fail:
3597 for (pHba = hba_chain; pHba; pHba = next) {
3598 next = pHba->next;
3599 scsi_remove_host(pHba->host);
3600 }
3601 return error;
3602}
3603
3604static void __exit adpt_exit(void)
3605{
3606 adpt_hba *pHba, *next;
3607
3608 for (pHba = hba_chain; pHba; pHba = pHba->next)
3609 scsi_remove_host(pHba->host);
3610 for (pHba = hba_chain; pHba; pHba = next) {
3611 next = pHba->next;
3612 adpt_release(pHba->host);
3613 }
3614}
3615
3616module_init(adpt_init);
3617module_exit(adpt_exit);
3618
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619MODULE_LICENSE("GPL");