blob: 7b1a084ec94ef758e1eaff92020e00b65a5da087 [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 */
78static dpt_sig_S DPTI_sig = {
79 {'d', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION,
80#ifdef __i386__
81 PROC_INTEL, PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM,
82#elif defined(__ia64__)
83 PROC_INTEL, PROC_IA64,
84#elif defined(__sparc__)
85 PROC_ULTRASPARC, PROC_ULTRASPARC,
86#elif defined(__alpha__)
87 PROC_ALPHA, PROC_ALPHA,
88#else
89 (-1),(-1),
90#endif
91 FT_HBADRVR, 0, OEM_DPT, OS_LINUX, CAP_OVERLAP, DEV_ALL,
92 ADF_ALL_SC5, 0, 0, DPT_VERSION, DPT_REVISION, DPT_SUBREVISION,
93 DPT_MONTH, DPT_DAY, DPT_YEAR, "Adaptec Linux I2O RAID Driver"
94};
95
96
97
98
99/*============================================================================
100 * Globals
101 *============================================================================
102 */
103
Arjan van de Ven0b950672006-01-11 13:16:10 +0100104static DEFINE_MUTEX(adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200106static struct i2o_sys_tbl *sys_tbl;
107static dma_addr_t sys_tbl_pa;
108static int sys_tbl_ind;
109static int sys_tbl_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111static adpt_hba* hba_chain = NULL;
112static int hba_count = 0;
113
Arjan van de Ven00977a52007-02-12 00:55:34 -0800114static const struct file_operations adpt_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 .ioctl = adpt_ioctl,
116 .open = adpt_open,
117 .release = adpt_close
118};
119
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120/* Structures and definitions for synchronous message posting.
121 * See adpt_i2o_post_wait() for description
122 * */
123struct adpt_i2o_post_wait_data
124{
125 int status;
126 u32 id;
127 adpt_wait_queue_head_t *wq;
128 struct adpt_i2o_post_wait_data *next;
129};
130
131static struct adpt_i2o_post_wait_data *adpt_post_wait_queue = NULL;
132static u32 adpt_post_wait_id = 0;
133static DEFINE_SPINLOCK(adpt_post_wait_lock);
134
135
136/*============================================================================
137 * Functions
138 *============================================================================
139 */
140
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200141static inline u32 dma_high(dma_addr_t addr)
142{
143 return upper_32_bits(addr);
144}
145
146static inline u32 dma_low(dma_addr_t addr)
147{
148 return (u32)addr;
149}
150
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151static u8 adpt_read_blink_led(adpt_hba* host)
152{
153 if(host->FwDebugBLEDflag_P != 0) {
154 if( readb(host->FwDebugBLEDflag_P) == 0xbc ){
155 return readb(host->FwDebugBLEDvalue_P);
156 }
157 }
158 return 0;
159}
160
161/*============================================================================
162 * Scsi host template interface functions
163 *============================================================================
164 */
165
166static struct pci_device_id dptids[] = {
167 { PCI_DPT_VENDOR_ID, PCI_DPT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
168 { PCI_DPT_VENDOR_ID, PCI_DPT_RAPTOR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
169 { 0, }
170};
171MODULE_DEVICE_TABLE(pci,dptids);
172
Andrew Morton24601bb2007-12-10 15:49:20 -0800173static int adpt_detect(struct scsi_host_template* sht)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174{
175 struct pci_dev *pDev = NULL;
176 adpt_hba* pHba;
177
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 PINFO("Detecting Adaptec I2O RAID controllers...\n");
179
180 /* search for all Adatpec I2O RAID cards */
Alan Coxa07f3532006-09-15 15:34:32 +0100181 while ((pDev = pci_get_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 if(pDev->device == PCI_DPT_DEVICE_ID ||
183 pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){
Andrew Morton24601bb2007-12-10 15:49:20 -0800184 if(adpt_install_hba(sht, pDev) ){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 PERROR("Could not Init an I2O RAID device\n");
186 PERROR("Will not try to detect others.\n");
187 return hba_count-1;
188 }
Alan Coxa07f3532006-09-15 15:34:32 +0100189 pci_dev_get(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 }
191 }
192
193 /* In INIT state, Activate IOPs */
194 for (pHba = hba_chain; pHba; pHba = pHba->next) {
195 // Activate does get status , init outbound, and get hrt
196 if (adpt_i2o_activate_hba(pHba) < 0) {
197 adpt_i2o_delete_hba(pHba);
198 }
199 }
200
201
202 /* Active IOPs in HOLD state */
203
204rebuild_sys_tab:
205 if (hba_chain == NULL)
206 return 0;
207
208 /*
209 * If build_sys_table fails, we kill everything and bail
210 * as we can't init the IOPs w/o a system table
211 */
212 if (adpt_i2o_build_sys_table() < 0) {
213 adpt_i2o_sys_shutdown();
214 return 0;
215 }
216
217 PDEBUG("HBA's in HOLD state\n");
218
219 /* If IOP don't get online, we need to rebuild the System table */
220 for (pHba = hba_chain; pHba; pHba = pHba->next) {
221 if (adpt_i2o_online_hba(pHba) < 0) {
222 adpt_i2o_delete_hba(pHba);
223 goto rebuild_sys_tab;
224 }
225 }
226
227 /* Active IOPs now in OPERATIONAL state */
228 PDEBUG("HBA's in OPERATIONAL state\n");
229
230 printk("dpti: If you have a lot of devices this could take a few minutes.\n");
231 for (pHba = hba_chain; pHba; pHba = pHba->next) {
232 printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name);
233 if (adpt_i2o_lct_get(pHba) < 0){
234 adpt_i2o_delete_hba(pHba);
235 continue;
236 }
237
238 if (adpt_i2o_parse_lct(pHba) < 0){
239 adpt_i2o_delete_hba(pHba);
240 continue;
241 }
242 adpt_inquiry(pHba);
243 }
244
245 for (pHba = hba_chain; pHba; pHba = pHba->next) {
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +0200246 if (adpt_scsi_host_alloc(pHba, sht) < 0){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 adpt_i2o_delete_hba(pHba);
248 continue;
249 }
250 pHba->initialized = TRUE;
251 pHba->state &= ~DPTI_STATE_RESET;
252 }
253
254 // Register our control device node
255 // nodes will need to be created in /dev to access this
256 // the nodes can not be created from within the driver
257 if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) {
Andrew Morton24601bb2007-12-10 15:49:20 -0800258 adpt_i2o_sys_shutdown();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 return 0;
260 }
261 return hba_count;
262}
263
264
Andrew Morton24601bb2007-12-10 15:49:20 -0800265/*
266 * scsi_unregister will be called AFTER we return.
267 */
268static int adpt_release(struct Scsi_Host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269{
Andrew Morton24601bb2007-12-10 15:49:20 -0800270 adpt_hba* pHba = (adpt_hba*) host->hostdata[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271// adpt_i2o_quiesce_hba(pHba);
272 adpt_i2o_delete_hba(pHba);
Andrew Morton24601bb2007-12-10 15:49:20 -0800273 scsi_unregister(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 return 0;
275}
276
277
278static void adpt_inquiry(adpt_hba* pHba)
279{
280 u32 msg[14];
281 u32 *mptr;
282 u32 *lenptr;
283 int direction;
284 int scsidir;
285 u32 len;
286 u32 reqlen;
287 u8* buf;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200288 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 u8 scb[16];
290 s32 rcode;
291
292 memset(msg, 0, sizeof(msg));
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200293 buf = dma_alloc_coherent(&pHba->pDev->dev, 80, &addr, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 if(!buf){
295 printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name);
296 return;
297 }
298 memset((void*)buf, 0, 36);
299
300 len = 36;
301 direction = 0x00000000;
302 scsidir =0x40000000; // DATA IN (iop<--dev)
303
304 reqlen = 14; // SINGLE SGE
305 /* Stick the headers on */
306 msg[0] = reqlen<<16 | SGL_OFFSET_12;
307 msg[1] = (0xff<<24|HOST_TID<<12|ADAPTER_TID);
308 msg[2] = 0;
309 msg[3] = 0;
310 // Adaptec/DPT Private stuff
311 msg[4] = I2O_CMD_SCSI_EXEC|DPT_ORGANIZATION_ID<<16;
312 msg[5] = ADAPTER_TID | 1<<16 /* Interpret*/;
313 /* Direction, disconnect ok | sense data | simple queue , CDBLen */
314 // I2O_SCB_FLAG_ENABLE_DISCONNECT |
315 // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG |
316 // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;
317 msg[6] = scsidir|0x20a00000| 6 /* cmd len*/;
318
319 mptr=msg+7;
320
321 memset(scb, 0, sizeof(scb));
322 // Write SCSI command into the message - always 16 byte block
323 scb[0] = INQUIRY;
324 scb[1] = 0;
325 scb[2] = 0;
326 scb[3] = 0;
327 scb[4] = 36;
328 scb[5] = 0;
329 // Don't care about the rest of scb
330
331 memcpy(mptr, scb, sizeof(scb));
332 mptr+=4;
333 lenptr=mptr++; /* Remember me - fill in when we know */
334
335 /* Now fill in the SGList and command */
336 *lenptr = len;
337 *mptr++ = 0xD0000000|direction|len;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200338 *mptr++ = addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339
340 // Send it on it's way
341 rcode = adpt_i2o_post_wait(pHba, msg, reqlen<<2, 120);
342 if (rcode != 0) {
343 sprintf(pHba->detail, "Adaptec I2O RAID");
344 printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode);
345 if (rcode != -ETIME && rcode != -EINTR)
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200346 dma_free_coherent(&pHba->pDev->dev, 80, buf, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 } else {
348 memset(pHba->detail, 0, sizeof(pHba->detail));
349 memcpy(&(pHba->detail), "Vendor: Adaptec ", 16);
350 memcpy(&(pHba->detail[16]), " Model: ", 8);
351 memcpy(&(pHba->detail[24]), (u8*) &buf[16], 16);
352 memcpy(&(pHba->detail[40]), " FW: ", 4);
353 memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4);
354 pHba->detail[48] = '\0'; /* precautionary */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200355 dma_free_coherent(&pHba->pDev->dev, 80, buf, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 }
357 adpt_i2o_status_get(pHba);
358 return ;
359}
360
361
362static int adpt_slave_configure(struct scsi_device * device)
363{
364 struct Scsi_Host *host = device->host;
365 adpt_hba* pHba;
366
367 pHba = (adpt_hba *) host->hostdata[0];
368
369 if (host->can_queue && device->tagged_supported) {
370 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
371 host->can_queue - 1);
372 } else {
373 scsi_adjust_queue_depth(device, 0, 1);
374 }
375 return 0;
376}
377
378static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
379{
380 adpt_hba* pHba = NULL;
381 struct adpt_device* pDev = NULL; /* dpt per device information */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
383 cmd->scsi_done = done;
384 /*
385 * SCSI REQUEST_SENSE commands will be executed automatically by the
386 * Host Adapter for any errors, so they should not be executed
387 * explicitly unless the Sense Data is zero indicating that no error
388 * occurred.
389 */
390
391 if ((cmd->cmnd[0] == REQUEST_SENSE) && (cmd->sense_buffer[0] != 0)) {
392 cmd->result = (DID_OK << 16);
393 cmd->scsi_done(cmd);
394 return 0;
395 }
396
397 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
398 if (!pHba) {
399 return FAILED;
400 }
401
402 rmb();
403 /*
404 * TODO: I need to block here if I am processing ioctl cmds
405 * but if the outstanding cmds all finish before the ioctl,
406 * the scsi-core will not know to start sending cmds to me again.
407 * I need to a way to restart the scsi-cores queues or should I block
408 * calling scsi_done on the outstanding cmds instead
409 * for now we don't set the IOCTL state
410 */
411 if(((pHba->state) & DPTI_STATE_IOCTL) || ((pHba->state) & DPTI_STATE_RESET)) {
412 pHba->host->last_reset = jiffies;
413 pHba->host->resetting = 1;
414 return 1;
415 }
416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 // TODO if the cmd->device if offline then I may need to issue a bus rescan
418 // followed by a get_lct to see if the device is there anymore
419 if((pDev = (struct adpt_device*) (cmd->device->hostdata)) == NULL) {
420 /*
421 * First command request for this device. Set up a pointer
422 * to the device structure. This should be a TEST_UNIT_READY
423 * command from scan_scsis_single.
424 */
425 if ((pDev = adpt_find_device(pHba, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun)) == NULL) {
426 // TODO: if any luns are at this bus, scsi id then fake a TEST_UNIT_READY and INQUIRY response
427 // with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue.
428 cmd->result = (DID_NO_CONNECT << 16);
429 cmd->scsi_done(cmd);
430 return 0;
431 }
432 cmd->device->hostdata = pDev;
433 }
434 pDev->pScsi_dev = cmd->device;
435
436 /*
437 * If we are being called from when the device is being reset,
438 * delay processing of the command until later.
439 */
440 if (pDev->state & DPTI_DEV_RESET ) {
441 return FAILED;
442 }
443 return adpt_scsi_to_i2o(pHba, cmd, pDev);
444}
445
446static int adpt_bios_param(struct scsi_device *sdev, struct block_device *dev,
447 sector_t capacity, int geom[])
448{
449 int heads=-1;
450 int sectors=-1;
451 int cylinders=-1;
452
453 // *** First lets set the default geometry ****
454
455 // If the capacity is less than ox2000
456 if (capacity < 0x2000 ) { // floppy
457 heads = 18;
458 sectors = 2;
459 }
460 // else if between 0x2000 and 0x20000
461 else if (capacity < 0x20000) {
462 heads = 64;
463 sectors = 32;
464 }
465 // else if between 0x20000 and 0x40000
466 else if (capacity < 0x40000) {
467 heads = 65;
468 sectors = 63;
469 }
470 // else if between 0x4000 and 0x80000
471 else if (capacity < 0x80000) {
472 heads = 128;
473 sectors = 63;
474 }
475 // else if greater than 0x80000
476 else {
477 heads = 255;
478 sectors = 63;
479 }
480 cylinders = sector_div(capacity, heads * sectors);
481
482 // Special case if CDROM
483 if(sdev->type == 5) { // CDROM
484 heads = 252;
485 sectors = 63;
486 cylinders = 1111;
487 }
488
489 geom[0] = heads;
490 geom[1] = sectors;
491 geom[2] = cylinders;
492
493 PDEBUG("adpt_bios_param: exit\n");
494 return 0;
495}
496
497
498static const char *adpt_info(struct Scsi_Host *host)
499{
500 adpt_hba* pHba;
501
502 pHba = (adpt_hba *) host->hostdata[0];
503 return (char *) (pHba->detail);
504}
505
506static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
507 int length, int inout)
508{
509 struct adpt_device* d;
510 int id;
511 int chan;
512 int len = 0;
513 int begin = 0;
514 int pos = 0;
515 adpt_hba* pHba;
516 int unit;
517
518 *start = buffer;
519 if (inout == TRUE) {
520 /*
521 * The user has done a write and wants us to take the
522 * data in the buffer and do something with it.
523 * proc_scsiwrite calls us with inout = 1
524 *
525 * Read data from buffer (writing to us) - NOT SUPPORTED
526 */
527 return -EINVAL;
528 }
529
530 /*
531 * inout = 0 means the user has done a read and wants information
532 * returned, so we write information about the cards into the buffer
533 * proc_scsiread() calls us with inout = 0
534 */
535
536 // Find HBA (host bus adapter) we are looking for
Arjan van de Ven0b950672006-01-11 13:16:10 +0100537 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 for (pHba = hba_chain; pHba; pHba = pHba->next) {
539 if (pHba->host == host) {
540 break; /* found adapter */
541 }
542 }
Arjan van de Ven0b950672006-01-11 13:16:10 +0100543 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 if (pHba == NULL) {
545 return 0;
546 }
547 host = pHba->host;
548
549 len = sprintf(buffer , "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION);
550 len += sprintf(buffer+len, "%s\n", pHba->detail);
551 len += sprintf(buffer+len, "SCSI Host=scsi%d Control Node=/dev/%s irq=%d\n",
552 pHba->host->host_no, pHba->name, host->irq);
553 len += sprintf(buffer+len, "\tpost fifo size = %d\n\treply fifo size = %d\n\tsg table size = %d\n\n",
554 host->can_queue, (int) pHba->reply_fifo_size , host->sg_tablesize);
555
556 pos = begin + len;
557
558 /* CHECKPOINT */
559 if(pos > offset + length) {
560 goto stop_output;
561 }
562 if(pos <= offset) {
563 /*
564 * If we haven't even written to where we last left
565 * off (the last time we were called), reset the
566 * beginning pointer.
567 */
568 len = 0;
569 begin = pos;
570 }
571 len += sprintf(buffer+len, "Devices:\n");
572 for(chan = 0; chan < MAX_CHANNEL; chan++) {
573 for(id = 0; id < MAX_ID; id++) {
574 d = pHba->channel[chan].device[id];
575 while(d){
576 len += sprintf(buffer+len,"\t%-24.24s", d->pScsi_dev->vendor);
577 len += sprintf(buffer+len," Rev: %-8.8s\n", d->pScsi_dev->rev);
578 pos = begin + len;
579
580
581 /* CHECKPOINT */
582 if(pos > offset + length) {
583 goto stop_output;
584 }
585 if(pos <= offset) {
586 len = 0;
587 begin = pos;
588 }
589
590 unit = d->pI2o_dev->lct_data.tid;
591 len += sprintf(buffer+len, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d) (%s)\n\n",
592 unit, (int)d->scsi_channel, (int)d->scsi_id, (int)d->scsi_lun,
593 scsi_device_online(d->pScsi_dev)? "online":"offline");
594 pos = begin + len;
595
596 /* CHECKPOINT */
597 if(pos > offset + length) {
598 goto stop_output;
599 }
600 if(pos <= offset) {
601 len = 0;
602 begin = pos;
603 }
604
605 d = d->next_lun;
606 }
607 }
608 }
609
610 /*
611 * begin is where we last checked our position with regards to offset
612 * begin is always less than offset. len is relative to begin. It
613 * is the number of bytes written past begin
614 *
615 */
616stop_output:
617 /* stop the output and calculate the correct length */
618 *(buffer + len) = '\0';
619
620 *start = buffer + (offset - begin); /* Start of wanted data */
621 len -= (offset - begin);
622 if(len > length) {
623 len = length;
624 } else if(len < 0){
625 len = 0;
626 **start = '\0';
627 }
628 return len;
629}
630
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631/*===========================================================================
632 * Error Handling routines
633 *===========================================================================
634 */
635
636static int adpt_abort(struct scsi_cmnd * cmd)
637{
638 adpt_hba* pHba = NULL; /* host bus adapter structure */
639 struct adpt_device* dptdevice; /* dpt per device information */
640 u32 msg[5];
641 int rcode;
642
643 if(cmd->serial_number == 0){
644 return FAILED;
645 }
646 pHba = (adpt_hba*) cmd->device->host->hostdata[0];
647 printk(KERN_INFO"%s: Trying to Abort cmd=%ld\n",pHba->name, cmd->serial_number);
648 if ((dptdevice = (void*) (cmd->device->hostdata)) == NULL) {
649 printk(KERN_ERR "%s: Unable to abort: No device in cmnd\n",pHba->name);
650 return FAILED;
651 }
652
653 memset(msg, 0, sizeof(msg));
654 msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
655 msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|dptdevice->tid;
656 msg[2] = 0;
657 msg[3]= 0;
658 msg[4] = (u32)cmd;
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800659 if (pHba->host)
660 spin_lock_irq(pHba->host->host_lock);
661 rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER);
662 if (pHba->host)
663 spin_unlock_irq(pHba->host->host_lock);
664 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 if(rcode == -EOPNOTSUPP ){
666 printk(KERN_INFO"%s: Abort cmd not supported\n",pHba->name);
667 return FAILED;
668 }
669 printk(KERN_INFO"%s: Abort cmd=%ld failed.\n",pHba->name, cmd->serial_number);
670 return FAILED;
671 }
672 printk(KERN_INFO"%s: Abort cmd=%ld complete.\n",pHba->name, cmd->serial_number);
673 return SUCCESS;
674}
675
676
677#define I2O_DEVICE_RESET 0x27
678// This is the same for BLK and SCSI devices
679// NOTE this is wrong in the i2o.h definitions
680// This is not currently supported by our adapter but we issue it anyway
681static int adpt_device_reset(struct scsi_cmnd* cmd)
682{
683 adpt_hba* pHba;
684 u32 msg[4];
685 u32 rcode;
686 int old_state;
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -0700687 struct adpt_device* d = cmd->device->hostdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
689 pHba = (void*) cmd->device->host->hostdata[0];
690 printk(KERN_INFO"%s: Trying to reset device\n",pHba->name);
691 if (!d) {
692 printk(KERN_INFO"%s: Reset Device: Device Not found\n",pHba->name);
693 return FAILED;
694 }
695 memset(msg, 0, sizeof(msg));
696 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
697 msg[1] = (I2O_DEVICE_RESET<<24|HOST_TID<<12|d->tid);
698 msg[2] = 0;
699 msg[3] = 0;
700
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800701 if (pHba->host)
702 spin_lock_irq(pHba->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 old_state = d->state;
704 d->state |= DPTI_DEV_RESET;
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800705 rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
706 d->state = old_state;
707 if (pHba->host)
708 spin_unlock_irq(pHba->host->host_lock);
709 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 if(rcode == -EOPNOTSUPP ){
711 printk(KERN_INFO"%s: Device reset not supported\n",pHba->name);
712 return FAILED;
713 }
714 printk(KERN_INFO"%s: Device reset failed\n",pHba->name);
715 return FAILED;
716 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 printk(KERN_INFO"%s: Device reset successful\n",pHba->name);
718 return SUCCESS;
719 }
720}
721
722
723#define I2O_HBA_BUS_RESET 0x87
724// This version of bus reset is called by the eh_error handler
725static int adpt_bus_reset(struct scsi_cmnd* cmd)
726{
727 adpt_hba* pHba;
728 u32 msg[4];
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800729 u32 rcode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
731 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
732 memset(msg, 0, sizeof(msg));
733 printk(KERN_WARNING"%s: Bus reset: SCSI Bus %d: tid: %d\n",pHba->name, cmd->device->channel,pHba->channel[cmd->device->channel].tid );
734 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
735 msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->device->channel].tid);
736 msg[2] = 0;
737 msg[3] = 0;
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800738 if (pHba->host)
739 spin_lock_irq(pHba->host->host_lock);
740 rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
741 if (pHba->host)
742 spin_unlock_irq(pHba->host->host_lock);
743 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name);
745 return FAILED;
746 } else {
747 printk(KERN_WARNING"%s: Bus reset success.\n",pHba->name);
748 return SUCCESS;
749 }
750}
751
752// This version of reset is called by the eh_error_handler
Jeff Garzik df0ae242005-05-28 07:57:14 -0400753static int __adpt_reset(struct scsi_cmnd* cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754{
755 adpt_hba* pHba;
756 int rcode;
757 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
758 printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n",pHba->name,cmd->device->channel,pHba->channel[cmd->device->channel].tid );
759 rcode = adpt_hba_reset(pHba);
760 if(rcode == 0){
761 printk(KERN_WARNING"%s: HBA reset complete\n",pHba->name);
762 return SUCCESS;
763 } else {
764 printk(KERN_WARNING"%s: HBA reset failed (%x)\n",pHba->name, rcode);
765 return FAILED;
766 }
767}
768
Jeff Garzik df0ae242005-05-28 07:57:14 -0400769static int adpt_reset(struct scsi_cmnd* cmd)
770{
771 int rc;
772
773 spin_lock_irq(cmd->device->host->host_lock);
774 rc = __adpt_reset(cmd);
775 spin_unlock_irq(cmd->device->host->host_lock);
776
777 return rc;
778}
779
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780// This version of reset is called by the ioctls and indirectly from eh_error_handler via adpt_reset
781static int adpt_hba_reset(adpt_hba* pHba)
782{
783 int rcode;
784
785 pHba->state |= DPTI_STATE_RESET;
786
787 // Activate does get status , init outbound, and get hrt
788 if ((rcode=adpt_i2o_activate_hba(pHba)) < 0) {
789 printk(KERN_ERR "%s: Could not activate\n", pHba->name);
790 adpt_i2o_delete_hba(pHba);
791 return rcode;
792 }
793
794 if ((rcode=adpt_i2o_build_sys_table()) < 0) {
795 adpt_i2o_delete_hba(pHba);
796 return rcode;
797 }
798 PDEBUG("%s: in HOLD state\n",pHba->name);
799
800 if ((rcode=adpt_i2o_online_hba(pHba)) < 0) {
801 adpt_i2o_delete_hba(pHba);
802 return rcode;
803 }
804 PDEBUG("%s: in OPERATIONAL state\n",pHba->name);
805
806 if ((rcode=adpt_i2o_lct_get(pHba)) < 0){
807 adpt_i2o_delete_hba(pHba);
808 return rcode;
809 }
810
811 if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){
812 adpt_i2o_delete_hba(pHba);
813 return rcode;
814 }
815 pHba->state &= ~DPTI_STATE_RESET;
816
817 adpt_fail_posted_scbs(pHba);
818 return 0; /* return success */
819}
820
821/*===========================================================================
822 *
823 *===========================================================================
824 */
825
826
827static void adpt_i2o_sys_shutdown(void)
828{
829 adpt_hba *pHba, *pNext;
Adrian Bunk458af542005-11-27 00:36:37 +0100830 struct adpt_i2o_post_wait_data *p1, *old;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831
832 printk(KERN_INFO"Shutting down Adaptec I2O controllers.\n");
833 printk(KERN_INFO" This could take a few minutes if there are many devices attached\n");
834 /* Delete all IOPs from the controller chain */
835 /* They should have already been released by the
836 * scsi-core
837 */
838 for (pHba = hba_chain; pHba; pHba = pNext) {
839 pNext = pHba->next;
840 adpt_i2o_delete_hba(pHba);
841 }
842
843 /* Remove any timedout entries from the wait queue. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844// spin_lock_irqsave(&adpt_post_wait_lock, flags);
845 /* Nothing should be outstanding at this point so just
846 * free them
847 */
Adrian Bunk458af542005-11-27 00:36:37 +0100848 for(p1 = adpt_post_wait_queue; p1;) {
849 old = p1;
850 p1 = p1->next;
851 kfree(old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 }
853// spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
854 adpt_post_wait_queue = NULL;
855
856 printk(KERN_INFO "Adaptec I2O controllers down.\n");
857}
858
Andrew Morton24601bb2007-12-10 15:49:20 -0800859static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860{
861
862 adpt_hba* pHba = NULL;
863 adpt_hba* p = NULL;
864 ulong base_addr0_phys = 0;
865 ulong base_addr1_phys = 0;
866 u32 hba_map0_area_size = 0;
867 u32 hba_map1_area_size = 0;
868 void __iomem *base_addr_virt = NULL;
869 void __iomem *msg_addr_virt = NULL;
870
871 int raptorFlag = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
873 if(pci_enable_device(pDev)) {
874 return -EINVAL;
875 }
Salyzyn, Mark9638d892006-01-12 08:31:57 -0500876
877 if (pci_request_regions(pDev, "dpt_i2o")) {
878 PERROR("dpti: adpt_config_hba: pci request region failed\n");
879 return -EINVAL;
880 }
881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 pci_set_master(pDev);
James Bottomleyc80ddf02007-12-12 15:06:21 -0500883 if (pci_set_dma_mask(pDev, DMA_32BIT_MASK))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 return -EINVAL;
885
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200886 /* adapter only supports message blocks below 4GB */
887 pci_set_consistent_dma_mask(pDev, DMA_32BIT_MASK);
888
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 base_addr0_phys = pci_resource_start(pDev,0);
890 hba_map0_area_size = pci_resource_len(pDev,0);
891
892 // Check if standard PCI card or single BAR Raptor
893 if(pDev->device == PCI_DPT_DEVICE_ID){
894 if(pDev->subsystem_device >=0xc032 && pDev->subsystem_device <= 0xc03b){
895 // Raptor card with this device id needs 4M
896 hba_map0_area_size = 0x400000;
897 } else { // Not Raptor - it is a PCI card
898 if(hba_map0_area_size > 0x100000 ){
899 hba_map0_area_size = 0x100000;
900 }
901 }
902 } else {// Raptor split BAR config
903 // Use BAR1 in this configuration
904 base_addr1_phys = pci_resource_start(pDev,1);
905 hba_map1_area_size = pci_resource_len(pDev,1);
906 raptorFlag = TRUE;
907 }
908
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size);
910 if (!base_addr_virt) {
James Bottomley9c472dd2005-08-08 11:51:38 -0500911 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 PERROR("dpti: adpt_config_hba: io remap failed\n");
913 return -EINVAL;
914 }
915
916 if(raptorFlag == TRUE) {
917 msg_addr_virt = ioremap(base_addr1_phys, hba_map1_area_size );
918 if (!msg_addr_virt) {
919 PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n");
920 iounmap(base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -0500921 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 return -EINVAL;
923 }
924 } else {
925 msg_addr_virt = base_addr_virt;
926 }
927
928 // Allocate and zero the data structure
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +0200929 pHba = kzalloc(sizeof(adpt_hba), GFP_KERNEL);
930 if (!pHba) {
931 if (msg_addr_virt != base_addr_virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 iounmap(msg_addr_virt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 iounmap(base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -0500934 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 return -ENOMEM;
936 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937
Arjan van de Ven0b950672006-01-11 13:16:10 +0100938 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
940 if(hba_chain != NULL){
941 for(p = hba_chain; p->next; p = p->next);
942 p->next = pHba;
943 } else {
944 hba_chain = pHba;
945 }
946 pHba->next = NULL;
947 pHba->unit = hba_count;
Benoit Boissinot 23a2bc22005-04-25 19:46:30 -0700948 sprintf(pHba->name, "dpti%d", hba_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 hba_count++;
950
Arjan van de Ven0b950672006-01-11 13:16:10 +0100951 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952
953 pHba->pDev = pDev;
954 pHba->base_addr_phys = base_addr0_phys;
955
956 // Set up the Virtual Base Address of the I2O Device
957 pHba->base_addr_virt = base_addr_virt;
958 pHba->msg_addr_virt = msg_addr_virt;
959 pHba->irq_mask = base_addr_virt+0x30;
960 pHba->post_port = base_addr_virt+0x40;
961 pHba->reply_port = base_addr_virt+0x44;
962
963 pHba->hrt = NULL;
964 pHba->lct = NULL;
965 pHba->lct_size = 0;
966 pHba->status_block = NULL;
967 pHba->post_count = 0;
968 pHba->state = DPTI_STATE_RESET;
969 pHba->pDev = pDev;
970 pHba->devices = NULL;
971
972 // Initializing the spinlocks
973 spin_lock_init(&pHba->state_lock);
974 spin_lock_init(&adpt_post_wait_lock);
975
976 if(raptorFlag == 0){
977 printk(KERN_INFO"Adaptec I2O RAID controller %d at %p size=%x irq=%d\n",
978 hba_count-1, base_addr_virt, hba_map0_area_size, pDev->irq);
979 } else {
980 printk(KERN_INFO"Adaptec I2O RAID controller %d irq=%d\n",hba_count-1, pDev->irq);
981 printk(KERN_INFO" BAR0 %p - size= %x\n",base_addr_virt,hba_map0_area_size);
982 printk(KERN_INFO" BAR1 %p - size= %x\n",msg_addr_virt,hba_map1_area_size);
983 }
984
Thomas Gleixner1d6f3592006-07-01 19:29:42 -0700985 if (request_irq (pDev->irq, adpt_isr, IRQF_SHARED, pHba->name, pHba)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 printk(KERN_ERR"%s: Couldn't register IRQ %d\n", pHba->name, pDev->irq);
987 adpt_i2o_delete_hba(pHba);
988 return -EINVAL;
989 }
990
991 return 0;
992}
993
994
995static void adpt_i2o_delete_hba(adpt_hba* pHba)
996{
997 adpt_hba* p1;
998 adpt_hba* p2;
999 struct i2o_device* d;
1000 struct i2o_device* next;
1001 int i;
1002 int j;
1003 struct adpt_device* pDev;
1004 struct adpt_device* pNext;
1005
1006
Arjan van de Ven0b950672006-01-11 13:16:10 +01001007 mutex_lock(&adpt_configuration_lock);
Andrew Morton24601bb2007-12-10 15:49:20 -08001008 // scsi_unregister calls our adpt_release which
1009 // does a quiese
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 if(pHba->host){
1011 free_irq(pHba->host->irq, pHba);
1012 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 p2 = NULL;
1014 for( p1 = hba_chain; p1; p2 = p1,p1=p1->next){
1015 if(p1 == pHba) {
1016 if(p2) {
1017 p2->next = p1->next;
1018 } else {
1019 hba_chain = p1->next;
1020 }
1021 break;
1022 }
1023 }
1024
1025 hba_count--;
Arjan van de Ven0b950672006-01-11 13:16:10 +01001026 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
1028 iounmap(pHba->base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -05001029 pci_release_regions(pHba->pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 if(pHba->msg_addr_virt != pHba->base_addr_virt){
1031 iounmap(pHba->msg_addr_virt);
1032 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001033 if(pHba->hrt) {
1034 dma_free_coherent(&pHba->pDev->dev,
1035 pHba->hrt->num_entries * pHba->hrt->entry_len << 2,
1036 pHba->hrt, pHba->hrt_pa);
1037 }
1038 if(pHba->lct) {
1039 dma_free_coherent(&pHba->pDev->dev, pHba->lct_size,
1040 pHba->lct, pHba->lct_pa);
1041 }
1042 if(pHba->status_block) {
1043 dma_free_coherent(&pHba->pDev->dev, sizeof(i2o_status_block),
1044 pHba->status_block, pHba->status_block_pa);
1045 }
1046 if(pHba->reply_pool) {
1047 dma_free_coherent(&pHba->pDev->dev,
1048 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
1049 pHba->reply_pool, pHba->reply_pool_pa);
1050 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
1052 for(d = pHba->devices; d ; d = next){
1053 next = d->next;
1054 kfree(d);
1055 }
1056 for(i = 0 ; i < pHba->top_scsi_channel ; i++){
1057 for(j = 0; j < MAX_ID; j++){
1058 if(pHba->channel[i].device[j] != NULL){
1059 for(pDev = pHba->channel[i].device[j]; pDev; pDev = pNext){
1060 pNext = pDev->next_lun;
1061 kfree(pDev);
1062 }
1063 }
1064 }
1065 }
Alan Coxa07f3532006-09-15 15:34:32 +01001066 pci_dev_put(pHba->pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 kfree(pHba);
1068
1069 if(hba_count <= 0){
1070 unregister_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER);
1071 }
1072}
1073
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun)
1075{
1076 struct adpt_device* d;
1077
1078 if(chan < 0 || chan >= MAX_CHANNEL)
1079 return NULL;
1080
1081 if( pHba->channel[chan].device == NULL){
1082 printk(KERN_DEBUG"Adaptec I2O RAID: Trying to find device before they are allocated\n");
1083 return NULL;
1084 }
1085
1086 d = pHba->channel[chan].device[id];
1087 if(!d || d->tid == 0) {
1088 return NULL;
1089 }
1090
1091 /* If it is the only lun at that address then this should match*/
1092 if(d->scsi_lun == lun){
1093 return d;
1094 }
1095
1096 /* else we need to look through all the luns */
1097 for(d=d->next_lun ; d ; d = d->next_lun){
1098 if(d->scsi_lun == lun){
1099 return d;
1100 }
1101 }
1102 return NULL;
1103}
1104
1105
1106static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout)
1107{
1108 // I used my own version of the WAIT_QUEUE_HEAD
1109 // to handle some version differences
1110 // When embedded in the kernel this could go back to the vanilla one
1111 ADPT_DECLARE_WAIT_QUEUE_HEAD(adpt_wq_i2o_post);
1112 int status = 0;
1113 ulong flags = 0;
1114 struct adpt_i2o_post_wait_data *p1, *p2;
1115 struct adpt_i2o_post_wait_data *wait_data =
1116 kmalloc(sizeof(struct adpt_i2o_post_wait_data),GFP_KERNEL);
Andrew Morton4452ea52005-06-23 00:10:26 -07001117 DECLARE_WAITQUEUE(wait, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
Andrew Morton4452ea52005-06-23 00:10:26 -07001119 if (!wait_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 return -ENOMEM;
Andrew Morton4452ea52005-06-23 00:10:26 -07001121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 /*
1123 * The spin locking is needed to keep anyone from playing
1124 * with the queue pointers and id while we do the same
1125 */
1126 spin_lock_irqsave(&adpt_post_wait_lock, flags);
1127 // TODO we need a MORE unique way of getting ids
1128 // to support async LCT get
1129 wait_data->next = adpt_post_wait_queue;
1130 adpt_post_wait_queue = wait_data;
1131 adpt_post_wait_id++;
1132 adpt_post_wait_id &= 0x7fff;
1133 wait_data->id = adpt_post_wait_id;
1134 spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
1135
1136 wait_data->wq = &adpt_wq_i2o_post;
1137 wait_data->status = -ETIMEDOUT;
1138
Andrew Morton4452ea52005-06-23 00:10:26 -07001139 add_wait_queue(&adpt_wq_i2o_post, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
1141 msg[2] |= 0x80000000 | ((u32)wait_data->id);
1142 timeout *= HZ;
1143 if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){
1144 set_current_state(TASK_INTERRUPTIBLE);
1145 if(pHba->host)
1146 spin_unlock_irq(pHba->host->host_lock);
1147 if (!timeout)
1148 schedule();
1149 else{
1150 timeout = schedule_timeout(timeout);
1151 if (timeout == 0) {
1152 // I/O issued, but cannot get result in
1153 // specified time. Freeing resorces is
1154 // dangerous.
1155 status = -ETIME;
1156 }
1157 }
1158 if(pHba->host)
1159 spin_lock_irq(pHba->host->host_lock);
1160 }
Andrew Morton4452ea52005-06-23 00:10:26 -07001161 remove_wait_queue(&adpt_wq_i2o_post, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
1163 if(status == -ETIMEDOUT){
1164 printk(KERN_INFO"dpti%d: POST WAIT TIMEOUT\n",pHba->unit);
1165 // We will have to free the wait_data memory during shutdown
1166 return status;
1167 }
1168
1169 /* Remove the entry from the queue. */
1170 p2 = NULL;
1171 spin_lock_irqsave(&adpt_post_wait_lock, flags);
1172 for(p1 = adpt_post_wait_queue; p1; p2 = p1, p1 = p1->next) {
1173 if(p1 == wait_data) {
1174 if(p1->status == I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION ) {
1175 status = -EOPNOTSUPP;
1176 }
1177 if(p2) {
1178 p2->next = p1->next;
1179 } else {
1180 adpt_post_wait_queue = p1->next;
1181 }
1182 break;
1183 }
1184 }
1185 spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
1186
1187 kfree(wait_data);
1188
1189 return status;
1190}
1191
1192
1193static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len)
1194{
1195
1196 u32 m = EMPTY_QUEUE;
1197 u32 __iomem *msg;
1198 ulong timeout = jiffies + 30*HZ;
1199 do {
1200 rmb();
1201 m = readl(pHba->post_port);
1202 if (m != EMPTY_QUEUE) {
1203 break;
1204 }
1205 if(time_after(jiffies,timeout)){
1206 printk(KERN_WARNING"dpti%d: Timeout waiting for message frame!\n", pHba->unit);
1207 return -ETIMEDOUT;
1208 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001209 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 } while(m == EMPTY_QUEUE);
1211
1212 msg = pHba->msg_addr_virt + m;
1213 memcpy_toio(msg, data, len);
1214 wmb();
1215
1216 //post message
1217 writel(m, pHba->post_port);
1218 wmb();
1219
1220 return 0;
1221}
1222
1223
1224static void adpt_i2o_post_wait_complete(u32 context, int status)
1225{
1226 struct adpt_i2o_post_wait_data *p1 = NULL;
1227 /*
1228 * We need to search through the adpt_post_wait
1229 * queue to see if the given message is still
1230 * outstanding. If not, it means that the IOP
1231 * took longer to respond to the message than we
1232 * had allowed and timer has already expired.
1233 * Not much we can do about that except log
1234 * it for debug purposes, increase timeout, and recompile
1235 *
1236 * Lock needed to keep anyone from moving queue pointers
1237 * around while we're looking through them.
1238 */
1239
1240 context &= 0x7fff;
1241
1242 spin_lock(&adpt_post_wait_lock);
1243 for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) {
1244 if(p1->id == context) {
1245 p1->status = status;
1246 spin_unlock(&adpt_post_wait_lock);
1247 wake_up_interruptible(p1->wq);
1248 return;
1249 }
1250 }
1251 spin_unlock(&adpt_post_wait_lock);
1252 // If this happens we lose commands that probably really completed
1253 printk(KERN_DEBUG"dpti: Could Not find task %d in wait queue\n",context);
1254 printk(KERN_DEBUG" Tasks in wait queue:\n");
1255 for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) {
1256 printk(KERN_DEBUG" %d\n",p1->id);
1257 }
1258 return;
1259}
1260
1261static s32 adpt_i2o_reset_hba(adpt_hba* pHba)
1262{
1263 u32 msg[8];
1264 u8* status;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001265 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 u32 m = EMPTY_QUEUE ;
1267 ulong timeout = jiffies + (TMOUT_IOPRESET*HZ);
1268
1269 if(pHba->initialized == FALSE) { // First time reset should be quick
1270 timeout = jiffies + (25*HZ);
1271 } else {
1272 adpt_i2o_quiesce_hba(pHba);
1273 }
1274
1275 do {
1276 rmb();
1277 m = readl(pHba->post_port);
1278 if (m != EMPTY_QUEUE) {
1279 break;
1280 }
1281 if(time_after(jiffies,timeout)){
1282 printk(KERN_WARNING"Timeout waiting for message!\n");
1283 return -ETIMEDOUT;
1284 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001285 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 } while (m == EMPTY_QUEUE);
1287
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001288 status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 if(status == NULL) {
1290 adpt_send_nop(pHba, m);
1291 printk(KERN_ERR"IOP reset failed - no free memory.\n");
1292 return -ENOMEM;
1293 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001294 memset(status,0,4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
1296 msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
1297 msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
1298 msg[2]=0;
1299 msg[3]=0;
1300 msg[4]=0;
1301 msg[5]=0;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001302 msg[6]=dma_low(addr);
1303 msg[7]=dma_high(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
1305 memcpy_toio(pHba->msg_addr_virt+m, msg, sizeof(msg));
1306 wmb();
1307 writel(m, pHba->post_port);
1308 wmb();
1309
1310 while(*status == 0){
1311 if(time_after(jiffies,timeout)){
1312 printk(KERN_WARNING"%s: IOP Reset Timeout\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001313 /* We lose 4 bytes of "status" here, but we cannot
1314 free these because controller may awake and corrupt
1315 those bytes at any time */
1316 /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 return -ETIMEDOUT;
1318 }
1319 rmb();
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001320 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 }
1322
1323 if(*status == 0x01 /*I2O_EXEC_IOP_RESET_IN_PROGRESS*/) {
1324 PDEBUG("%s: Reset in progress...\n", pHba->name);
1325 // Here we wait for message frame to become available
1326 // indicated that reset has finished
1327 do {
1328 rmb();
1329 m = readl(pHba->post_port);
1330 if (m != EMPTY_QUEUE) {
1331 break;
1332 }
1333 if(time_after(jiffies,timeout)){
1334 printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001335 /* We lose 4 bytes of "status" here, but we
1336 cannot free these because controller may
1337 awake and corrupt those bytes at any time */
1338 /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 return -ETIMEDOUT;
1340 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001341 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 } while (m == EMPTY_QUEUE);
1343 // Flush the offset
1344 adpt_send_nop(pHba, m);
1345 }
1346 adpt_i2o_status_get(pHba);
1347 if(*status == 0x02 ||
1348 pHba->status_block->iop_state != ADAPTER_STATE_RESET) {
1349 printk(KERN_WARNING"%s: Reset reject, trying to clear\n",
1350 pHba->name);
1351 } else {
1352 PDEBUG("%s: Reset completed.\n", pHba->name);
1353 }
1354
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001355 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356#ifdef UARTDELAY
1357 // This delay is to allow someone attached to the card through the debug UART to
1358 // set up the dump levels that they want before the rest of the initialization sequence
1359 adpt_delay(20000);
1360#endif
1361 return 0;
1362}
1363
1364
1365static int adpt_i2o_parse_lct(adpt_hba* pHba)
1366{
1367 int i;
1368 int max;
1369 int tid;
1370 struct i2o_device *d;
1371 i2o_lct *lct = pHba->lct;
1372 u8 bus_no = 0;
1373 s16 scsi_id;
1374 s16 scsi_lun;
1375 u32 buf[10]; // larger than 7, or 8 ...
1376 struct adpt_device* pDev;
1377
1378 if (lct == NULL) {
1379 printk(KERN_ERR "%s: LCT is empty???\n",pHba->name);
1380 return -1;
1381 }
1382
1383 max = lct->table_size;
1384 max -= 3;
1385 max /= 9;
1386
1387 for(i=0;i<max;i++) {
1388 if( lct->lct_entry[i].user_tid != 0xfff){
1389 /*
1390 * If we have hidden devices, we need to inform the upper layers about
1391 * the possible maximum id reference to handle device access when
1392 * an array is disassembled. This code has no other purpose but to
1393 * allow us future access to devices that are currently hidden
1394 * behind arrays, hotspares or have not been configured (JBOD mode).
1395 */
1396 if( lct->lct_entry[i].class_id != I2O_CLASS_RANDOM_BLOCK_STORAGE &&
1397 lct->lct_entry[i].class_id != I2O_CLASS_SCSI_PERIPHERAL &&
1398 lct->lct_entry[i].class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
1399 continue;
1400 }
1401 tid = lct->lct_entry[i].tid;
1402 // I2O_DPT_DEVICE_INFO_GROUP_NO;
1403 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) {
1404 continue;
1405 }
1406 bus_no = buf[0]>>16;
1407 scsi_id = buf[1];
1408 scsi_lun = (buf[2]>>8 )&0xff;
1409 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1410 printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no);
1411 continue;
1412 }
1413 if (scsi_id >= MAX_ID){
1414 printk(KERN_WARNING"%s: SCSI ID %d out of range \n", pHba->name, bus_no);
1415 continue;
1416 }
1417 if(bus_no > pHba->top_scsi_channel){
1418 pHba->top_scsi_channel = bus_no;
1419 }
1420 if(scsi_id > pHba->top_scsi_id){
1421 pHba->top_scsi_id = scsi_id;
1422 }
1423 if(scsi_lun > pHba->top_scsi_lun){
1424 pHba->top_scsi_lun = scsi_lun;
1425 }
1426 continue;
1427 }
Robert P. J. Day5cbded52006-12-13 00:35:56 -08001428 d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 if(d==NULL)
1430 {
1431 printk(KERN_CRIT"%s: Out of memory for I2O device data.\n",pHba->name);
1432 return -ENOMEM;
1433 }
1434
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07001435 d->controller = pHba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 d->next = NULL;
1437
1438 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
1439
1440 d->flags = 0;
1441 tid = d->lct_data.tid;
1442 adpt_i2o_report_hba_unit(pHba, d);
1443 adpt_i2o_install_device(pHba, d);
1444 }
1445 bus_no = 0;
1446 for(d = pHba->devices; d ; d = d->next) {
1447 if(d->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT ||
1448 d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PORT){
1449 tid = d->lct_data.tid;
1450 // TODO get the bus_no from hrt-but for now they are in order
1451 //bus_no =
1452 if(bus_no > pHba->top_scsi_channel){
1453 pHba->top_scsi_channel = bus_no;
1454 }
1455 pHba->channel[bus_no].type = d->lct_data.class_id;
1456 pHba->channel[bus_no].tid = tid;
1457 if(adpt_i2o_query_scalar(pHba, tid, 0x0200, -1, buf, 28)>=0)
1458 {
1459 pHba->channel[bus_no].scsi_id = buf[1];
1460 PDEBUG("Bus %d - SCSI ID %d.\n", bus_no, buf[1]);
1461 }
1462 // TODO remove - this is just until we get from hrt
1463 bus_no++;
1464 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1465 printk(KERN_WARNING"%s: Channel number %d out of range - LCT\n", pHba->name, bus_no);
1466 break;
1467 }
1468 }
1469 }
1470
1471 // Setup adpt_device table
1472 for(d = pHba->devices; d ; d = d->next) {
1473 if(d->lct_data.class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE ||
1474 d->lct_data.class_id == I2O_CLASS_SCSI_PERIPHERAL ||
1475 d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
1476
1477 tid = d->lct_data.tid;
1478 scsi_id = -1;
1479 // I2O_DPT_DEVICE_INFO_GROUP_NO;
1480 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)>=0) {
1481 bus_no = buf[0]>>16;
1482 scsi_id = buf[1];
1483 scsi_lun = (buf[2]>>8 )&0xff;
1484 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1485 continue;
1486 }
1487 if (scsi_id >= MAX_ID) {
1488 continue;
1489 }
1490 if( pHba->channel[bus_no].device[scsi_id] == NULL){
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301491 pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 if(pDev == NULL) {
1493 return -ENOMEM;
1494 }
1495 pHba->channel[bus_no].device[scsi_id] = pDev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 } else {
1497 for( pDev = pHba->channel[bus_no].device[scsi_id];
1498 pDev->next_lun; pDev = pDev->next_lun){
1499 }
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301500 pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 if(pDev->next_lun == NULL) {
1502 return -ENOMEM;
1503 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 pDev = pDev->next_lun;
1505 }
1506 pDev->tid = tid;
1507 pDev->scsi_channel = bus_no;
1508 pDev->scsi_id = scsi_id;
1509 pDev->scsi_lun = scsi_lun;
1510 pDev->pI2o_dev = d;
1511 d->owner = pDev;
1512 pDev->type = (buf[0])&0xff;
1513 pDev->flags = (buf[0]>>8)&0xff;
1514 if(scsi_id > pHba->top_scsi_id){
1515 pHba->top_scsi_id = scsi_id;
1516 }
1517 if(scsi_lun > pHba->top_scsi_lun){
1518 pHba->top_scsi_lun = scsi_lun;
1519 }
1520 }
1521 if(scsi_id == -1){
1522 printk(KERN_WARNING"Could not find SCSI ID for %s\n",
1523 d->lct_data.identity_tag);
1524 }
1525 }
1526 }
1527 return 0;
1528}
1529
1530
1531/*
1532 * Each I2O controller has a chain of devices on it - these match
1533 * the useful parts of the LCT of the board.
1534 */
1535
1536static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d)
1537{
Arjan van de Ven0b950672006-01-11 13:16:10 +01001538 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 d->controller=pHba;
1540 d->owner=NULL;
1541 d->next=pHba->devices;
1542 d->prev=NULL;
1543 if (pHba->devices != NULL){
1544 pHba->devices->prev=d;
1545 }
1546 pHba->devices=d;
1547 *d->dev_name = 0;
1548
Arjan van de Ven0b950672006-01-11 13:16:10 +01001549 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 return 0;
1551}
1552
1553static int adpt_open(struct inode *inode, struct file *file)
1554{
1555 int minor;
1556 adpt_hba* pHba;
1557
1558 //TODO check for root access
1559 //
1560 minor = iminor(inode);
1561 if (minor >= hba_count) {
1562 return -ENXIO;
1563 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001564 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1566 if (pHba->unit == minor) {
1567 break; /* found adapter */
1568 }
1569 }
1570 if (pHba == NULL) {
Arjan van de Ven0b950672006-01-11 13:16:10 +01001571 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 return -ENXIO;
1573 }
1574
1575// if(pHba->in_use){
Arjan van de Ven0b950672006-01-11 13:16:10 +01001576 // mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577// return -EBUSY;
1578// }
1579
1580 pHba->in_use = 1;
Arjan van de Ven0b950672006-01-11 13:16:10 +01001581 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582
1583 return 0;
1584}
1585
1586static int adpt_close(struct inode *inode, struct file *file)
1587{
1588 int minor;
1589 adpt_hba* pHba;
1590
1591 minor = iminor(inode);
1592 if (minor >= hba_count) {
1593 return -ENXIO;
1594 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001595 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1597 if (pHba->unit == minor) {
1598 break; /* found adapter */
1599 }
1600 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001601 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 if (pHba == NULL) {
1603 return -ENXIO;
1604 }
1605
1606 pHba->in_use = 0;
1607
1608 return 0;
1609}
1610
1611
1612static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
1613{
1614 u32 msg[MAX_MESSAGE_SIZE];
1615 u32* reply = NULL;
1616 u32 size = 0;
1617 u32 reply_size = 0;
1618 u32 __user *user_msg = arg;
1619 u32 __user * user_reply = NULL;
1620 void *sg_list[pHba->sg_tablesize];
1621 u32 sg_offset = 0;
1622 u32 sg_count = 0;
1623 int sg_index = 0;
1624 u32 i = 0;
1625 u32 rcode = 0;
1626 void *p = NULL;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001627 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 ulong flags = 0;
1629
1630 memset(&msg, 0, MAX_MESSAGE_SIZE*4);
1631 // get user msg size in u32s
1632 if(get_user(size, &user_msg[0])){
1633 return -EFAULT;
1634 }
1635 size = size>>16;
1636
1637 user_reply = &user_msg[size];
1638 if(size > MAX_MESSAGE_SIZE){
1639 return -EFAULT;
1640 }
1641 size *= 4; // Convert to bytes
1642
1643 /* Copy in the user's I2O command */
1644 if(copy_from_user(msg, user_msg, size)) {
1645 return -EFAULT;
1646 }
1647 get_user(reply_size, &user_reply[0]);
1648 reply_size = reply_size>>16;
1649 if(reply_size > REPLY_FRAME_SIZE){
1650 reply_size = REPLY_FRAME_SIZE;
1651 }
1652 reply_size *= 4;
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301653 reply = kzalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 if(reply == NULL) {
1655 printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name);
1656 return -ENOMEM;
1657 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 sg_offset = (msg[0]>>4)&0xf;
1659 msg[2] = 0x40000000; // IOCTL context
1660 msg[3] = (u32)reply;
1661 memset(sg_list,0, sizeof(sg_list[0])*pHba->sg_tablesize);
1662 if(sg_offset) {
1663 // TODO 64bit fix
1664 struct sg_simple_element *sg = (struct sg_simple_element*) (msg+sg_offset);
1665 sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
1666 if (sg_count > pHba->sg_tablesize){
1667 printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", pHba->name,sg_count);
1668 kfree (reply);
1669 return -EINVAL;
1670 }
1671
1672 for(i = 0; i < sg_count; i++) {
1673 int sg_size;
1674
1675 if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) {
1676 printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",pHba->name,i, sg[i].flag_count);
1677 rcode = -EINVAL;
1678 goto cleanup;
1679 }
1680 sg_size = sg[i].flag_count & 0xffffff;
1681 /* Allocate memory for the transfer */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001682 p = dma_alloc_coherent(&pHba->pDev->dev, sg_size, &addr, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 if(!p) {
1684 printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
1685 pHba->name,sg_size,i,sg_count);
1686 rcode = -ENOMEM;
1687 goto cleanup;
1688 }
1689 sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
1690 /* Copy in the user's SG buffer if necessary */
1691 if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) {
1692 // TODO 64bit fix
1693 if (copy_from_user(p,(void __user *)sg[i].addr_bus, sg_size)) {
1694 printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",pHba->name,i);
1695 rcode = -EFAULT;
1696 goto cleanup;
1697 }
1698 }
1699 //TODO 64bit fix
1700 sg[i].addr_bus = (u32)virt_to_bus(p);
1701 }
1702 }
1703
1704 do {
1705 if(pHba->host)
1706 spin_lock_irqsave(pHba->host->host_lock, flags);
1707 // This state stops any new commands from enterring the
1708 // controller while processing the ioctl
1709// pHba->state |= DPTI_STATE_IOCTL;
1710// We can't set this now - The scsi subsystem sets host_blocked and
1711// the queue empties and stops. We need a way to restart the queue
1712 rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER);
1713 if (rcode != 0)
1714 printk("adpt_i2o_passthru: post wait failed %d %p\n",
1715 rcode, reply);
1716// pHba->state &= ~DPTI_STATE_IOCTL;
1717 if(pHba->host)
1718 spin_unlock_irqrestore(pHba->host->host_lock, flags);
1719 } while(rcode == -ETIMEDOUT);
1720
1721 if(rcode){
1722 goto cleanup;
1723 }
1724
1725 if(sg_offset) {
1726 /* Copy back the Scatter Gather buffers back to user space */
1727 u32 j;
1728 // TODO 64bit fix
1729 struct sg_simple_element* sg;
1730 int sg_size;
1731
1732 // re-acquire the original message to handle correctly the sg copy operation
1733 memset(&msg, 0, MAX_MESSAGE_SIZE*4);
1734 // get user msg size in u32s
1735 if(get_user(size, &user_msg[0])){
1736 rcode = -EFAULT;
1737 goto cleanup;
1738 }
1739 size = size>>16;
1740 size *= 4;
1741 /* Copy in the user's I2O command */
1742 if (copy_from_user (msg, user_msg, size)) {
1743 rcode = -EFAULT;
1744 goto cleanup;
1745 }
1746 sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
1747
1748 // TODO 64bit fix
1749 sg = (struct sg_simple_element*)(msg + sg_offset);
1750 for (j = 0; j < sg_count; j++) {
1751 /* Copy out the SG list to user's buffer if necessary */
1752 if(! (sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) {
1753 sg_size = sg[j].flag_count & 0xffffff;
1754 // TODO 64bit fix
1755 if (copy_to_user((void __user *)sg[j].addr_bus,sg_list[j], sg_size)) {
1756 printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",pHba->name, sg_list[j], sg[j].addr_bus);
1757 rcode = -EFAULT;
1758 goto cleanup;
1759 }
1760 }
1761 }
1762 }
1763
1764 /* Copy back the reply to user space */
1765 if (reply_size) {
1766 // we wrote our own values for context - now restore the user supplied ones
1767 if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) {
1768 printk(KERN_WARNING"%s: Could not copy message context FROM user\n",pHba->name);
1769 rcode = -EFAULT;
1770 }
1771 if(copy_to_user(user_reply, reply, reply_size)) {
1772 printk(KERN_WARNING"%s: Could not copy reply TO user\n",pHba->name);
1773 rcode = -EFAULT;
1774 }
1775 }
1776
1777
1778cleanup:
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001779 if (rcode != -ETIME && rcode != -EINTR) {
1780 struct sg_simple_element *sg =
1781 (struct sg_simple_element*) (msg +sg_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 kfree (reply);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001783 while(sg_index) {
1784 if(sg_list[--sg_index]) {
1785 dma_free_coherent(&pHba->pDev->dev,
1786 sg[sg_index].flag_count & 0xffffff,
1787 sg_list[sg_index],
1788 sg[sg_index].addr_bus);
1789 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 }
1791 }
1792 return rcode;
1793}
1794
1795
1796/*
1797 * This routine returns information about the system. This does not effect
1798 * any logic and if the info is wrong - it doesn't matter.
1799 */
1800
1801/* Get all the info we can not get from kernel services */
1802static int adpt_system_info(void __user *buffer)
1803{
1804 sysInfo_S si;
1805
1806 memset(&si, 0, sizeof(si));
1807
1808 si.osType = OS_LINUX;
Adrian Bunka4cd16e2005-06-25 14:59:01 -07001809 si.osMajorVersion = 0;
1810 si.osMinorVersion = 0;
1811 si.osRevision = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 si.busType = SI_PCI_BUS;
1813 si.processorFamily = DPTI_sig.dsProcessorFamily;
1814
1815#if defined __i386__
1816 adpt_i386_info(&si);
1817#elif defined (__ia64__)
1818 adpt_ia64_info(&si);
1819#elif defined(__sparc__)
1820 adpt_sparc_info(&si);
1821#elif defined (__alpha__)
1822 adpt_alpha_info(&si);
1823#else
1824 si.processorType = 0xff ;
1825#endif
1826 if(copy_to_user(buffer, &si, sizeof(si))){
1827 printk(KERN_WARNING"dpti: Could not copy buffer TO user\n");
1828 return -EFAULT;
1829 }
1830
1831 return 0;
1832}
1833
1834#if defined __ia64__
1835static void adpt_ia64_info(sysInfo_S* si)
1836{
1837 // This is all the info we need for now
1838 // We will add more info as our new
1839 // managmenent utility requires it
1840 si->processorType = PROC_IA64;
1841}
1842#endif
1843
1844
1845#if defined __sparc__
1846static void adpt_sparc_info(sysInfo_S* si)
1847{
1848 // This is all the info we need for now
1849 // We will add more info as our new
1850 // managmenent utility requires it
1851 si->processorType = PROC_ULTRASPARC;
1852}
1853#endif
1854
1855#if defined __alpha__
1856static void adpt_alpha_info(sysInfo_S* si)
1857{
1858 // This is all the info we need for now
1859 // We will add more info as our new
1860 // managmenent utility requires it
1861 si->processorType = PROC_ALPHA;
1862}
1863#endif
1864
1865#if defined __i386__
1866
1867static void adpt_i386_info(sysInfo_S* si)
1868{
1869 // This is all the info we need for now
1870 // We will add more info as our new
1871 // managmenent utility requires it
1872 switch (boot_cpu_data.x86) {
1873 case CPU_386:
1874 si->processorType = PROC_386;
1875 break;
1876 case CPU_486:
1877 si->processorType = PROC_486;
1878 break;
1879 case CPU_586:
1880 si->processorType = PROC_PENTIUM;
1881 break;
1882 default: // Just in case
1883 si->processorType = PROC_PENTIUM;
1884 break;
1885 }
1886}
1887
1888#endif
1889
1890
1891static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
1892 ulong arg)
1893{
1894 int minor;
1895 int error = 0;
1896 adpt_hba* pHba;
1897 ulong flags = 0;
1898 void __user *argp = (void __user *)arg;
1899
1900 minor = iminor(inode);
1901 if (minor >= DPTI_MAX_HBA){
1902 return -ENXIO;
1903 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001904 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1906 if (pHba->unit == minor) {
1907 break; /* found adapter */
1908 }
1909 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001910 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 if(pHba == NULL){
1912 return -ENXIO;
1913 }
1914
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001915 while((volatile u32) pHba->state & DPTI_STATE_RESET )
1916 schedule_timeout_uninterruptible(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
1918 switch (cmd) {
1919 // TODO: handle 3 cases
1920 case DPT_SIGNATURE:
1921 if (copy_to_user(argp, &DPTI_sig, sizeof(DPTI_sig))) {
1922 return -EFAULT;
1923 }
1924 break;
1925 case I2OUSRCMD:
1926 return adpt_i2o_passthru(pHba, argp);
1927
1928 case DPT_CTRLINFO:{
1929 drvrHBAinfo_S HbaInfo;
1930
1931#define FLG_OSD_PCI_VALID 0x0001
1932#define FLG_OSD_DMA 0x0002
1933#define FLG_OSD_I2O 0x0004
1934 memset(&HbaInfo, 0, sizeof(HbaInfo));
1935 HbaInfo.drvrHBAnum = pHba->unit;
1936 HbaInfo.baseAddr = (ulong) pHba->base_addr_phys;
1937 HbaInfo.blinkState = adpt_read_blink_led(pHba);
1938 HbaInfo.pciBusNum = pHba->pDev->bus->number;
1939 HbaInfo.pciDeviceNum=PCI_SLOT(pHba->pDev->devfn);
1940 HbaInfo.Interrupt = pHba->pDev->irq;
1941 HbaInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O;
1942 if(copy_to_user(argp, &HbaInfo, sizeof(HbaInfo))){
1943 printk(KERN_WARNING"%s: Could not copy HbaInfo TO user\n",pHba->name);
1944 return -EFAULT;
1945 }
1946 break;
1947 }
1948 case DPT_SYSINFO:
1949 return adpt_system_info(argp);
1950 case DPT_BLINKLED:{
1951 u32 value;
1952 value = (u32)adpt_read_blink_led(pHba);
1953 if (copy_to_user(argp, &value, sizeof(value))) {
1954 return -EFAULT;
1955 }
1956 break;
1957 }
1958 case I2ORESETCMD:
1959 if(pHba->host)
1960 spin_lock_irqsave(pHba->host->host_lock, flags);
1961 adpt_hba_reset(pHba);
1962 if(pHba->host)
1963 spin_unlock_irqrestore(pHba->host->host_lock, flags);
1964 break;
1965 case I2ORESCANCMD:
1966 adpt_rescan(pHba);
1967 break;
1968 default:
1969 return -EINVAL;
1970 }
1971
1972 return error;
1973}
1974
1975
David Howells7d12e782006-10-05 14:55:46 +01001976static irqreturn_t adpt_isr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977{
1978 struct scsi_cmnd* cmd;
1979 adpt_hba* pHba = dev_id;
1980 u32 m;
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07001981 void __iomem *reply;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 u32 status=0;
1983 u32 context;
1984 ulong flags = 0;
1985 int handled = 0;
1986
1987 if (pHba == NULL){
1988 printk(KERN_WARNING"adpt_isr: NULL dev_id\n");
1989 return IRQ_NONE;
1990 }
1991 if(pHba->host)
1992 spin_lock_irqsave(pHba->host->host_lock, flags);
1993
1994 while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) {
1995 m = readl(pHba->reply_port);
1996 if(m == EMPTY_QUEUE){
1997 // Try twice then give up
1998 rmb();
1999 m = readl(pHba->reply_port);
2000 if(m == EMPTY_QUEUE){
2001 // This really should not happen
2002 printk(KERN_ERR"dpti: Could not get reply frame\n");
2003 goto out;
2004 }
2005 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002006 if (pHba->reply_pool_pa <= m &&
2007 m < pHba->reply_pool_pa +
2008 (pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4)) {
2009 reply = (u8 *)pHba->reply_pool +
2010 (m - pHba->reply_pool_pa);
2011 } else {
2012 /* Ick, we should *never* be here */
2013 printk(KERN_ERR "dpti: reply frame not from pool\n");
2014 reply = (u8 *)bus_to_virt(m);
2015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016
2017 if (readl(reply) & MSG_FAIL) {
2018 u32 old_m = readl(reply+28);
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002019 void __iomem *msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 u32 old_context;
2021 PDEBUG("%s: Failed message\n",pHba->name);
2022 if(old_m >= 0x100000){
2023 printk(KERN_ERR"%s: Bad preserved MFA (%x)- dropping frame\n",pHba->name,old_m);
2024 writel(m,pHba->reply_port);
2025 continue;
2026 }
2027 // Transaction context is 0 in failed reply frame
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002028 msg = pHba->msg_addr_virt + old_m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 old_context = readl(msg+12);
2030 writel(old_context, reply+12);
2031 adpt_send_nop(pHba, old_m);
2032 }
2033 context = readl(reply+8);
2034 if(context & 0x40000000){ // IOCTL
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002035 void *p = (void *)readl(reply+12);
2036 if( p != NULL) {
2037 memcpy_fromio(p, reply, REPLY_FRAME_SIZE * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 }
2039 // All IOCTLs will also be post wait
2040 }
2041 if(context & 0x80000000){ // Post wait message
2042 status = readl(reply+16);
2043 if(status >> 24){
2044 status &= 0xffff; /* Get detail status */
2045 } else {
2046 status = I2O_POST_WAIT_OK;
2047 }
2048 if(!(context & 0x40000000)) {
2049 cmd = (struct scsi_cmnd*) readl(reply+12);
2050 if(cmd != NULL) {
2051 printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context);
2052 }
2053 }
2054 adpt_i2o_post_wait_complete(context, status);
2055 } else { // SCSI message
2056 cmd = (struct scsi_cmnd*) readl(reply+12);
2057 if(cmd != NULL){
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002058 scsi_dma_unmap(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 if(cmd->serial_number != 0) { // If not timedout
2060 adpt_i2o_to_scsi(reply, cmd);
2061 }
2062 }
2063 }
2064 writel(m, pHba->reply_port);
2065 wmb();
2066 rmb();
2067 }
2068 handled = 1;
2069out: if(pHba->host)
2070 spin_unlock_irqrestore(pHba->host->host_lock, flags);
2071 return IRQ_RETVAL(handled);
2072}
2073
2074static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* d)
2075{
2076 int i;
2077 u32 msg[MAX_MESSAGE_SIZE];
2078 u32* mptr;
2079 u32 *lenptr;
2080 int direction;
2081 int scsidir;
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002082 int nseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 u32 len;
2084 u32 reqlen;
2085 s32 rcode;
2086
2087 memset(msg, 0 , sizeof(msg));
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002088 len = scsi_bufflen(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 direction = 0x00000000;
2090
2091 scsidir = 0x00000000; // DATA NO XFER
2092 if(len) {
2093 /*
2094 * Set SCBFlags to indicate if data is being transferred
2095 * in or out, or no data transfer
2096 * Note: Do not have to verify index is less than 0 since
2097 * cmd->cmnd[0] is an unsigned char
2098 */
2099 switch(cmd->sc_data_direction){
2100 case DMA_FROM_DEVICE:
2101 scsidir =0x40000000; // DATA IN (iop<--dev)
2102 break;
2103 case DMA_TO_DEVICE:
2104 direction=0x04000000; // SGL OUT
2105 scsidir =0x80000000; // DATA OUT (iop-->dev)
2106 break;
2107 case DMA_NONE:
2108 break;
2109 case DMA_BIDIRECTIONAL:
2110 scsidir =0x40000000; // DATA IN (iop<--dev)
2111 // Assume In - and continue;
2112 break;
2113 default:
2114 printk(KERN_WARNING"%s: scsi opcode 0x%x not supported.\n",
2115 pHba->name, cmd->cmnd[0]);
2116 cmd->result = (DID_OK <<16) | (INITIATOR_ERROR << 8);
2117 cmd->scsi_done(cmd);
2118 return 0;
2119 }
2120 }
2121 // msg[0] is set later
2122 // I2O_CMD_SCSI_EXEC
2123 msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid);
2124 msg[2] = 0;
2125 msg[3] = (u32)cmd; /* We want the SCSI control block back */
2126 // Our cards use the transaction context as the tag for queueing
2127 // Adaptec/DPT Private stuff
2128 msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16);
2129 msg[5] = d->tid;
2130 /* Direction, disconnect ok | sense data | simple queue , CDBLen */
2131 // I2O_SCB_FLAG_ENABLE_DISCONNECT |
2132 // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG |
2133 // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;
2134 msg[6] = scsidir|0x20a00000|cmd->cmd_len;
2135
2136 mptr=msg+7;
2137
2138 // Write SCSI command into the message - always 16 byte block
2139 memset(mptr, 0, 16);
2140 memcpy(mptr, cmd->cmnd, cmd->cmd_len);
2141 mptr+=4;
2142 lenptr=mptr++; /* Remember me - fill in when we know */
2143 reqlen = 14; // SINGLE SGE
2144 /* Now fill in the SGList and command */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002146 nseg = scsi_dma_map(cmd);
2147 BUG_ON(nseg < 0);
2148 if (nseg) {
2149 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150
2151 len = 0;
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002152 scsi_for_each_sg(cmd, sg, nseg, i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 *mptr++ = direction|0x10000000|sg_dma_len(sg);
2154 len+=sg_dma_len(sg);
2155 *mptr++ = sg_dma_address(sg);
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002156 /* Make this an end of list */
2157 if (i == nseg - 1)
2158 mptr[-2] = direction|0xD0000000|sg_dma_len(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 reqlen = mptr - msg;
2161 *lenptr = len;
2162
2163 if(cmd->underflow && len != cmd->underflow){
2164 printk(KERN_WARNING"Cmd len %08X Cmd underflow %08X\n",
2165 len, cmd->underflow);
2166 }
2167 } else {
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002168 *lenptr = len = 0;
2169 reqlen = 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 }
2171
2172 /* Stick the headers on */
2173 msg[0] = reqlen<<16 | ((reqlen > 12) ? SGL_OFFSET_12 : SGL_OFFSET_0);
2174
2175 // Send it on it's way
2176 rcode = adpt_i2o_post_this(pHba, msg, reqlen<<2);
2177 if (rcode == 0) {
2178 return 0;
2179 }
2180 return rcode;
2181}
2182
2183
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002184static s32 adpt_scsi_host_alloc(adpt_hba* pHba, struct scsi_host_template *sht)
Andrew Morton24601bb2007-12-10 15:49:20 -08002185{
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002186 struct Scsi_Host *host;
Andrew Morton24601bb2007-12-10 15:49:20 -08002187
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002188 host = scsi_host_alloc(sht, sizeof(adpt_hba*));
Andrew Morton24601bb2007-12-10 15:49:20 -08002189 if (host == NULL) {
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002190 printk("%s: scsi_host_alloc returned NULL\n", pHba->name);
Andrew Morton24601bb2007-12-10 15:49:20 -08002191 return -1;
2192 }
2193 host->hostdata[0] = (unsigned long)pHba;
2194 pHba->host = host;
2195
2196 host->irq = pHba->pDev->irq;
2197 /* no IO ports, so don't have to set host->io_port and
2198 * host->n_io_port
2199 */
2200 host->io_port = 0;
2201 host->n_io_port = 0;
2202 /* see comments in scsi_host.h */
2203 host->max_id = 16;
2204 host->max_lun = 256;
2205 host->max_channel = pHba->top_scsi_channel + 1;
2206 host->cmd_per_lun = 1;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002207 host->unique_id = (u32)sys_tbl_pa + pHba->unit;
Andrew Morton24601bb2007-12-10 15:49:20 -08002208 host->sg_tablesize = pHba->sg_tablesize;
2209 host->can_queue = pHba->post_fifo_size;
2210
2211 return 0;
2212}
2213
2214
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002215static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216{
2217 adpt_hba* pHba;
2218 u32 hba_status;
2219 u32 dev_status;
2220 u32 reply_flags = readl(reply) & 0xff00; // Leave it shifted up 8 bits
2221 // I know this would look cleaner if I just read bytes
2222 // but the model I have been using for all the rest of the
2223 // io is in 4 byte words - so I keep that model
2224 u16 detailed_status = readl(reply+16) &0xffff;
2225 dev_status = (detailed_status & 0xff);
2226 hba_status = detailed_status >> 8;
2227
2228 // calculate resid for sg
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002229 scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+5));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230
2231 pHba = (adpt_hba*) cmd->device->host->hostdata[0];
2232
2233 cmd->sense_buffer[0] = '\0'; // initialize sense valid flag to false
2234
2235 if(!(reply_flags & MSG_FAIL)) {
2236 switch(detailed_status & I2O_SCSI_DSC_MASK) {
2237 case I2O_SCSI_DSC_SUCCESS:
2238 cmd->result = (DID_OK << 16);
2239 // handle underflow
2240 if(readl(reply+5) < cmd->underflow ) {
2241 cmd->result = (DID_ERROR <<16);
2242 printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name);
2243 }
2244 break;
2245 case I2O_SCSI_DSC_REQUEST_ABORTED:
2246 cmd->result = (DID_ABORT << 16);
2247 break;
2248 case I2O_SCSI_DSC_PATH_INVALID:
2249 case I2O_SCSI_DSC_DEVICE_NOT_PRESENT:
2250 case I2O_SCSI_DSC_SELECTION_TIMEOUT:
2251 case I2O_SCSI_DSC_COMMAND_TIMEOUT:
2252 case I2O_SCSI_DSC_NO_ADAPTER:
2253 case I2O_SCSI_DSC_RESOURCE_UNAVAILABLE:
2254 printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%d) hba status=0x%x, dev status=0x%x, cmd=0x%x\n",
2255 pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]);
2256 cmd->result = (DID_TIME_OUT << 16);
2257 break;
2258 case I2O_SCSI_DSC_ADAPTER_BUSY:
2259 case I2O_SCSI_DSC_BUS_BUSY:
2260 cmd->result = (DID_BUS_BUSY << 16);
2261 break;
2262 case I2O_SCSI_DSC_SCSI_BUS_RESET:
2263 case I2O_SCSI_DSC_BDR_MESSAGE_SENT:
2264 cmd->result = (DID_RESET << 16);
2265 break;
2266 case I2O_SCSI_DSC_PARITY_ERROR_FAILURE:
2267 printk(KERN_WARNING"%s: SCSI CMD parity error\n",pHba->name);
2268 cmd->result = (DID_PARITY << 16);
2269 break;
2270 case I2O_SCSI_DSC_UNABLE_TO_ABORT:
2271 case I2O_SCSI_DSC_COMPLETE_WITH_ERROR:
2272 case I2O_SCSI_DSC_UNABLE_TO_TERMINATE:
2273 case I2O_SCSI_DSC_MR_MESSAGE_RECEIVED:
2274 case I2O_SCSI_DSC_AUTOSENSE_FAILED:
2275 case I2O_SCSI_DSC_DATA_OVERRUN:
2276 case I2O_SCSI_DSC_UNEXPECTED_BUS_FREE:
2277 case I2O_SCSI_DSC_SEQUENCE_FAILURE:
2278 case I2O_SCSI_DSC_REQUEST_LENGTH_ERROR:
2279 case I2O_SCSI_DSC_PROVIDE_FAILURE:
2280 case I2O_SCSI_DSC_REQUEST_TERMINATED:
2281 case I2O_SCSI_DSC_IDE_MESSAGE_SENT:
2282 case I2O_SCSI_DSC_UNACKNOWLEDGED_EVENT:
2283 case I2O_SCSI_DSC_MESSAGE_RECEIVED:
2284 case I2O_SCSI_DSC_INVALID_CDB:
2285 case I2O_SCSI_DSC_LUN_INVALID:
2286 case I2O_SCSI_DSC_SCSI_TID_INVALID:
2287 case I2O_SCSI_DSC_FUNCTION_UNAVAILABLE:
2288 case I2O_SCSI_DSC_NO_NEXUS:
2289 case I2O_SCSI_DSC_CDB_RECEIVED:
2290 case I2O_SCSI_DSC_LUN_ALREADY_ENABLED:
2291 case I2O_SCSI_DSC_QUEUE_FROZEN:
2292 case I2O_SCSI_DSC_REQUEST_INVALID:
2293 default:
2294 printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
2295 pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun,
2296 hba_status, dev_status, cmd->cmnd[0]);
2297 cmd->result = (DID_ERROR << 16);
2298 break;
2299 }
2300
2301 // copy over the request sense data if it was a check
2302 // condition status
Salyzyn, Markd814c512008-01-14 11:04:40 -08002303 if (dev_status == SAM_STAT_CHECK_CONDITION) {
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +09002304 u32 len = min(SCSI_SENSE_BUFFERSIZE, 40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 // Copy over the sense data
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002306 memcpy_fromio(cmd->sense_buffer, (reply+28) , len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 if(cmd->sense_buffer[0] == 0x70 /* class 7 */ &&
2308 cmd->sense_buffer[2] == DATA_PROTECT ){
2309 /* This is to handle an array failed */
2310 cmd->result = (DID_TIME_OUT << 16);
2311 printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
2312 pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun,
2313 hba_status, dev_status, cmd->cmnd[0]);
2314
2315 }
2316 }
2317 } else {
2318 /* In this condtion we could not talk to the tid
2319 * the card rejected it. We should signal a retry
2320 * for a limitted number of retries.
2321 */
2322 cmd->result = (DID_TIME_OUT << 16);
2323 printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%d) tid=%d, cmd=0x%x\n",
2324 pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun,
2325 ((struct adpt_device*)(cmd->device->hostdata))->tid, cmd->cmnd[0]);
2326 }
2327
2328 cmd->result |= (dev_status);
2329
2330 if(cmd->scsi_done != NULL){
2331 cmd->scsi_done(cmd);
2332 }
2333 return cmd->result;
2334}
2335
2336
2337static s32 adpt_rescan(adpt_hba* pHba)
2338{
2339 s32 rcode;
2340 ulong flags = 0;
2341
2342 if(pHba->host)
2343 spin_lock_irqsave(pHba->host->host_lock, flags);
2344 if ((rcode=adpt_i2o_lct_get(pHba)) < 0)
2345 goto out;
2346 if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0)
2347 goto out;
2348 rcode = 0;
2349out: if(pHba->host)
2350 spin_unlock_irqrestore(pHba->host->host_lock, flags);
2351 return rcode;
2352}
2353
2354
2355static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
2356{
2357 int i;
2358 int max;
2359 int tid;
2360 struct i2o_device *d;
2361 i2o_lct *lct = pHba->lct;
2362 u8 bus_no = 0;
2363 s16 scsi_id;
2364 s16 scsi_lun;
2365 u32 buf[10]; // at least 8 u32's
2366 struct adpt_device* pDev = NULL;
2367 struct i2o_device* pI2o_dev = NULL;
2368
2369 if (lct == NULL) {
2370 printk(KERN_ERR "%s: LCT is empty???\n",pHba->name);
2371 return -1;
2372 }
2373
2374 max = lct->table_size;
2375 max -= 3;
2376 max /= 9;
2377
2378 // Mark each drive as unscanned
2379 for (d = pHba->devices; d; d = d->next) {
2380 pDev =(struct adpt_device*) d->owner;
2381 if(!pDev){
2382 continue;
2383 }
2384 pDev->state |= DPTI_DEV_UNSCANNED;
2385 }
2386
2387 printk(KERN_INFO "%s: LCT has %d entries.\n", pHba->name,max);
2388
2389 for(i=0;i<max;i++) {
2390 if( lct->lct_entry[i].user_tid != 0xfff){
2391 continue;
2392 }
2393
2394 if( lct->lct_entry[i].class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE ||
2395 lct->lct_entry[i].class_id == I2O_CLASS_SCSI_PERIPHERAL ||
2396 lct->lct_entry[i].class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
2397 tid = lct->lct_entry[i].tid;
2398 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) {
2399 printk(KERN_ERR"%s: Could not query device\n",pHba->name);
2400 continue;
2401 }
2402 bus_no = buf[0]>>16;
2403 scsi_id = buf[1];
2404 scsi_lun = (buf[2]>>8 )&0xff;
2405 pDev = pHba->channel[bus_no].device[scsi_id];
2406 /* da lun */
2407 while(pDev) {
2408 if(pDev->scsi_lun == scsi_lun) {
2409 break;
2410 }
2411 pDev = pDev->next_lun;
2412 }
2413 if(!pDev ) { // Something new add it
Robert P. J. Day5cbded52006-12-13 00:35:56 -08002414 d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 if(d==NULL)
2416 {
2417 printk(KERN_CRIT "Out of memory for I2O device data.\n");
2418 return -ENOMEM;
2419 }
2420
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002421 d->controller = pHba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 d->next = NULL;
2423
2424 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
2425
2426 d->flags = 0;
2427 adpt_i2o_report_hba_unit(pHba, d);
2428 adpt_i2o_install_device(pHba, d);
2429
2430 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
2431 printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no);
2432 continue;
2433 }
2434 pDev = pHba->channel[bus_no].device[scsi_id];
2435 if( pDev == NULL){
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05302436 pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 if(pDev == NULL) {
2438 return -ENOMEM;
2439 }
2440 pHba->channel[bus_no].device[scsi_id] = pDev;
2441 } else {
2442 while (pDev->next_lun) {
2443 pDev = pDev->next_lun;
2444 }
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05302445 pDev = pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 if(pDev == NULL) {
2447 return -ENOMEM;
2448 }
2449 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 pDev->tid = d->lct_data.tid;
2451 pDev->scsi_channel = bus_no;
2452 pDev->scsi_id = scsi_id;
2453 pDev->scsi_lun = scsi_lun;
2454 pDev->pI2o_dev = d;
2455 d->owner = pDev;
2456 pDev->type = (buf[0])&0xff;
2457 pDev->flags = (buf[0]>>8)&0xff;
2458 // Too late, SCSI system has made up it's mind, but what the hey ...
2459 if(scsi_id > pHba->top_scsi_id){
2460 pHba->top_scsi_id = scsi_id;
2461 }
2462 if(scsi_lun > pHba->top_scsi_lun){
2463 pHba->top_scsi_lun = scsi_lun;
2464 }
2465 continue;
2466 } // end of new i2o device
2467
2468 // We found an old device - check it
2469 while(pDev) {
2470 if(pDev->scsi_lun == scsi_lun) {
2471 if(!scsi_device_online(pDev->pScsi_dev)) {
2472 printk(KERN_WARNING"%s: Setting device (%d,%d,%d) back online\n",
2473 pHba->name,bus_no,scsi_id,scsi_lun);
2474 if (pDev->pScsi_dev) {
2475 scsi_device_set_state(pDev->pScsi_dev, SDEV_RUNNING);
2476 }
2477 }
2478 d = pDev->pI2o_dev;
2479 if(d->lct_data.tid != tid) { // something changed
2480 pDev->tid = tid;
2481 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
2482 if (pDev->pScsi_dev) {
2483 pDev->pScsi_dev->changed = TRUE;
2484 pDev->pScsi_dev->removable = TRUE;
2485 }
2486 }
2487 // Found it - mark it scanned
2488 pDev->state = DPTI_DEV_ONLINE;
2489 break;
2490 }
2491 pDev = pDev->next_lun;
2492 }
2493 }
2494 }
2495 for (pI2o_dev = pHba->devices; pI2o_dev; pI2o_dev = pI2o_dev->next) {
2496 pDev =(struct adpt_device*) pI2o_dev->owner;
2497 if(!pDev){
2498 continue;
2499 }
2500 // Drive offline drives that previously existed but could not be found
2501 // in the LCT table
2502 if (pDev->state & DPTI_DEV_UNSCANNED){
2503 pDev->state = DPTI_DEV_OFFLINE;
2504 printk(KERN_WARNING"%s: Device (%d,%d,%d) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun);
2505 if (pDev->pScsi_dev) {
2506 scsi_device_set_state(pDev->pScsi_dev, SDEV_OFFLINE);
2507 }
2508 }
2509 }
2510 return 0;
2511}
2512
2513static void adpt_fail_posted_scbs(adpt_hba* pHba)
2514{
2515 struct scsi_cmnd* cmd = NULL;
2516 struct scsi_device* d = NULL;
2517
2518 shost_for_each_device(d, pHba->host) {
2519 unsigned long flags;
2520 spin_lock_irqsave(&d->list_lock, flags);
2521 list_for_each_entry(cmd, &d->cmd_list, list) {
2522 if(cmd->serial_number == 0){
2523 continue;
2524 }
2525 cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1);
2526 cmd->scsi_done(cmd);
2527 }
2528 spin_unlock_irqrestore(&d->list_lock, flags);
2529 }
2530}
2531
2532
2533/*============================================================================
2534 * Routines from i2o subsystem
2535 *============================================================================
2536 */
2537
2538
2539
2540/*
2541 * Bring an I2O controller into HOLD state. See the spec.
2542 */
2543static int adpt_i2o_activate_hba(adpt_hba* pHba)
2544{
2545 int rcode;
2546
2547 if(pHba->initialized ) {
2548 if (adpt_i2o_status_get(pHba) < 0) {
2549 if((rcode = adpt_i2o_reset_hba(pHba)) != 0){
2550 printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name);
2551 return rcode;
2552 }
2553 if (adpt_i2o_status_get(pHba) < 0) {
2554 printk(KERN_INFO "HBA not responding.\n");
2555 return -1;
2556 }
2557 }
2558
2559 if(pHba->status_block->iop_state == ADAPTER_STATE_FAULTED) {
2560 printk(KERN_CRIT "%s: hardware fault\n", pHba->name);
2561 return -1;
2562 }
2563
2564 if (pHba->status_block->iop_state == ADAPTER_STATE_READY ||
2565 pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
2566 pHba->status_block->iop_state == ADAPTER_STATE_HOLD ||
2567 pHba->status_block->iop_state == ADAPTER_STATE_FAILED) {
2568 adpt_i2o_reset_hba(pHba);
2569 if (adpt_i2o_status_get(pHba) < 0 || pHba->status_block->iop_state != ADAPTER_STATE_RESET) {
2570 printk(KERN_ERR "%s: Failed to initialize.\n", pHba->name);
2571 return -1;
2572 }
2573 }
2574 } else {
2575 if((rcode = adpt_i2o_reset_hba(pHba)) != 0){
2576 printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name);
2577 return rcode;
2578 }
2579
2580 }
2581
2582 if (adpt_i2o_init_outbound_q(pHba) < 0) {
2583 return -1;
2584 }
2585
2586 /* In HOLD state */
2587
2588 if (adpt_i2o_hrt_get(pHba) < 0) {
2589 return -1;
2590 }
2591
2592 return 0;
2593}
2594
2595/*
2596 * Bring a controller online into OPERATIONAL state.
2597 */
2598
2599static int adpt_i2o_online_hba(adpt_hba* pHba)
2600{
2601 if (adpt_i2o_systab_send(pHba) < 0) {
2602 adpt_i2o_delete_hba(pHba);
2603 return -1;
2604 }
2605 /* In READY state */
2606
2607 if (adpt_i2o_enable_hba(pHba) < 0) {
2608 adpt_i2o_delete_hba(pHba);
2609 return -1;
2610 }
2611
2612 /* In OPERATIONAL state */
2613 return 0;
2614}
2615
2616static s32 adpt_send_nop(adpt_hba*pHba,u32 m)
2617{
2618 u32 __iomem *msg;
2619 ulong timeout = jiffies + 5*HZ;
2620
2621 while(m == EMPTY_QUEUE){
2622 rmb();
2623 m = readl(pHba->post_port);
2624 if(m != EMPTY_QUEUE){
2625 break;
2626 }
2627 if(time_after(jiffies,timeout)){
2628 printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name);
2629 return 2;
2630 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002631 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 }
2633 msg = (u32 __iomem *)(pHba->msg_addr_virt + m);
2634 writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]);
2635 writel( I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0,&msg[1]);
2636 writel( 0,&msg[2]);
2637 wmb();
2638
2639 writel(m, pHba->post_port);
2640 wmb();
2641 return 0;
2642}
2643
2644static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba)
2645{
2646 u8 *status;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002647 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 u32 __iomem *msg = NULL;
2649 int i;
2650 ulong timeout = jiffies + TMOUT_INITOUTBOUND*HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 u32 m;
2652
2653 do {
2654 rmb();
2655 m = readl(pHba->post_port);
2656 if (m != EMPTY_QUEUE) {
2657 break;
2658 }
2659
2660 if(time_after(jiffies,timeout)){
2661 printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name);
2662 return -ETIMEDOUT;
2663 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002664 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 } while(m == EMPTY_QUEUE);
2666
2667 msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
2668
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002669 status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002670 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671 adpt_send_nop(pHba, m);
2672 printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n",
2673 pHba->name);
2674 return -ENOMEM;
2675 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002676 memset(status, 0, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677
2678 writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]);
2679 writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]);
2680 writel(0, &msg[2]);
2681 writel(0x0106, &msg[3]); /* Transaction context */
2682 writel(4096, &msg[4]); /* Host page frame size */
2683 writel((REPLY_FRAME_SIZE)<<16|0x80, &msg[5]); /* Outbound msg frame size and Initcode */
2684 writel(0xD0000004, &msg[6]); /* Simple SG LE, EOB */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002685 writel((u32)addr, &msg[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686
2687 writel(m, pHba->post_port);
2688 wmb();
2689
2690 // Wait for the reply status to come back
2691 do {
2692 if (*status) {
2693 if (*status != 0x01 /*I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS*/) {
2694 break;
2695 }
2696 }
2697 rmb();
2698 if(time_after(jiffies,timeout)){
2699 printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002700 /* We lose 4 bytes of "status" here, but we
2701 cannot free these because controller may
2702 awake and corrupt those bytes at any time */
2703 /* dma_free_coherent(&pHba->pDev->dev, 4, status, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704 return -ETIMEDOUT;
2705 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002706 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 } while (1);
2708
2709 // If the command was successful, fill the fifo with our reply
2710 // message packets
2711 if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002712 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 return -2;
2714 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002715 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002717 if(pHba->reply_pool != NULL) {
2718 dma_free_coherent(&pHba->pDev->dev,
2719 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
2720 pHba->reply_pool, pHba->reply_pool_pa);
2721 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002723 pHba->reply_pool = dma_alloc_coherent(&pHba->pDev->dev,
2724 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
2725 &pHba->reply_pool_pa, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002726 if (!pHba->reply_pool) {
2727 printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name);
2728 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002730 memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 for(i = 0; i < pHba->reply_fifo_size; i++) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002733 writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4),
2734 pHba->reply_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 }
2737 adpt_i2o_status_get(pHba);
2738 return 0;
2739}
2740
2741
2742/*
2743 * I2O System Table. Contains information about
2744 * all the IOPs in the system. Used to inform IOPs
2745 * about each other's existence.
2746 *
2747 * sys_tbl_ver is the CurrentChangeIndicator that is
2748 * used by IOPs to track changes.
2749 */
2750
2751
2752
2753static s32 adpt_i2o_status_get(adpt_hba* pHba)
2754{
2755 ulong timeout;
2756 u32 m;
2757 u32 __iomem *msg;
2758 u8 *status_block=NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759
2760 if(pHba->status_block == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002761 pHba->status_block = dma_alloc_coherent(&pHba->pDev->dev,
2762 sizeof(i2o_status_block),
2763 &pHba->status_block_pa, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 if(pHba->status_block == NULL) {
2765 printk(KERN_ERR
2766 "dpti%d: Get Status Block failed; Out of memory. \n",
2767 pHba->unit);
2768 return -ENOMEM;
2769 }
2770 }
2771 memset(pHba->status_block, 0, sizeof(i2o_status_block));
2772 status_block = (u8*)(pHba->status_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 timeout = jiffies+TMOUT_GETSTATUS*HZ;
2774 do {
2775 rmb();
2776 m = readl(pHba->post_port);
2777 if (m != EMPTY_QUEUE) {
2778 break;
2779 }
2780 if(time_after(jiffies,timeout)){
2781 printk(KERN_ERR "%s: Timeout waiting for message !\n",
2782 pHba->name);
2783 return -ETIMEDOUT;
2784 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002785 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 } while(m==EMPTY_QUEUE);
2787
2788
2789 msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
2790
2791 writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]);
2792 writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]);
2793 writel(1, &msg[2]);
2794 writel(0, &msg[3]);
2795 writel(0, &msg[4]);
2796 writel(0, &msg[5]);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002797 writel( dma_low(pHba->status_block_pa), &msg[6]);
2798 writel( dma_high(pHba->status_block_pa), &msg[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 writel(sizeof(i2o_status_block), &msg[8]); // 88 bytes
2800
2801 //post message
2802 writel(m, pHba->post_port);
2803 wmb();
2804
2805 while(status_block[87]!=0xff){
2806 if(time_after(jiffies,timeout)){
2807 printk(KERN_ERR"dpti%d: Get status timeout.\n",
2808 pHba->unit);
2809 return -ETIMEDOUT;
2810 }
2811 rmb();
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002812 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 }
2814
2815 // Set up our number of outbound and inbound messages
2816 pHba->post_fifo_size = pHba->status_block->max_inbound_frames;
2817 if (pHba->post_fifo_size > MAX_TO_IOP_MESSAGES) {
2818 pHba->post_fifo_size = MAX_TO_IOP_MESSAGES;
2819 }
2820
2821 pHba->reply_fifo_size = pHba->status_block->max_outbound_frames;
2822 if (pHba->reply_fifo_size > MAX_FROM_IOP_MESSAGES) {
2823 pHba->reply_fifo_size = MAX_FROM_IOP_MESSAGES;
2824 }
2825
2826 // Calculate the Scatter Gather list size
2827 pHba->sg_tablesize = (pHba->status_block->inbound_frame_size * 4 -40)/ sizeof(struct sg_simple_element);
2828 if (pHba->sg_tablesize > SG_LIST_ELEMENTS) {
2829 pHba->sg_tablesize = SG_LIST_ELEMENTS;
2830 }
2831
2832
2833#ifdef DEBUG
2834 printk("dpti%d: State = ",pHba->unit);
2835 switch(pHba->status_block->iop_state) {
2836 case 0x01:
2837 printk("INIT\n");
2838 break;
2839 case 0x02:
2840 printk("RESET\n");
2841 break;
2842 case 0x04:
2843 printk("HOLD\n");
2844 break;
2845 case 0x05:
2846 printk("READY\n");
2847 break;
2848 case 0x08:
2849 printk("OPERATIONAL\n");
2850 break;
2851 case 0x10:
2852 printk("FAILED\n");
2853 break;
2854 case 0x11:
2855 printk("FAULTED\n");
2856 break;
2857 default:
2858 printk("%x (unknown!!)\n",pHba->status_block->iop_state);
2859 }
2860#endif
2861 return 0;
2862}
2863
2864/*
2865 * Get the IOP's Logical Configuration Table
2866 */
2867static int adpt_i2o_lct_get(adpt_hba* pHba)
2868{
2869 u32 msg[8];
2870 int ret;
2871 u32 buf[16];
2872
2873 if ((pHba->lct_size == 0) || (pHba->lct == NULL)){
2874 pHba->lct_size = pHba->status_block->expected_lct_size;
2875 }
2876 do {
2877 if (pHba->lct == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002878 pHba->lct = dma_alloc_coherent(&pHba->pDev->dev,
2879 pHba->lct_size, &pHba->lct_pa,
2880 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881 if(pHba->lct == NULL) {
2882 printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n",
2883 pHba->name);
2884 return -ENOMEM;
2885 }
2886 }
2887 memset(pHba->lct, 0, pHba->lct_size);
2888
2889 msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
2890 msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
2891 msg[2] = 0;
2892 msg[3] = 0;
2893 msg[4] = 0xFFFFFFFF; /* All devices */
2894 msg[5] = 0x00000000; /* Report now */
2895 msg[6] = 0xD0000000|pHba->lct_size;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002896 msg[7] = (u32)pHba->lct_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897
2898 if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 360))) {
2899 printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n",
2900 pHba->name, ret);
2901 printk(KERN_ERR"Adaptec: Error Reading Hardware.\n");
2902 return ret;
2903 }
2904
2905 if ((pHba->lct->table_size << 2) > pHba->lct_size) {
2906 pHba->lct_size = pHba->lct->table_size << 2;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002907 dma_free_coherent(&pHba->pDev->dev, pHba->lct_size,
2908 pHba->lct, pHba->lct_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909 pHba->lct = NULL;
2910 }
2911 } while (pHba->lct == NULL);
2912
2913 PDEBUG("%s: Hardware resource table read.\n", pHba->name);
2914
2915
2916 // I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO;
2917 if(adpt_i2o_query_scalar(pHba, 0 , 0x8000, -1, buf, sizeof(buf))>=0) {
2918 pHba->FwDebugBufferSize = buf[1];
2919 pHba->FwDebugBuffer_P = pHba->base_addr_virt + buf[0];
2920 pHba->FwDebugFlags_P = pHba->FwDebugBuffer_P + FW_DEBUG_FLAGS_OFFSET;
2921 pHba->FwDebugBLEDvalue_P = pHba->FwDebugBuffer_P + FW_DEBUG_BLED_OFFSET;
2922 pHba->FwDebugBLEDflag_P = pHba->FwDebugBLEDvalue_P + 1;
2923 pHba->FwDebugStrLength_P = pHba->FwDebugBuffer_P + FW_DEBUG_STR_LENGTH_OFFSET;
2924 pHba->FwDebugBuffer_P += buf[2];
2925 pHba->FwDebugFlags = 0;
2926 }
2927
2928 return 0;
2929}
2930
2931static int adpt_i2o_build_sys_table(void)
2932{
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002933 adpt_hba* pHba = hba_chain;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934 int count = 0;
2935
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002936 if (sys_tbl)
2937 dma_free_coherent(&pHba->pDev->dev, sys_tbl_len,
2938 sys_tbl, sys_tbl_pa);
2939
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs
2941 (hba_count) * sizeof(struct i2o_sys_tbl_entry);
2942
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002943 sys_tbl = dma_alloc_coherent(&pHba->pDev->dev,
2944 sys_tbl_len, &sys_tbl_pa, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002945 if (!sys_tbl) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 printk(KERN_WARNING "SysTab Set failed. Out of memory.\n");
2947 return -ENOMEM;
2948 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002949 memset(sys_tbl, 0, sys_tbl_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950
2951 sys_tbl->num_entries = hba_count;
2952 sys_tbl->version = I2OVERSION;
2953 sys_tbl->change_ind = sys_tbl_ind++;
2954
2955 for(pHba = hba_chain; pHba; pHba = pHba->next) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002956 u64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 // Get updated Status Block so we have the latest information
2958 if (adpt_i2o_status_get(pHba)) {
2959 sys_tbl->num_entries--;
2960 continue; // try next one
2961 }
2962
2963 sys_tbl->iops[count].org_id = pHba->status_block->org_id;
2964 sys_tbl->iops[count].iop_id = pHba->unit + 2;
2965 sys_tbl->iops[count].seg_num = 0;
2966 sys_tbl->iops[count].i2o_version = pHba->status_block->i2o_version;
2967 sys_tbl->iops[count].iop_state = pHba->status_block->iop_state;
2968 sys_tbl->iops[count].msg_type = pHba->status_block->msg_type;
2969 sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size;
2970 sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
2971 sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002972 addr = pHba->base_addr_phys + 0x40;
2973 sys_tbl->iops[count].inbound_low = dma_low(addr);
2974 sys_tbl->iops[count].inbound_high = dma_high(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975
2976 count++;
2977 }
2978
2979#ifdef DEBUG
2980{
2981 u32 *table = (u32*)sys_tbl;
2982 printk(KERN_DEBUG"sys_tbl_len=%d in 32bit words\n",(sys_tbl_len >>2));
2983 for(count = 0; count < (sys_tbl_len >>2); count++) {
2984 printk(KERN_INFO "sys_tbl[%d] = %0#10x\n",
2985 count, table[count]);
2986 }
2987}
2988#endif
2989
2990 return 0;
2991}
2992
2993
2994/*
2995 * Dump the information block associated with a given unit (TID)
2996 */
2997
2998static void adpt_i2o_report_hba_unit(adpt_hba* pHba, struct i2o_device *d)
2999{
3000 char buf[64];
3001 int unit = d->lct_data.tid;
3002
3003 printk(KERN_INFO "TID %3.3d ", unit);
3004
3005 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 3, buf, 16)>=0)
3006 {
3007 buf[16]=0;
3008 printk(" Vendor: %-12.12s", buf);
3009 }
3010 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 4, buf, 16)>=0)
3011 {
3012 buf[16]=0;
3013 printk(" Device: %-12.12s", buf);
3014 }
3015 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 6, buf, 8)>=0)
3016 {
3017 buf[8]=0;
3018 printk(" Rev: %-12.12s\n", buf);
3019 }
3020#ifdef DEBUG
3021 printk(KERN_INFO "\tClass: %.21s\n", adpt_i2o_get_class_name(d->lct_data.class_id));
3022 printk(KERN_INFO "\tSubclass: 0x%04X\n", d->lct_data.sub_class);
3023 printk(KERN_INFO "\tFlags: ");
3024
3025 if(d->lct_data.device_flags&(1<<0))
3026 printk("C"); // ConfigDialog requested
3027 if(d->lct_data.device_flags&(1<<1))
3028 printk("U"); // Multi-user capable
3029 if(!(d->lct_data.device_flags&(1<<4)))
3030 printk("P"); // Peer service enabled!
3031 if(!(d->lct_data.device_flags&(1<<5)))
3032 printk("M"); // Mgmt service enabled!
3033 printk("\n");
3034#endif
3035}
3036
3037#ifdef DEBUG
3038/*
3039 * Do i2o class name lookup
3040 */
3041static const char *adpt_i2o_get_class_name(int class)
3042{
3043 int idx = 16;
3044 static char *i2o_class_name[] = {
3045 "Executive",
3046 "Device Driver Module",
3047 "Block Device",
3048 "Tape Device",
3049 "LAN Interface",
3050 "WAN Interface",
3051 "Fibre Channel Port",
3052 "Fibre Channel Device",
3053 "SCSI Device",
3054 "ATE Port",
3055 "ATE Device",
3056 "Floppy Controller",
3057 "Floppy Device",
3058 "Secondary Bus Port",
3059 "Peer Transport Agent",
3060 "Peer Transport",
3061 "Unknown"
3062 };
3063
3064 switch(class&0xFFF) {
3065 case I2O_CLASS_EXECUTIVE:
3066 idx = 0; break;
3067 case I2O_CLASS_DDM:
3068 idx = 1; break;
3069 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
3070 idx = 2; break;
3071 case I2O_CLASS_SEQUENTIAL_STORAGE:
3072 idx = 3; break;
3073 case I2O_CLASS_LAN:
3074 idx = 4; break;
3075 case I2O_CLASS_WAN:
3076 idx = 5; break;
3077 case I2O_CLASS_FIBRE_CHANNEL_PORT:
3078 idx = 6; break;
3079 case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
3080 idx = 7; break;
3081 case I2O_CLASS_SCSI_PERIPHERAL:
3082 idx = 8; break;
3083 case I2O_CLASS_ATE_PORT:
3084 idx = 9; break;
3085 case I2O_CLASS_ATE_PERIPHERAL:
3086 idx = 10; break;
3087 case I2O_CLASS_FLOPPY_CONTROLLER:
3088 idx = 11; break;
3089 case I2O_CLASS_FLOPPY_DEVICE:
3090 idx = 12; break;
3091 case I2O_CLASS_BUS_ADAPTER_PORT:
3092 idx = 13; break;
3093 case I2O_CLASS_PEER_TRANSPORT_AGENT:
3094 idx = 14; break;
3095 case I2O_CLASS_PEER_TRANSPORT:
3096 idx = 15; break;
3097 }
3098 return i2o_class_name[idx];
3099}
3100#endif
3101
3102
3103static s32 adpt_i2o_hrt_get(adpt_hba* pHba)
3104{
3105 u32 msg[6];
3106 int ret, size = sizeof(i2o_hrt);
3107
3108 do {
3109 if (pHba->hrt == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003110 pHba->hrt = dma_alloc_coherent(&pHba->pDev->dev,
3111 size, &pHba->hrt_pa, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 if (pHba->hrt == NULL) {
3113 printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", pHba->name);
3114 return -ENOMEM;
3115 }
3116 }
3117
3118 msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
3119 msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
3120 msg[2]= 0;
3121 msg[3]= 0;
3122 msg[4]= (0xD0000000 | size); /* Simple transaction */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003123 msg[5]= (u32)pHba->hrt_pa; /* Dump it here */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124
3125 if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg),20))) {
3126 printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n", pHba->name, ret);
3127 return ret;
3128 }
3129
3130 if (pHba->hrt->num_entries * pHba->hrt->entry_len << 2 > size) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003131 int newsize = pHba->hrt->num_entries * pHba->hrt->entry_len << 2;
3132 dma_free_coherent(&pHba->pDev->dev, size,
3133 pHba->hrt, pHba->hrt_pa);
3134 size = newsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 pHba->hrt = NULL;
3136 }
3137 } while(pHba->hrt == NULL);
3138 return 0;
3139}
3140
3141/*
3142 * Query one scalar group value or a whole scalar group.
3143 */
3144static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid,
3145 int group, int field, void *buf, int buflen)
3146{
3147 u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003148 u8 *opblk_va;
3149 dma_addr_t opblk_pa;
3150 u8 *resblk_va;
3151 dma_addr_t resblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152
3153 int size;
3154
3155 /* 8 bytes for header */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003156 resblk_va = dma_alloc_coherent(&pHba->pDev->dev,
3157 sizeof(u8) * (8 + buflen), &resblk_pa, GFP_KERNEL);
3158 if (resblk_va == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name);
3160 return -ENOMEM;
3161 }
3162
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003163 opblk_va = dma_alloc_coherent(&pHba->pDev->dev,
3164 sizeof(opblk), &opblk_pa, GFP_KERNEL);
3165 if (opblk_va == NULL) {
3166 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3167 resblk_va, resblk_pa);
3168 printk(KERN_CRIT "%s: query operatio failed; Out of memory.\n",
3169 pHba->name);
3170 return -ENOMEM;
3171 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 if (field == -1) /* whole group */
3173 opblk[4] = -1;
3174
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003175 memcpy(opblk_va, opblk, sizeof(opblk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid,
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003177 opblk_va, opblk_pa, sizeof(opblk),
3178 resblk_va, resblk_pa, sizeof(u8)*(8+buflen));
3179 dma_free_coherent(&pHba->pDev->dev, sizeof(opblk), opblk_va, opblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 if (size == -ETIME) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003181 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3182 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183 printk(KERN_WARNING "%s: issue params failed; Timed out.\n", pHba->name);
3184 return -ETIME;
3185 } else if (size == -EINTR) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003186 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3187 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188 printk(KERN_WARNING "%s: issue params failed; Interrupted.\n", pHba->name);
3189 return -EINTR;
3190 }
3191
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003192 memcpy(buf, resblk_va+8, buflen); /* cut off header */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003194 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3195 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196 if (size < 0)
3197 return size;
3198
3199 return buflen;
3200}
3201
3202
3203/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
3204 *
3205 * This function can be used for all UtilParamsGet/Set operations.
3206 * The OperationBlock is given in opblk-buffer,
3207 * and results are returned in resblk-buffer.
3208 * Note that the minimum sized resblk is 8 bytes and contains
3209 * ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
3210 */
3211static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid,
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003212 void *opblk_va, dma_addr_t opblk_pa, int oplen,
3213 void *resblk_va, dma_addr_t resblk_pa, int reslen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214{
3215 u32 msg[9];
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003216 u32 *res = (u32 *)resblk_va;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217 int wait_status;
3218
3219 msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
3220 msg[1] = cmd << 24 | HOST_TID << 12 | tid;
3221 msg[2] = 0;
3222 msg[3] = 0;
3223 msg[4] = 0;
3224 msg[5] = 0x54000000 | oplen; /* OperationBlock */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003225 msg[6] = (u32)opblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 msg[7] = 0xD0000000 | reslen; /* ResultBlock */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003227 msg[8] = (u32)resblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228
3229 if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003230 printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk_va);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231 return wait_status; /* -DetailedStatus */
3232 }
3233
3234 if (res[1]&0x00FF0000) { /* BlockStatus != SUCCESS */
3235 printk(KERN_WARNING "%s: %s - Error:\n ErrorInfoSize = 0x%02x, "
3236 "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
3237 pHba->name,
3238 (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"
3239 : "PARAMS_GET",
3240 res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
3241 return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
3242 }
3243
3244 return 4 + ((res[1] & 0x0000FFFF) << 2); /* bytes used in resblk */
3245}
3246
3247
3248static s32 adpt_i2o_quiesce_hba(adpt_hba* pHba)
3249{
3250 u32 msg[4];
3251 int ret;
3252
3253 adpt_i2o_status_get(pHba);
3254
3255 /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */
3256
3257 if((pHba->status_block->iop_state != ADAPTER_STATE_READY) &&
3258 (pHba->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)){
3259 return 0;
3260 }
3261
3262 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
3263 msg[1] = I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
3264 msg[2] = 0;
3265 msg[3] = 0;
3266
3267 if((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) {
3268 printk(KERN_INFO"dpti%d: Unable to quiesce (status=%#x).\n",
3269 pHba->unit, -ret);
3270 } else {
3271 printk(KERN_INFO"dpti%d: Quiesced.\n",pHba->unit);
3272 }
3273
3274 adpt_i2o_status_get(pHba);
3275 return ret;
3276}
3277
3278
3279/*
3280 * Enable IOP. Allows the IOP to resume external operations.
3281 */
3282static int adpt_i2o_enable_hba(adpt_hba* pHba)
3283{
3284 u32 msg[4];
3285 int ret;
3286
3287 adpt_i2o_status_get(pHba);
3288 if(!pHba->status_block){
3289 return -ENOMEM;
3290 }
3291 /* Enable only allowed on READY state */
3292 if(pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)
3293 return 0;
3294
3295 if(pHba->status_block->iop_state != ADAPTER_STATE_READY)
3296 return -EINVAL;
3297
3298 msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
3299 msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
3300 msg[2]= 0;
3301 msg[3]= 0;
3302
3303 if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) {
3304 printk(KERN_WARNING"%s: Could not enable (status=%#10x).\n",
3305 pHba->name, ret);
3306 } else {
3307 PDEBUG("%s: Enabled.\n", pHba->name);
3308 }
3309
3310 adpt_i2o_status_get(pHba);
3311 return ret;
3312}
3313
3314
3315static int adpt_i2o_systab_send(adpt_hba* pHba)
3316{
3317 u32 msg[12];
3318 int ret;
3319
3320 msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
3321 msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
3322 msg[2] = 0;
3323 msg[3] = 0;
3324 msg[4] = (0<<16) | ((pHba->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */
3325 msg[5] = 0; /* Segment 0 */
3326
3327 /*
3328 * Provide three SGL-elements:
3329 * System table (SysTab), Private memory space declaration and
3330 * Private i/o space declaration
3331 */
3332 msg[6] = 0x54000000 | sys_tbl_len;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003333 msg[7] = (u32)sys_tbl_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334 msg[8] = 0x54000000 | 0;
3335 msg[9] = 0;
3336 msg[10] = 0xD4000000 | 0;
3337 msg[11] = 0;
3338
3339 if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 120))) {
3340 printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n",
3341 pHba->name, ret);
3342 }
3343#ifdef DEBUG
3344 else {
3345 PINFO("%s: SysTab set.\n", pHba->name);
3346 }
3347#endif
3348
3349 return ret;
3350 }
3351
3352
3353/*============================================================================
3354 *
3355 *============================================================================
3356 */
3357
3358
3359#ifdef UARTDELAY
3360
3361static static void adpt_delay(int millisec)
3362{
3363 int i;
3364 for (i = 0; i < millisec; i++) {
3365 udelay(1000); /* delay for one millisecond */
3366 }
3367}
3368
3369#endif
3370
Andrew Morton24601bb2007-12-10 15:49:20 -08003371static struct scsi_host_template driver_template = {
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02003372 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 .name = "dpt_i2o",
3374 .proc_name = "dpt_i2o",
3375 .proc_info = adpt_proc_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376 .info = adpt_info,
3377 .queuecommand = adpt_queue,
3378 .eh_abort_handler = adpt_abort,
3379 .eh_device_reset_handler = adpt_device_reset,
3380 .eh_bus_reset_handler = adpt_bus_reset,
3381 .eh_host_reset_handler = adpt_reset,
3382 .bios_param = adpt_bios_param,
3383 .slave_configure = adpt_slave_configure,
3384 .can_queue = MAX_TO_IOP_MESSAGES,
3385 .this_id = 7,
3386 .cmd_per_lun = 1,
3387 .use_clustering = ENABLE_CLUSTERING,
3388};
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02003389
3390static int __init adpt_init(void)
3391{
3392 int error;
3393 adpt_hba *pHba, *next;
3394
3395 printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n");
3396
3397 error = adpt_detect(&driver_template);
3398 if (error < 0)
3399 return error;
3400 if (hba_chain == NULL)
3401 return -ENODEV;
3402
3403 for (pHba = hba_chain; pHba; pHba = pHba->next) {
3404 error = scsi_add_host(pHba->host, &pHba->pDev->dev);
3405 if (error)
3406 goto fail;
3407 scsi_scan_host(pHba->host);
3408 }
3409 return 0;
3410fail:
3411 for (pHba = hba_chain; pHba; pHba = next) {
3412 next = pHba->next;
3413 scsi_remove_host(pHba->host);
3414 }
3415 return error;
3416}
3417
3418static void __exit adpt_exit(void)
3419{
3420 adpt_hba *pHba, *next;
3421
3422 for (pHba = hba_chain; pHba; pHba = pHba->next)
3423 scsi_remove_host(pHba->host);
3424 for (pHba = hba_chain; pHba; pHba = next) {
3425 next = pHba->next;
3426 adpt_release(pHba->host);
3427 }
3428}
3429
3430module_init(adpt_init);
3431module_exit(adpt_exit);
3432
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433MODULE_LICENSE("GPL");