blob: f2d4df14c311520da5c8f9b73beea275c4444f50 [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>
Jonathan Corbetdea3f662008-05-16 14:11:09 -060052#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#include <linux/spinlock.h>
Matthias Gehre910638a2006-03-28 01:56:48 -080054#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56#include <linux/timer.h>
57#include <linux/string.h>
58#include <linux/ioport.h>
Arjan van de Ven0b950672006-01-11 13:16:10 +010059#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
61#include <asm/processor.h> /* for boot_cpu_data */
62#include <asm/pgtable.h>
63#include <asm/io.h> /* for virt_to_bus, etc. */
64
65#include <scsi/scsi.h>
66#include <scsi/scsi_cmnd.h>
67#include <scsi/scsi_device.h>
68#include <scsi/scsi_host.h>
69#include <scsi/scsi_tcq.h>
70
71#include "dpt/dptsig.h"
72#include "dpti.h"
73
74/*============================================================================
75 * Create a binary signature - this is read by dptsig
76 * Needed for our management apps
77 *============================================================================
78 */
79static dpt_sig_S DPTI_sig = {
80 {'d', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION,
81#ifdef __i386__
82 PROC_INTEL, PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM,
83#elif defined(__ia64__)
84 PROC_INTEL, PROC_IA64,
85#elif defined(__sparc__)
86 PROC_ULTRASPARC, PROC_ULTRASPARC,
87#elif defined(__alpha__)
88 PROC_ALPHA, PROC_ALPHA,
89#else
90 (-1),(-1),
91#endif
92 FT_HBADRVR, 0, OEM_DPT, OS_LINUX, CAP_OVERLAP, DEV_ALL,
93 ADF_ALL_SC5, 0, 0, DPT_VERSION, DPT_REVISION, DPT_SUBREVISION,
94 DPT_MONTH, DPT_DAY, DPT_YEAR, "Adaptec Linux I2O RAID Driver"
95};
96
97
98
99
100/*============================================================================
101 * Globals
102 *============================================================================
103 */
104
Arjan van de Ven0b950672006-01-11 13:16:10 +0100105static DEFINE_MUTEX(adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200107static struct i2o_sys_tbl *sys_tbl;
108static dma_addr_t sys_tbl_pa;
109static int sys_tbl_ind;
110static int sys_tbl_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112static adpt_hba* hba_chain = NULL;
113static int hba_count = 0;
114
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +0200115static struct class *adpt_sysfs_class;
116
Arnd Bergmannf4927c42010-04-27 00:24:01 +0200117static long adpt_unlocked_ioctl(struct file *, unsigned int, unsigned long);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200118#ifdef CONFIG_COMPAT
119static long compat_adpt_ioctl(struct file *, unsigned int, unsigned long);
120#endif
121
Arjan van de Ven00977a52007-02-12 00:55:34 -0800122static const struct file_operations adpt_fops = {
Arnd Bergmannf4927c42010-04-27 00:24:01 +0200123 .unlocked_ioctl = adpt_unlocked_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 .open = adpt_open,
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200125 .release = adpt_close,
126#ifdef CONFIG_COMPAT
127 .compat_ioctl = compat_adpt_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
131/* Structures and definitions for synchronous message posting.
132 * See adpt_i2o_post_wait() for description
133 * */
134struct adpt_i2o_post_wait_data
135{
136 int status;
137 u32 id;
138 adpt_wait_queue_head_t *wq;
139 struct adpt_i2o_post_wait_data *next;
140};
141
142static struct adpt_i2o_post_wait_data *adpt_post_wait_queue = NULL;
143static u32 adpt_post_wait_id = 0;
144static DEFINE_SPINLOCK(adpt_post_wait_lock);
145
146
147/*============================================================================
148 * Functions
149 *============================================================================
150 */
151
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200152static inline int dpt_dma64(adpt_hba *pHba)
153{
154 return (sizeof(dma_addr_t) > 4 && (pHba)->dma64);
155}
156
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200157static inline u32 dma_high(dma_addr_t addr)
158{
159 return upper_32_bits(addr);
160}
161
162static inline u32 dma_low(dma_addr_t addr)
163{
164 return (u32)addr;
165}
166
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167static u8 adpt_read_blink_led(adpt_hba* host)
168{
Harvey Harrison172c1222008-04-28 16:50:03 -0700169 if (host->FwDebugBLEDflag_P) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 if( readb(host->FwDebugBLEDflag_P) == 0xbc ){
171 return readb(host->FwDebugBLEDvalue_P);
172 }
173 }
174 return 0;
175}
176
177/*============================================================================
178 * Scsi host template interface functions
179 *============================================================================
180 */
181
182static struct pci_device_id dptids[] = {
183 { PCI_DPT_VENDOR_ID, PCI_DPT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
184 { PCI_DPT_VENDOR_ID, PCI_DPT_RAPTOR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
185 { 0, }
186};
187MODULE_DEVICE_TABLE(pci,dptids);
188
Andrew Morton24601bb2007-12-10 15:49:20 -0800189static int adpt_detect(struct scsi_host_template* sht)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190{
191 struct pci_dev *pDev = NULL;
Dan Carpenter229bab62010-03-15 11:26:56 +0300192 adpt_hba *pHba;
193 adpt_hba *next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 PINFO("Detecting Adaptec I2O RAID controllers...\n");
196
197 /* search for all Adatpec I2O RAID cards */
Alan Coxa07f3532006-09-15 15:34:32 +0100198 while ((pDev = pci_get_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 if(pDev->device == PCI_DPT_DEVICE_ID ||
200 pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){
Andrew Morton24601bb2007-12-10 15:49:20 -0800201 if(adpt_install_hba(sht, pDev) ){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 PERROR("Could not Init an I2O RAID device\n");
203 PERROR("Will not try to detect others.\n");
204 return hba_count-1;
205 }
Alan Coxa07f3532006-09-15 15:34:32 +0100206 pci_dev_get(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 }
208 }
209
210 /* In INIT state, Activate IOPs */
Dan Carpenter229bab62010-03-15 11:26:56 +0300211 for (pHba = hba_chain; pHba; pHba = next) {
212 next = pHba->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 // Activate does get status , init outbound, and get hrt
214 if (adpt_i2o_activate_hba(pHba) < 0) {
215 adpt_i2o_delete_hba(pHba);
216 }
217 }
218
219
220 /* Active IOPs in HOLD state */
221
222rebuild_sys_tab:
223 if (hba_chain == NULL)
224 return 0;
225
226 /*
227 * If build_sys_table fails, we kill everything and bail
228 * as we can't init the IOPs w/o a system table
229 */
230 if (adpt_i2o_build_sys_table() < 0) {
231 adpt_i2o_sys_shutdown();
232 return 0;
233 }
234
235 PDEBUG("HBA's in HOLD state\n");
236
237 /* If IOP don't get online, we need to rebuild the System table */
238 for (pHba = hba_chain; pHba; pHba = pHba->next) {
239 if (adpt_i2o_online_hba(pHba) < 0) {
240 adpt_i2o_delete_hba(pHba);
241 goto rebuild_sys_tab;
242 }
243 }
244
245 /* Active IOPs now in OPERATIONAL state */
246 PDEBUG("HBA's in OPERATIONAL state\n");
247
248 printk("dpti: If you have a lot of devices this could take a few minutes.\n");
Dan Carpenter229bab62010-03-15 11:26:56 +0300249 for (pHba = hba_chain; pHba; pHba = next) {
250 next = pHba->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name);
252 if (adpt_i2o_lct_get(pHba) < 0){
253 adpt_i2o_delete_hba(pHba);
254 continue;
255 }
256
257 if (adpt_i2o_parse_lct(pHba) < 0){
258 adpt_i2o_delete_hba(pHba);
259 continue;
260 }
261 adpt_inquiry(pHba);
262 }
263
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +0200264 adpt_sysfs_class = class_create(THIS_MODULE, "dpt_i2o");
265 if (IS_ERR(adpt_sysfs_class)) {
266 printk(KERN_WARNING"dpti: unable to create dpt_i2o class\n");
267 adpt_sysfs_class = NULL;
268 }
269
Dan Carpenter229bab62010-03-15 11:26:56 +0300270 for (pHba = hba_chain; pHba; pHba = next) {
271 next = pHba->next;
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +0200272 if (adpt_scsi_host_alloc(pHba, sht) < 0){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 adpt_i2o_delete_hba(pHba);
274 continue;
275 }
276 pHba->initialized = TRUE;
277 pHba->state &= ~DPTI_STATE_RESET;
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +0200278 if (adpt_sysfs_class) {
Greg Kroah-Hartmand73a1a62008-07-21 20:03:34 -0700279 struct device *dev = device_create(adpt_sysfs_class,
Greg Kroah-Hartman9def0b92008-05-21 12:52:33 -0700280 NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +0200281 "dpti%d", pHba->unit);
282 if (IS_ERR(dev)) {
283 printk(KERN_WARNING"dpti%d: unable to "
284 "create device in dpt_i2o class\n",
285 pHba->unit);
286 }
287 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 }
289
290 // Register our control device node
291 // nodes will need to be created in /dev to access this
292 // the nodes can not be created from within the driver
293 if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) {
Andrew Morton24601bb2007-12-10 15:49:20 -0800294 adpt_i2o_sys_shutdown();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 return 0;
296 }
297 return hba_count;
298}
299
300
Andrew Morton24601bb2007-12-10 15:49:20 -0800301/*
302 * scsi_unregister will be called AFTER we return.
303 */
304static int adpt_release(struct Scsi_Host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305{
Andrew Morton24601bb2007-12-10 15:49:20 -0800306 adpt_hba* pHba = (adpt_hba*) host->hostdata[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307// adpt_i2o_quiesce_hba(pHba);
308 adpt_i2o_delete_hba(pHba);
Andrew Morton24601bb2007-12-10 15:49:20 -0800309 scsi_unregister(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 return 0;
311}
312
313
314static void adpt_inquiry(adpt_hba* pHba)
315{
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200316 u32 msg[17];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 u32 *mptr;
318 u32 *lenptr;
319 int direction;
320 int scsidir;
321 u32 len;
322 u32 reqlen;
323 u8* buf;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200324 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 u8 scb[16];
326 s32 rcode;
327
328 memset(msg, 0, sizeof(msg));
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200329 buf = dma_alloc_coherent(&pHba->pDev->dev, 80, &addr, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 if(!buf){
331 printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name);
332 return;
333 }
334 memset((void*)buf, 0, 36);
335
336 len = 36;
337 direction = 0x00000000;
338 scsidir =0x40000000; // DATA IN (iop<--dev)
339
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200340 if (dpt_dma64(pHba))
341 reqlen = 17; // SINGLE SGE, 64 bit
342 else
343 reqlen = 14; // SINGLE SGE, 32 bit
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 /* Stick the headers on */
345 msg[0] = reqlen<<16 | SGL_OFFSET_12;
346 msg[1] = (0xff<<24|HOST_TID<<12|ADAPTER_TID);
347 msg[2] = 0;
348 msg[3] = 0;
349 // Adaptec/DPT Private stuff
350 msg[4] = I2O_CMD_SCSI_EXEC|DPT_ORGANIZATION_ID<<16;
351 msg[5] = ADAPTER_TID | 1<<16 /* Interpret*/;
352 /* Direction, disconnect ok | sense data | simple queue , CDBLen */
353 // I2O_SCB_FLAG_ENABLE_DISCONNECT |
354 // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG |
355 // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;
356 msg[6] = scsidir|0x20a00000| 6 /* cmd len*/;
357
358 mptr=msg+7;
359
360 memset(scb, 0, sizeof(scb));
361 // Write SCSI command into the message - always 16 byte block
362 scb[0] = INQUIRY;
363 scb[1] = 0;
364 scb[2] = 0;
365 scb[3] = 0;
366 scb[4] = 36;
367 scb[5] = 0;
368 // Don't care about the rest of scb
369
370 memcpy(mptr, scb, sizeof(scb));
371 mptr+=4;
372 lenptr=mptr++; /* Remember me - fill in when we know */
373
374 /* Now fill in the SGList and command */
375 *lenptr = len;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200376 if (dpt_dma64(pHba)) {
377 *mptr++ = (0x7C<<24)+(2<<16)+0x02; /* Enable 64 bit */
378 *mptr++ = 1 << PAGE_SHIFT;
379 *mptr++ = 0xD0000000|direction|len;
380 *mptr++ = dma_low(addr);
381 *mptr++ = dma_high(addr);
382 } else {
383 *mptr++ = 0xD0000000|direction|len;
384 *mptr++ = addr;
385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
387 // Send it on it's way
388 rcode = adpt_i2o_post_wait(pHba, msg, reqlen<<2, 120);
389 if (rcode != 0) {
390 sprintf(pHba->detail, "Adaptec I2O RAID");
391 printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode);
392 if (rcode != -ETIME && rcode != -EINTR)
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200393 dma_free_coherent(&pHba->pDev->dev, 80, buf, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 } else {
395 memset(pHba->detail, 0, sizeof(pHba->detail));
396 memcpy(&(pHba->detail), "Vendor: Adaptec ", 16);
397 memcpy(&(pHba->detail[16]), " Model: ", 8);
398 memcpy(&(pHba->detail[24]), (u8*) &buf[16], 16);
399 memcpy(&(pHba->detail[40]), " FW: ", 4);
400 memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4);
401 pHba->detail[48] = '\0'; /* precautionary */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +0200402 dma_free_coherent(&pHba->pDev->dev, 80, buf, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 }
404 adpt_i2o_status_get(pHba);
405 return ;
406}
407
408
409static int adpt_slave_configure(struct scsi_device * device)
410{
411 struct Scsi_Host *host = device->host;
412 adpt_hba* pHba;
413
414 pHba = (adpt_hba *) host->hostdata[0];
415
416 if (host->can_queue && device->tagged_supported) {
417 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
418 host->can_queue - 1);
419 } else {
420 scsi_adjust_queue_depth(device, 0, 1);
421 }
422 return 0;
423}
424
425static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
426{
427 adpt_hba* pHba = NULL;
428 struct adpt_device* pDev = NULL; /* dpt per device information */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
430 cmd->scsi_done = done;
431 /*
432 * SCSI REQUEST_SENSE commands will be executed automatically by the
433 * Host Adapter for any errors, so they should not be executed
434 * explicitly unless the Sense Data is zero indicating that no error
435 * occurred.
436 */
437
438 if ((cmd->cmnd[0] == REQUEST_SENSE) && (cmd->sense_buffer[0] != 0)) {
439 cmd->result = (DID_OK << 16);
440 cmd->scsi_done(cmd);
441 return 0;
442 }
443
444 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
445 if (!pHba) {
446 return FAILED;
447 }
448
449 rmb();
450 /*
451 * TODO: I need to block here if I am processing ioctl cmds
452 * but if the outstanding cmds all finish before the ioctl,
453 * the scsi-core will not know to start sending cmds to me again.
454 * I need to a way to restart the scsi-cores queues or should I block
455 * calling scsi_done on the outstanding cmds instead
456 * for now we don't set the IOCTL state
457 */
458 if(((pHba->state) & DPTI_STATE_IOCTL) || ((pHba->state) & DPTI_STATE_RESET)) {
459 pHba->host->last_reset = jiffies;
460 pHba->host->resetting = 1;
461 return 1;
462 }
463
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 // TODO if the cmd->device if offline then I may need to issue a bus rescan
465 // followed by a get_lct to see if the device is there anymore
466 if((pDev = (struct adpt_device*) (cmd->device->hostdata)) == NULL) {
467 /*
468 * First command request for this device. Set up a pointer
469 * to the device structure. This should be a TEST_UNIT_READY
470 * command from scan_scsis_single.
471 */
472 if ((pDev = adpt_find_device(pHba, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun)) == NULL) {
473 // TODO: if any luns are at this bus, scsi id then fake a TEST_UNIT_READY and INQUIRY response
474 // with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue.
475 cmd->result = (DID_NO_CONNECT << 16);
476 cmd->scsi_done(cmd);
477 return 0;
478 }
479 cmd->device->hostdata = pDev;
480 }
481 pDev->pScsi_dev = cmd->device;
482
483 /*
484 * If we are being called from when the device is being reset,
485 * delay processing of the command until later.
486 */
487 if (pDev->state & DPTI_DEV_RESET ) {
488 return FAILED;
489 }
490 return adpt_scsi_to_i2o(pHba, cmd, pDev);
491}
492
493static int adpt_bios_param(struct scsi_device *sdev, struct block_device *dev,
494 sector_t capacity, int geom[])
495{
496 int heads=-1;
497 int sectors=-1;
498 int cylinders=-1;
499
500 // *** First lets set the default geometry ****
501
502 // If the capacity is less than ox2000
503 if (capacity < 0x2000 ) { // floppy
504 heads = 18;
505 sectors = 2;
506 }
507 // else if between 0x2000 and 0x20000
508 else if (capacity < 0x20000) {
509 heads = 64;
510 sectors = 32;
511 }
512 // else if between 0x20000 and 0x40000
513 else if (capacity < 0x40000) {
514 heads = 65;
515 sectors = 63;
516 }
517 // else if between 0x4000 and 0x80000
518 else if (capacity < 0x80000) {
519 heads = 128;
520 sectors = 63;
521 }
522 // else if greater than 0x80000
523 else {
524 heads = 255;
525 sectors = 63;
526 }
527 cylinders = sector_div(capacity, heads * sectors);
528
529 // Special case if CDROM
530 if(sdev->type == 5) { // CDROM
531 heads = 252;
532 sectors = 63;
533 cylinders = 1111;
534 }
535
536 geom[0] = heads;
537 geom[1] = sectors;
538 geom[2] = cylinders;
539
540 PDEBUG("adpt_bios_param: exit\n");
541 return 0;
542}
543
544
545static const char *adpt_info(struct Scsi_Host *host)
546{
547 adpt_hba* pHba;
548
549 pHba = (adpt_hba *) host->hostdata[0];
550 return (char *) (pHba->detail);
551}
552
553static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
554 int length, int inout)
555{
556 struct adpt_device* d;
557 int id;
558 int chan;
559 int len = 0;
560 int begin = 0;
561 int pos = 0;
562 adpt_hba* pHba;
563 int unit;
564
565 *start = buffer;
566 if (inout == TRUE) {
567 /*
568 * The user has done a write and wants us to take the
569 * data in the buffer and do something with it.
570 * proc_scsiwrite calls us with inout = 1
571 *
572 * Read data from buffer (writing to us) - NOT SUPPORTED
573 */
574 return -EINVAL;
575 }
576
577 /*
578 * inout = 0 means the user has done a read and wants information
579 * returned, so we write information about the cards into the buffer
580 * proc_scsiread() calls us with inout = 0
581 */
582
583 // Find HBA (host bus adapter) we are looking for
Arjan van de Ven0b950672006-01-11 13:16:10 +0100584 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 for (pHba = hba_chain; pHba; pHba = pHba->next) {
586 if (pHba->host == host) {
587 break; /* found adapter */
588 }
589 }
Arjan van de Ven0b950672006-01-11 13:16:10 +0100590 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 if (pHba == NULL) {
592 return 0;
593 }
594 host = pHba->host;
595
596 len = sprintf(buffer , "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION);
597 len += sprintf(buffer+len, "%s\n", pHba->detail);
598 len += sprintf(buffer+len, "SCSI Host=scsi%d Control Node=/dev/%s irq=%d\n",
599 pHba->host->host_no, pHba->name, host->irq);
600 len += sprintf(buffer+len, "\tpost fifo size = %d\n\treply fifo size = %d\n\tsg table size = %d\n\n",
601 host->can_queue, (int) pHba->reply_fifo_size , host->sg_tablesize);
602
603 pos = begin + len;
604
605 /* CHECKPOINT */
606 if(pos > offset + length) {
607 goto stop_output;
608 }
609 if(pos <= offset) {
610 /*
611 * If we haven't even written to where we last left
612 * off (the last time we were called), reset the
613 * beginning pointer.
614 */
615 len = 0;
616 begin = pos;
617 }
618 len += sprintf(buffer+len, "Devices:\n");
619 for(chan = 0; chan < MAX_CHANNEL; chan++) {
620 for(id = 0; id < MAX_ID; id++) {
621 d = pHba->channel[chan].device[id];
622 while(d){
623 len += sprintf(buffer+len,"\t%-24.24s", d->pScsi_dev->vendor);
624 len += sprintf(buffer+len," Rev: %-8.8s\n", d->pScsi_dev->rev);
625 pos = begin + len;
626
627
628 /* CHECKPOINT */
629 if(pos > offset + length) {
630 goto stop_output;
631 }
632 if(pos <= offset) {
633 len = 0;
634 begin = pos;
635 }
636
637 unit = d->pI2o_dev->lct_data.tid;
638 len += sprintf(buffer+len, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d) (%s)\n\n",
639 unit, (int)d->scsi_channel, (int)d->scsi_id, (int)d->scsi_lun,
640 scsi_device_online(d->pScsi_dev)? "online":"offline");
641 pos = begin + len;
642
643 /* CHECKPOINT */
644 if(pos > offset + length) {
645 goto stop_output;
646 }
647 if(pos <= offset) {
648 len = 0;
649 begin = pos;
650 }
651
652 d = d->next_lun;
653 }
654 }
655 }
656
657 /*
658 * begin is where we last checked our position with regards to offset
659 * begin is always less than offset. len is relative to begin. It
660 * is the number of bytes written past begin
661 *
662 */
663stop_output:
664 /* stop the output and calculate the correct length */
665 *(buffer + len) = '\0';
666
667 *start = buffer + (offset - begin); /* Start of wanted data */
668 len -= (offset - begin);
669 if(len > length) {
670 len = length;
671 } else if(len < 0){
672 len = 0;
673 **start = '\0';
674 }
675 return len;
676}
677
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200678/*
679 * Turn a struct scsi_cmnd * into a unique 32 bit 'context'.
680 */
681static u32 adpt_cmd_to_context(struct scsi_cmnd *cmd)
682{
683 return (u32)cmd->serial_number;
684}
685
686/*
687 * Go from a u32 'context' to a struct scsi_cmnd * .
688 * This could probably be made more efficient.
689 */
690static struct scsi_cmnd *
691 adpt_cmd_from_context(adpt_hba * pHba, u32 context)
692{
693 struct scsi_cmnd * cmd;
694 struct scsi_device * d;
695
696 if (context == 0)
697 return NULL;
698
699 spin_unlock(pHba->host->host_lock);
700 shost_for_each_device(d, pHba->host) {
701 unsigned long flags;
702 spin_lock_irqsave(&d->list_lock, flags);
703 list_for_each_entry(cmd, &d->cmd_list, list) {
704 if (((u32)cmd->serial_number == context)) {
705 spin_unlock_irqrestore(&d->list_lock, flags);
706 scsi_device_put(d);
707 spin_lock(pHba->host->host_lock);
708 return cmd;
709 }
710 }
711 spin_unlock_irqrestore(&d->list_lock, flags);
712 }
713 spin_lock(pHba->host->host_lock);
714
715 return NULL;
716}
717
718/*
719 * Turn a pointer to ioctl reply data into an u32 'context'
720 */
721static u32 adpt_ioctl_to_context(adpt_hba * pHba, void *reply)
722{
723#if BITS_PER_LONG == 32
724 return (u32)(unsigned long)reply;
725#else
726 ulong flags = 0;
727 u32 nr, i;
728
729 spin_lock_irqsave(pHba->host->host_lock, flags);
730 nr = ARRAY_SIZE(pHba->ioctl_reply_context);
731 for (i = 0; i < nr; i++) {
732 if (pHba->ioctl_reply_context[i] == NULL) {
733 pHba->ioctl_reply_context[i] = reply;
734 break;
735 }
736 }
737 spin_unlock_irqrestore(pHba->host->host_lock, flags);
738 if (i >= nr) {
739 kfree (reply);
740 printk(KERN_WARNING"%s: Too many outstanding "
741 "ioctl commands\n", pHba->name);
742 return (u32)-1;
743 }
744
745 return i;
746#endif
747}
748
749/*
750 * Go from an u32 'context' to a pointer to ioctl reply data.
751 */
752static void *adpt_ioctl_from_context(adpt_hba *pHba, u32 context)
753{
754#if BITS_PER_LONG == 32
755 return (void *)(unsigned long)context;
756#else
757 void *p = pHba->ioctl_reply_context[context];
758 pHba->ioctl_reply_context[context] = NULL;
759
760 return p;
761#endif
762}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
764/*===========================================================================
765 * Error Handling routines
766 *===========================================================================
767 */
768
769static int adpt_abort(struct scsi_cmnd * cmd)
770{
771 adpt_hba* pHba = NULL; /* host bus adapter structure */
772 struct adpt_device* dptdevice; /* dpt per device information */
773 u32 msg[5];
774 int rcode;
775
776 if(cmd->serial_number == 0){
777 return FAILED;
778 }
779 pHba = (adpt_hba*) cmd->device->host->hostdata[0];
780 printk(KERN_INFO"%s: Trying to Abort cmd=%ld\n",pHba->name, cmd->serial_number);
781 if ((dptdevice = (void*) (cmd->device->hostdata)) == NULL) {
782 printk(KERN_ERR "%s: Unable to abort: No device in cmnd\n",pHba->name);
783 return FAILED;
784 }
785
786 memset(msg, 0, sizeof(msg));
787 msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
788 msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|dptdevice->tid;
789 msg[2] = 0;
790 msg[3]= 0;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +0200791 msg[4] = adpt_cmd_to_context(cmd);
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800792 if (pHba->host)
793 spin_lock_irq(pHba->host->host_lock);
794 rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER);
795 if (pHba->host)
796 spin_unlock_irq(pHba->host->host_lock);
797 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 if(rcode == -EOPNOTSUPP ){
799 printk(KERN_INFO"%s: Abort cmd not supported\n",pHba->name);
800 return FAILED;
801 }
802 printk(KERN_INFO"%s: Abort cmd=%ld failed.\n",pHba->name, cmd->serial_number);
803 return FAILED;
804 }
805 printk(KERN_INFO"%s: Abort cmd=%ld complete.\n",pHba->name, cmd->serial_number);
806 return SUCCESS;
807}
808
809
810#define I2O_DEVICE_RESET 0x27
811// This is the same for BLK and SCSI devices
812// NOTE this is wrong in the i2o.h definitions
813// This is not currently supported by our adapter but we issue it anyway
814static int adpt_device_reset(struct scsi_cmnd* cmd)
815{
816 adpt_hba* pHba;
817 u32 msg[4];
818 u32 rcode;
819 int old_state;
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -0700820 struct adpt_device* d = cmd->device->hostdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822 pHba = (void*) cmd->device->host->hostdata[0];
823 printk(KERN_INFO"%s: Trying to reset device\n",pHba->name);
824 if (!d) {
825 printk(KERN_INFO"%s: Reset Device: Device Not found\n",pHba->name);
826 return FAILED;
827 }
828 memset(msg, 0, sizeof(msg));
829 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
830 msg[1] = (I2O_DEVICE_RESET<<24|HOST_TID<<12|d->tid);
831 msg[2] = 0;
832 msg[3] = 0;
833
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800834 if (pHba->host)
835 spin_lock_irq(pHba->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 old_state = d->state;
837 d->state |= DPTI_DEV_RESET;
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800838 rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
839 d->state = old_state;
840 if (pHba->host)
841 spin_unlock_irq(pHba->host->host_lock);
842 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 if(rcode == -EOPNOTSUPP ){
844 printk(KERN_INFO"%s: Device reset not supported\n",pHba->name);
845 return FAILED;
846 }
847 printk(KERN_INFO"%s: Device reset failed\n",pHba->name);
848 return FAILED;
849 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 printk(KERN_INFO"%s: Device reset successful\n",pHba->name);
851 return SUCCESS;
852 }
853}
854
855
856#define I2O_HBA_BUS_RESET 0x87
857// This version of bus reset is called by the eh_error handler
858static int adpt_bus_reset(struct scsi_cmnd* cmd)
859{
860 adpt_hba* pHba;
861 u32 msg[4];
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800862 u32 rcode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
864 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
865 memset(msg, 0, sizeof(msg));
866 printk(KERN_WARNING"%s: Bus reset: SCSI Bus %d: tid: %d\n",pHba->name, cmd->device->channel,pHba->channel[cmd->device->channel].tid );
867 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
868 msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->device->channel].tid);
869 msg[2] = 0;
870 msg[3] = 0;
Salyzyn, Marke5508c12005-12-17 19:26:30 -0800871 if (pHba->host)
872 spin_lock_irq(pHba->host->host_lock);
873 rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
874 if (pHba->host)
875 spin_unlock_irq(pHba->host->host_lock);
876 if (rcode != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name);
878 return FAILED;
879 } else {
880 printk(KERN_WARNING"%s: Bus reset success.\n",pHba->name);
881 return SUCCESS;
882 }
883}
884
885// This version of reset is called by the eh_error_handler
Jeff Garzik df0ae242005-05-28 07:57:14 -0400886static int __adpt_reset(struct scsi_cmnd* cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887{
888 adpt_hba* pHba;
889 int rcode;
890 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
891 printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n",pHba->name,cmd->device->channel,pHba->channel[cmd->device->channel].tid );
892 rcode = adpt_hba_reset(pHba);
893 if(rcode == 0){
894 printk(KERN_WARNING"%s: HBA reset complete\n",pHba->name);
895 return SUCCESS;
896 } else {
897 printk(KERN_WARNING"%s: HBA reset failed (%x)\n",pHba->name, rcode);
898 return FAILED;
899 }
900}
901
Jeff Garzik df0ae242005-05-28 07:57:14 -0400902static int adpt_reset(struct scsi_cmnd* cmd)
903{
904 int rc;
905
906 spin_lock_irq(cmd->device->host->host_lock);
907 rc = __adpt_reset(cmd);
908 spin_unlock_irq(cmd->device->host->host_lock);
909
910 return rc;
911}
912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913// This version of reset is called by the ioctls and indirectly from eh_error_handler via adpt_reset
914static int adpt_hba_reset(adpt_hba* pHba)
915{
916 int rcode;
917
918 pHba->state |= DPTI_STATE_RESET;
919
920 // Activate does get status , init outbound, and get hrt
921 if ((rcode=adpt_i2o_activate_hba(pHba)) < 0) {
922 printk(KERN_ERR "%s: Could not activate\n", pHba->name);
923 adpt_i2o_delete_hba(pHba);
924 return rcode;
925 }
926
927 if ((rcode=adpt_i2o_build_sys_table()) < 0) {
928 adpt_i2o_delete_hba(pHba);
929 return rcode;
930 }
931 PDEBUG("%s: in HOLD state\n",pHba->name);
932
933 if ((rcode=adpt_i2o_online_hba(pHba)) < 0) {
934 adpt_i2o_delete_hba(pHba);
935 return rcode;
936 }
937 PDEBUG("%s: in OPERATIONAL state\n",pHba->name);
938
939 if ((rcode=adpt_i2o_lct_get(pHba)) < 0){
940 adpt_i2o_delete_hba(pHba);
941 return rcode;
942 }
943
944 if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){
945 adpt_i2o_delete_hba(pHba);
946 return rcode;
947 }
948 pHba->state &= ~DPTI_STATE_RESET;
949
950 adpt_fail_posted_scbs(pHba);
951 return 0; /* return success */
952}
953
954/*===========================================================================
955 *
956 *===========================================================================
957 */
958
959
960static void adpt_i2o_sys_shutdown(void)
961{
962 adpt_hba *pHba, *pNext;
Adrian Bunk458af542005-11-27 00:36:37 +0100963 struct adpt_i2o_post_wait_data *p1, *old;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964
965 printk(KERN_INFO"Shutting down Adaptec I2O controllers.\n");
966 printk(KERN_INFO" This could take a few minutes if there are many devices attached\n");
967 /* Delete all IOPs from the controller chain */
968 /* They should have already been released by the
969 * scsi-core
970 */
971 for (pHba = hba_chain; pHba; pHba = pNext) {
972 pNext = pHba->next;
973 adpt_i2o_delete_hba(pHba);
974 }
975
976 /* Remove any timedout entries from the wait queue. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977// spin_lock_irqsave(&adpt_post_wait_lock, flags);
978 /* Nothing should be outstanding at this point so just
979 * free them
980 */
Adrian Bunk458af542005-11-27 00:36:37 +0100981 for(p1 = adpt_post_wait_queue; p1;) {
982 old = p1;
983 p1 = p1->next;
984 kfree(old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 }
986// spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
987 adpt_post_wait_queue = NULL;
988
989 printk(KERN_INFO "Adaptec I2O controllers down.\n");
990}
991
Andrew Morton24601bb2007-12-10 15:49:20 -0800992static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993{
994
995 adpt_hba* pHba = NULL;
996 adpt_hba* p = NULL;
997 ulong base_addr0_phys = 0;
998 ulong base_addr1_phys = 0;
999 u32 hba_map0_area_size = 0;
1000 u32 hba_map1_area_size = 0;
1001 void __iomem *base_addr_virt = NULL;
1002 void __iomem *msg_addr_virt = NULL;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001003 int dma64 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004
1005 int raptorFlag = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006
1007 if(pci_enable_device(pDev)) {
1008 return -EINVAL;
1009 }
Salyzyn, Mark9638d892006-01-12 08:31:57 -05001010
1011 if (pci_request_regions(pDev, "dpt_i2o")) {
1012 PERROR("dpti: adpt_config_hba: pci request region failed\n");
1013 return -EINVAL;
1014 }
1015
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 pci_set_master(pDev);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001017
1018 /*
1019 * See if we should enable dma64 mode.
1020 */
1021 if (sizeof(dma_addr_t) > 4 &&
Yang Hongyang6a355282009-04-06 19:01:13 -07001022 pci_set_dma_mask(pDev, DMA_BIT_MASK(64)) == 0) {
Yang Hongyang284901a2009-04-06 19:01:15 -07001023 if (dma_get_required_mask(&pDev->dev) > DMA_BIT_MASK(32))
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001024 dma64 = 1;
1025 }
Yang Hongyang284901a2009-04-06 19:01:15 -07001026 if (!dma64 && pci_set_dma_mask(pDev, DMA_BIT_MASK(32)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 return -EINVAL;
1028
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001029 /* adapter only supports message blocks below 4GB */
Yang Hongyang284901a2009-04-06 19:01:15 -07001030 pci_set_consistent_dma_mask(pDev, DMA_BIT_MASK(32));
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001031
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 base_addr0_phys = pci_resource_start(pDev,0);
1033 hba_map0_area_size = pci_resource_len(pDev,0);
1034
1035 // Check if standard PCI card or single BAR Raptor
1036 if(pDev->device == PCI_DPT_DEVICE_ID){
1037 if(pDev->subsystem_device >=0xc032 && pDev->subsystem_device <= 0xc03b){
1038 // Raptor card with this device id needs 4M
1039 hba_map0_area_size = 0x400000;
1040 } else { // Not Raptor - it is a PCI card
1041 if(hba_map0_area_size > 0x100000 ){
1042 hba_map0_area_size = 0x100000;
1043 }
1044 }
1045 } else {// Raptor split BAR config
1046 // Use BAR1 in this configuration
1047 base_addr1_phys = pci_resource_start(pDev,1);
1048 hba_map1_area_size = pci_resource_len(pDev,1);
1049 raptorFlag = TRUE;
1050 }
1051
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001052#if BITS_PER_LONG == 64
1053 /*
1054 * The original Adaptec 64 bit driver has this comment here:
1055 * "x86_64 machines need more optimal mappings"
1056 *
1057 * I assume some HBAs report ridiculously large mappings
1058 * and we need to limit them on platforms with IOMMUs.
1059 */
1060 if (raptorFlag == TRUE) {
1061 if (hba_map0_area_size > 128)
1062 hba_map0_area_size = 128;
1063 if (hba_map1_area_size > 524288)
1064 hba_map1_area_size = 524288;
1065 } else {
1066 if (hba_map0_area_size > 524288)
1067 hba_map0_area_size = 524288;
1068 }
1069#endif
1070
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size);
1072 if (!base_addr_virt) {
James Bottomley9c472dd2005-08-08 11:51:38 -05001073 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 PERROR("dpti: adpt_config_hba: io remap failed\n");
1075 return -EINVAL;
1076 }
1077
1078 if(raptorFlag == TRUE) {
1079 msg_addr_virt = ioremap(base_addr1_phys, hba_map1_area_size );
1080 if (!msg_addr_virt) {
1081 PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n");
1082 iounmap(base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -05001083 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 return -EINVAL;
1085 }
1086 } else {
1087 msg_addr_virt = base_addr_virt;
1088 }
1089
1090 // Allocate and zero the data structure
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02001091 pHba = kzalloc(sizeof(adpt_hba), GFP_KERNEL);
1092 if (!pHba) {
1093 if (msg_addr_virt != base_addr_virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 iounmap(msg_addr_virt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 iounmap(base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -05001096 pci_release_regions(pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 return -ENOMEM;
1098 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
Arjan van de Ven0b950672006-01-11 13:16:10 +01001100 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
1102 if(hba_chain != NULL){
1103 for(p = hba_chain; p->next; p = p->next);
1104 p->next = pHba;
1105 } else {
1106 hba_chain = pHba;
1107 }
1108 pHba->next = NULL;
1109 pHba->unit = hba_count;
Benoit Boissinot 23a2bc22005-04-25 19:46:30 -07001110 sprintf(pHba->name, "dpti%d", hba_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 hba_count++;
1112
Arjan van de Ven0b950672006-01-11 13:16:10 +01001113 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
1115 pHba->pDev = pDev;
1116 pHba->base_addr_phys = base_addr0_phys;
1117
1118 // Set up the Virtual Base Address of the I2O Device
1119 pHba->base_addr_virt = base_addr_virt;
1120 pHba->msg_addr_virt = msg_addr_virt;
1121 pHba->irq_mask = base_addr_virt+0x30;
1122 pHba->post_port = base_addr_virt+0x40;
1123 pHba->reply_port = base_addr_virt+0x44;
1124
1125 pHba->hrt = NULL;
1126 pHba->lct = NULL;
1127 pHba->lct_size = 0;
1128 pHba->status_block = NULL;
1129 pHba->post_count = 0;
1130 pHba->state = DPTI_STATE_RESET;
1131 pHba->pDev = pDev;
1132 pHba->devices = NULL;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001133 pHba->dma64 = dma64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134
1135 // Initializing the spinlocks
1136 spin_lock_init(&pHba->state_lock);
1137 spin_lock_init(&adpt_post_wait_lock);
1138
1139 if(raptorFlag == 0){
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001140 printk(KERN_INFO "Adaptec I2O RAID controller"
1141 " %d at %p size=%x irq=%d%s\n",
1142 hba_count-1, base_addr_virt,
1143 hba_map0_area_size, pDev->irq,
1144 dma64 ? " (64-bit DMA)" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 } else {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001146 printk(KERN_INFO"Adaptec I2O RAID controller %d irq=%d%s\n",
1147 hba_count-1, pDev->irq,
1148 dma64 ? " (64-bit DMA)" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 printk(KERN_INFO" BAR0 %p - size= %x\n",base_addr_virt,hba_map0_area_size);
1150 printk(KERN_INFO" BAR1 %p - size= %x\n",msg_addr_virt,hba_map1_area_size);
1151 }
1152
Thomas Gleixner1d6f3592006-07-01 19:29:42 -07001153 if (request_irq (pDev->irq, adpt_isr, IRQF_SHARED, pHba->name, pHba)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 printk(KERN_ERR"%s: Couldn't register IRQ %d\n", pHba->name, pDev->irq);
1155 adpt_i2o_delete_hba(pHba);
1156 return -EINVAL;
1157 }
1158
1159 return 0;
1160}
1161
1162
1163static void adpt_i2o_delete_hba(adpt_hba* pHba)
1164{
1165 adpt_hba* p1;
1166 adpt_hba* p2;
1167 struct i2o_device* d;
1168 struct i2o_device* next;
1169 int i;
1170 int j;
1171 struct adpt_device* pDev;
1172 struct adpt_device* pNext;
1173
1174
Arjan van de Ven0b950672006-01-11 13:16:10 +01001175 mutex_lock(&adpt_configuration_lock);
Andrew Morton24601bb2007-12-10 15:49:20 -08001176 // scsi_unregister calls our adpt_release which
1177 // does a quiese
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 if(pHba->host){
1179 free_irq(pHba->host->irq, pHba);
1180 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 p2 = NULL;
1182 for( p1 = hba_chain; p1; p2 = p1,p1=p1->next){
1183 if(p1 == pHba) {
1184 if(p2) {
1185 p2->next = p1->next;
1186 } else {
1187 hba_chain = p1->next;
1188 }
1189 break;
1190 }
1191 }
1192
1193 hba_count--;
Arjan van de Ven0b950672006-01-11 13:16:10 +01001194 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
1196 iounmap(pHba->base_addr_virt);
James Bottomley9c472dd2005-08-08 11:51:38 -05001197 pci_release_regions(pHba->pDev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 if(pHba->msg_addr_virt != pHba->base_addr_virt){
1199 iounmap(pHba->msg_addr_virt);
1200 }
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001201 if(pHba->FwDebugBuffer_P)
1202 iounmap(pHba->FwDebugBuffer_P);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001203 if(pHba->hrt) {
1204 dma_free_coherent(&pHba->pDev->dev,
1205 pHba->hrt->num_entries * pHba->hrt->entry_len << 2,
1206 pHba->hrt, pHba->hrt_pa);
1207 }
1208 if(pHba->lct) {
1209 dma_free_coherent(&pHba->pDev->dev, pHba->lct_size,
1210 pHba->lct, pHba->lct_pa);
1211 }
1212 if(pHba->status_block) {
1213 dma_free_coherent(&pHba->pDev->dev, sizeof(i2o_status_block),
1214 pHba->status_block, pHba->status_block_pa);
1215 }
1216 if(pHba->reply_pool) {
1217 dma_free_coherent(&pHba->pDev->dev,
1218 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
1219 pHba->reply_pool, pHba->reply_pool_pa);
1220 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
1222 for(d = pHba->devices; d ; d = next){
1223 next = d->next;
1224 kfree(d);
1225 }
1226 for(i = 0 ; i < pHba->top_scsi_channel ; i++){
1227 for(j = 0; j < MAX_ID; j++){
1228 if(pHba->channel[i].device[j] != NULL){
1229 for(pDev = pHba->channel[i].device[j]; pDev; pDev = pNext){
1230 pNext = pDev->next_lun;
1231 kfree(pDev);
1232 }
1233 }
1234 }
1235 }
Alan Coxa07f3532006-09-15 15:34:32 +01001236 pci_dev_put(pHba->pDev);
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +02001237 if (adpt_sysfs_class)
1238 device_destroy(adpt_sysfs_class,
1239 MKDEV(DPTI_I2O_MAJOR, pHba->unit));
Dan Carpenter229bab62010-03-15 11:26:56 +03001240 kfree(pHba);
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +02001241
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 if(hba_count <= 0){
1243 unregister_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER);
Miquel van Smoorenburg1ed43912008-05-02 01:08:19 +02001244 if (adpt_sysfs_class) {
1245 class_destroy(adpt_sysfs_class);
1246 adpt_sysfs_class = NULL;
1247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 }
1249}
1250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun)
1252{
1253 struct adpt_device* d;
1254
1255 if(chan < 0 || chan >= MAX_CHANNEL)
1256 return NULL;
1257
1258 if( pHba->channel[chan].device == NULL){
1259 printk(KERN_DEBUG"Adaptec I2O RAID: Trying to find device before they are allocated\n");
1260 return NULL;
1261 }
1262
1263 d = pHba->channel[chan].device[id];
1264 if(!d || d->tid == 0) {
1265 return NULL;
1266 }
1267
1268 /* If it is the only lun at that address then this should match*/
1269 if(d->scsi_lun == lun){
1270 return d;
1271 }
1272
1273 /* else we need to look through all the luns */
1274 for(d=d->next_lun ; d ; d = d->next_lun){
1275 if(d->scsi_lun == lun){
1276 return d;
1277 }
1278 }
1279 return NULL;
1280}
1281
1282
1283static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout)
1284{
1285 // I used my own version of the WAIT_QUEUE_HEAD
1286 // to handle some version differences
1287 // When embedded in the kernel this could go back to the vanilla one
1288 ADPT_DECLARE_WAIT_QUEUE_HEAD(adpt_wq_i2o_post);
1289 int status = 0;
1290 ulong flags = 0;
1291 struct adpt_i2o_post_wait_data *p1, *p2;
1292 struct adpt_i2o_post_wait_data *wait_data =
Julia Lawallda2907f2010-05-30 15:49:22 +02001293 kmalloc(sizeof(struct adpt_i2o_post_wait_data), GFP_ATOMIC);
Andrew Morton4452ea52005-06-23 00:10:26 -07001294 DECLARE_WAITQUEUE(wait, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
Andrew Morton4452ea52005-06-23 00:10:26 -07001296 if (!wait_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 return -ENOMEM;
Andrew Morton4452ea52005-06-23 00:10:26 -07001298
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 /*
1300 * The spin locking is needed to keep anyone from playing
1301 * with the queue pointers and id while we do the same
1302 */
1303 spin_lock_irqsave(&adpt_post_wait_lock, flags);
1304 // TODO we need a MORE unique way of getting ids
1305 // to support async LCT get
1306 wait_data->next = adpt_post_wait_queue;
1307 adpt_post_wait_queue = wait_data;
1308 adpt_post_wait_id++;
1309 adpt_post_wait_id &= 0x7fff;
1310 wait_data->id = adpt_post_wait_id;
1311 spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
1312
1313 wait_data->wq = &adpt_wq_i2o_post;
1314 wait_data->status = -ETIMEDOUT;
1315
Andrew Morton4452ea52005-06-23 00:10:26 -07001316 add_wait_queue(&adpt_wq_i2o_post, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317
1318 msg[2] |= 0x80000000 | ((u32)wait_data->id);
1319 timeout *= HZ;
1320 if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){
1321 set_current_state(TASK_INTERRUPTIBLE);
1322 if(pHba->host)
1323 spin_unlock_irq(pHba->host->host_lock);
1324 if (!timeout)
1325 schedule();
1326 else{
1327 timeout = schedule_timeout(timeout);
1328 if (timeout == 0) {
1329 // I/O issued, but cannot get result in
1330 // specified time. Freeing resorces is
1331 // dangerous.
1332 status = -ETIME;
1333 }
1334 }
1335 if(pHba->host)
1336 spin_lock_irq(pHba->host->host_lock);
1337 }
Andrew Morton4452ea52005-06-23 00:10:26 -07001338 remove_wait_queue(&adpt_wq_i2o_post, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
1340 if(status == -ETIMEDOUT){
1341 printk(KERN_INFO"dpti%d: POST WAIT TIMEOUT\n",pHba->unit);
1342 // We will have to free the wait_data memory during shutdown
1343 return status;
1344 }
1345
1346 /* Remove the entry from the queue. */
1347 p2 = NULL;
1348 spin_lock_irqsave(&adpt_post_wait_lock, flags);
1349 for(p1 = adpt_post_wait_queue; p1; p2 = p1, p1 = p1->next) {
1350 if(p1 == wait_data) {
1351 if(p1->status == I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION ) {
1352 status = -EOPNOTSUPP;
1353 }
1354 if(p2) {
1355 p2->next = p1->next;
1356 } else {
1357 adpt_post_wait_queue = p1->next;
1358 }
1359 break;
1360 }
1361 }
1362 spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
1363
1364 kfree(wait_data);
1365
1366 return status;
1367}
1368
1369
1370static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len)
1371{
1372
1373 u32 m = EMPTY_QUEUE;
1374 u32 __iomem *msg;
1375 ulong timeout = jiffies + 30*HZ;
1376 do {
1377 rmb();
1378 m = readl(pHba->post_port);
1379 if (m != EMPTY_QUEUE) {
1380 break;
1381 }
1382 if(time_after(jiffies,timeout)){
1383 printk(KERN_WARNING"dpti%d: Timeout waiting for message frame!\n", pHba->unit);
1384 return -ETIMEDOUT;
1385 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001386 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 } while(m == EMPTY_QUEUE);
1388
1389 msg = pHba->msg_addr_virt + m;
1390 memcpy_toio(msg, data, len);
1391 wmb();
1392
1393 //post message
1394 writel(m, pHba->post_port);
1395 wmb();
1396
1397 return 0;
1398}
1399
1400
1401static void adpt_i2o_post_wait_complete(u32 context, int status)
1402{
1403 struct adpt_i2o_post_wait_data *p1 = NULL;
1404 /*
1405 * We need to search through the adpt_post_wait
1406 * queue to see if the given message is still
1407 * outstanding. If not, it means that the IOP
1408 * took longer to respond to the message than we
1409 * had allowed and timer has already expired.
1410 * Not much we can do about that except log
1411 * it for debug purposes, increase timeout, and recompile
1412 *
1413 * Lock needed to keep anyone from moving queue pointers
1414 * around while we're looking through them.
1415 */
1416
1417 context &= 0x7fff;
1418
1419 spin_lock(&adpt_post_wait_lock);
1420 for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) {
1421 if(p1->id == context) {
1422 p1->status = status;
1423 spin_unlock(&adpt_post_wait_lock);
1424 wake_up_interruptible(p1->wq);
1425 return;
1426 }
1427 }
1428 spin_unlock(&adpt_post_wait_lock);
1429 // If this happens we lose commands that probably really completed
1430 printk(KERN_DEBUG"dpti: Could Not find task %d in wait queue\n",context);
1431 printk(KERN_DEBUG" Tasks in wait queue:\n");
1432 for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) {
1433 printk(KERN_DEBUG" %d\n",p1->id);
1434 }
1435 return;
1436}
1437
1438static s32 adpt_i2o_reset_hba(adpt_hba* pHba)
1439{
1440 u32 msg[8];
1441 u8* status;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001442 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 u32 m = EMPTY_QUEUE ;
1444 ulong timeout = jiffies + (TMOUT_IOPRESET*HZ);
1445
1446 if(pHba->initialized == FALSE) { // First time reset should be quick
1447 timeout = jiffies + (25*HZ);
1448 } else {
1449 adpt_i2o_quiesce_hba(pHba);
1450 }
1451
1452 do {
1453 rmb();
1454 m = readl(pHba->post_port);
1455 if (m != EMPTY_QUEUE) {
1456 break;
1457 }
1458 if(time_after(jiffies,timeout)){
1459 printk(KERN_WARNING"Timeout waiting for message!\n");
1460 return -ETIMEDOUT;
1461 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001462 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 } while (m == EMPTY_QUEUE);
1464
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001465 status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 if(status == NULL) {
1467 adpt_send_nop(pHba, m);
1468 printk(KERN_ERR"IOP reset failed - no free memory.\n");
1469 return -ENOMEM;
1470 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001471 memset(status,0,4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
1473 msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
1474 msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
1475 msg[2]=0;
1476 msg[3]=0;
1477 msg[4]=0;
1478 msg[5]=0;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001479 msg[6]=dma_low(addr);
1480 msg[7]=dma_high(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
1482 memcpy_toio(pHba->msg_addr_virt+m, msg, sizeof(msg));
1483 wmb();
1484 writel(m, pHba->post_port);
1485 wmb();
1486
1487 while(*status == 0){
1488 if(time_after(jiffies,timeout)){
1489 printk(KERN_WARNING"%s: IOP Reset Timeout\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001490 /* We lose 4 bytes of "status" here, but we cannot
1491 free these because controller may awake and corrupt
1492 those bytes at any time */
1493 /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 return -ETIMEDOUT;
1495 }
1496 rmb();
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001497 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 }
1499
1500 if(*status == 0x01 /*I2O_EXEC_IOP_RESET_IN_PROGRESS*/) {
1501 PDEBUG("%s: Reset in progress...\n", pHba->name);
1502 // Here we wait for message frame to become available
1503 // indicated that reset has finished
1504 do {
1505 rmb();
1506 m = readl(pHba->post_port);
1507 if (m != EMPTY_QUEUE) {
1508 break;
1509 }
1510 if(time_after(jiffies,timeout)){
1511 printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001512 /* We lose 4 bytes of "status" here, but we
1513 cannot free these because controller may
1514 awake and corrupt those bytes at any time */
1515 /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 return -ETIMEDOUT;
1517 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08001518 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 } while (m == EMPTY_QUEUE);
1520 // Flush the offset
1521 adpt_send_nop(pHba, m);
1522 }
1523 adpt_i2o_status_get(pHba);
1524 if(*status == 0x02 ||
1525 pHba->status_block->iop_state != ADAPTER_STATE_RESET) {
1526 printk(KERN_WARNING"%s: Reset reject, trying to clear\n",
1527 pHba->name);
1528 } else {
1529 PDEBUG("%s: Reset completed.\n", pHba->name);
1530 }
1531
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001532 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533#ifdef UARTDELAY
1534 // This delay is to allow someone attached to the card through the debug UART to
1535 // set up the dump levels that they want before the rest of the initialization sequence
1536 adpt_delay(20000);
1537#endif
1538 return 0;
1539}
1540
1541
1542static int adpt_i2o_parse_lct(adpt_hba* pHba)
1543{
1544 int i;
1545 int max;
1546 int tid;
1547 struct i2o_device *d;
1548 i2o_lct *lct = pHba->lct;
1549 u8 bus_no = 0;
1550 s16 scsi_id;
1551 s16 scsi_lun;
1552 u32 buf[10]; // larger than 7, or 8 ...
1553 struct adpt_device* pDev;
1554
1555 if (lct == NULL) {
1556 printk(KERN_ERR "%s: LCT is empty???\n",pHba->name);
1557 return -1;
1558 }
1559
1560 max = lct->table_size;
1561 max -= 3;
1562 max /= 9;
1563
1564 for(i=0;i<max;i++) {
1565 if( lct->lct_entry[i].user_tid != 0xfff){
1566 /*
1567 * If we have hidden devices, we need to inform the upper layers about
1568 * the possible maximum id reference to handle device access when
1569 * an array is disassembled. This code has no other purpose but to
1570 * allow us future access to devices that are currently hidden
1571 * behind arrays, hotspares or have not been configured (JBOD mode).
1572 */
1573 if( lct->lct_entry[i].class_id != I2O_CLASS_RANDOM_BLOCK_STORAGE &&
1574 lct->lct_entry[i].class_id != I2O_CLASS_SCSI_PERIPHERAL &&
1575 lct->lct_entry[i].class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
1576 continue;
1577 }
1578 tid = lct->lct_entry[i].tid;
1579 // I2O_DPT_DEVICE_INFO_GROUP_NO;
1580 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) {
1581 continue;
1582 }
1583 bus_no = buf[0]>>16;
1584 scsi_id = buf[1];
1585 scsi_lun = (buf[2]>>8 )&0xff;
1586 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1587 printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no);
1588 continue;
1589 }
1590 if (scsi_id >= MAX_ID){
1591 printk(KERN_WARNING"%s: SCSI ID %d out of range \n", pHba->name, bus_no);
1592 continue;
1593 }
1594 if(bus_no > pHba->top_scsi_channel){
1595 pHba->top_scsi_channel = bus_no;
1596 }
1597 if(scsi_id > pHba->top_scsi_id){
1598 pHba->top_scsi_id = scsi_id;
1599 }
1600 if(scsi_lun > pHba->top_scsi_lun){
1601 pHba->top_scsi_lun = scsi_lun;
1602 }
1603 continue;
1604 }
Robert P. J. Day5cbded52006-12-13 00:35:56 -08001605 d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 if(d==NULL)
1607 {
1608 printk(KERN_CRIT"%s: Out of memory for I2O device data.\n",pHba->name);
1609 return -ENOMEM;
1610 }
1611
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07001612 d->controller = pHba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 d->next = NULL;
1614
1615 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
1616
1617 d->flags = 0;
1618 tid = d->lct_data.tid;
1619 adpt_i2o_report_hba_unit(pHba, d);
1620 adpt_i2o_install_device(pHba, d);
1621 }
1622 bus_no = 0;
1623 for(d = pHba->devices; d ; d = d->next) {
1624 if(d->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT ||
1625 d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PORT){
1626 tid = d->lct_data.tid;
1627 // TODO get the bus_no from hrt-but for now they are in order
1628 //bus_no =
1629 if(bus_no > pHba->top_scsi_channel){
1630 pHba->top_scsi_channel = bus_no;
1631 }
1632 pHba->channel[bus_no].type = d->lct_data.class_id;
1633 pHba->channel[bus_no].tid = tid;
1634 if(adpt_i2o_query_scalar(pHba, tid, 0x0200, -1, buf, 28)>=0)
1635 {
1636 pHba->channel[bus_no].scsi_id = buf[1];
1637 PDEBUG("Bus %d - SCSI ID %d.\n", bus_no, buf[1]);
1638 }
1639 // TODO remove - this is just until we get from hrt
1640 bus_no++;
1641 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1642 printk(KERN_WARNING"%s: Channel number %d out of range - LCT\n", pHba->name, bus_no);
1643 break;
1644 }
1645 }
1646 }
1647
1648 // Setup adpt_device table
1649 for(d = pHba->devices; d ; d = d->next) {
1650 if(d->lct_data.class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE ||
1651 d->lct_data.class_id == I2O_CLASS_SCSI_PERIPHERAL ||
1652 d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
1653
1654 tid = d->lct_data.tid;
1655 scsi_id = -1;
1656 // I2O_DPT_DEVICE_INFO_GROUP_NO;
1657 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)>=0) {
1658 bus_no = buf[0]>>16;
1659 scsi_id = buf[1];
1660 scsi_lun = (buf[2]>>8 )&0xff;
1661 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
1662 continue;
1663 }
1664 if (scsi_id >= MAX_ID) {
1665 continue;
1666 }
1667 if( pHba->channel[bus_no].device[scsi_id] == NULL){
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301668 pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 if(pDev == NULL) {
1670 return -ENOMEM;
1671 }
1672 pHba->channel[bus_no].device[scsi_id] = pDev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 } else {
1674 for( pDev = pHba->channel[bus_no].device[scsi_id];
1675 pDev->next_lun; pDev = pDev->next_lun){
1676 }
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301677 pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 if(pDev->next_lun == NULL) {
1679 return -ENOMEM;
1680 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 pDev = pDev->next_lun;
1682 }
1683 pDev->tid = tid;
1684 pDev->scsi_channel = bus_no;
1685 pDev->scsi_id = scsi_id;
1686 pDev->scsi_lun = scsi_lun;
1687 pDev->pI2o_dev = d;
1688 d->owner = pDev;
1689 pDev->type = (buf[0])&0xff;
1690 pDev->flags = (buf[0]>>8)&0xff;
1691 if(scsi_id > pHba->top_scsi_id){
1692 pHba->top_scsi_id = scsi_id;
1693 }
1694 if(scsi_lun > pHba->top_scsi_lun){
1695 pHba->top_scsi_lun = scsi_lun;
1696 }
1697 }
1698 if(scsi_id == -1){
1699 printk(KERN_WARNING"Could not find SCSI ID for %s\n",
1700 d->lct_data.identity_tag);
1701 }
1702 }
1703 }
1704 return 0;
1705}
1706
1707
1708/*
1709 * Each I2O controller has a chain of devices on it - these match
1710 * the useful parts of the LCT of the board.
1711 */
1712
1713static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d)
1714{
Arjan van de Ven0b950672006-01-11 13:16:10 +01001715 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 d->controller=pHba;
1717 d->owner=NULL;
1718 d->next=pHba->devices;
1719 d->prev=NULL;
1720 if (pHba->devices != NULL){
1721 pHba->devices->prev=d;
1722 }
1723 pHba->devices=d;
1724 *d->dev_name = 0;
1725
Arjan van de Ven0b950672006-01-11 13:16:10 +01001726 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 return 0;
1728}
1729
1730static int adpt_open(struct inode *inode, struct file *file)
1731{
1732 int minor;
1733 adpt_hba* pHba;
1734
Jonathan Corbetdea3f662008-05-16 14:11:09 -06001735 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 //TODO check for root access
1737 //
1738 minor = iminor(inode);
1739 if (minor >= hba_count) {
Jonathan Corbetdea3f662008-05-16 14:11:09 -06001740 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 return -ENXIO;
1742 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001743 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1745 if (pHba->unit == minor) {
1746 break; /* found adapter */
1747 }
1748 }
1749 if (pHba == NULL) {
Arjan van de Ven0b950672006-01-11 13:16:10 +01001750 mutex_unlock(&adpt_configuration_lock);
Jonathan Corbetdea3f662008-05-16 14:11:09 -06001751 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 return -ENXIO;
1753 }
1754
1755// if(pHba->in_use){
Arjan van de Ven0b950672006-01-11 13:16:10 +01001756 // mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757// return -EBUSY;
1758// }
1759
1760 pHba->in_use = 1;
Arjan van de Ven0b950672006-01-11 13:16:10 +01001761 mutex_unlock(&adpt_configuration_lock);
Jonathan Corbetdea3f662008-05-16 14:11:09 -06001762 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763
1764 return 0;
1765}
1766
1767static int adpt_close(struct inode *inode, struct file *file)
1768{
1769 int minor;
1770 adpt_hba* pHba;
1771
1772 minor = iminor(inode);
1773 if (minor >= hba_count) {
1774 return -ENXIO;
1775 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001776 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 for (pHba = hba_chain; pHba; pHba = pHba->next) {
1778 if (pHba->unit == minor) {
1779 break; /* found adapter */
1780 }
1781 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01001782 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 if (pHba == NULL) {
1784 return -ENXIO;
1785 }
1786
1787 pHba->in_use = 0;
1788
1789 return 0;
1790}
1791
1792
1793static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
1794{
1795 u32 msg[MAX_MESSAGE_SIZE];
1796 u32* reply = NULL;
1797 u32 size = 0;
1798 u32 reply_size = 0;
1799 u32 __user *user_msg = arg;
1800 u32 __user * user_reply = NULL;
1801 void *sg_list[pHba->sg_tablesize];
1802 u32 sg_offset = 0;
1803 u32 sg_count = 0;
1804 int sg_index = 0;
1805 u32 i = 0;
1806 u32 rcode = 0;
1807 void *p = NULL;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001808 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 ulong flags = 0;
1810
1811 memset(&msg, 0, MAX_MESSAGE_SIZE*4);
1812 // get user msg size in u32s
1813 if(get_user(size, &user_msg[0])){
1814 return -EFAULT;
1815 }
1816 size = size>>16;
1817
1818 user_reply = &user_msg[size];
1819 if(size > MAX_MESSAGE_SIZE){
1820 return -EFAULT;
1821 }
1822 size *= 4; // Convert to bytes
1823
1824 /* Copy in the user's I2O command */
1825 if(copy_from_user(msg, user_msg, size)) {
1826 return -EFAULT;
1827 }
1828 get_user(reply_size, &user_reply[0]);
1829 reply_size = reply_size>>16;
1830 if(reply_size > REPLY_FRAME_SIZE){
1831 reply_size = REPLY_FRAME_SIZE;
1832 }
1833 reply_size *= 4;
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05301834 reply = kzalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 if(reply == NULL) {
1836 printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name);
1837 return -ENOMEM;
1838 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 sg_offset = (msg[0]>>4)&0xf;
1840 msg[2] = 0x40000000; // IOCTL context
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001841 msg[3] = adpt_ioctl_to_context(pHba, reply);
1842 if (msg[3] == (u32)-1)
1843 return -EBUSY;
1844
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 memset(sg_list,0, sizeof(sg_list[0])*pHba->sg_tablesize);
1846 if(sg_offset) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001847 // TODO add 64 bit API
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 struct sg_simple_element *sg = (struct sg_simple_element*) (msg+sg_offset);
1849 sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
1850 if (sg_count > pHba->sg_tablesize){
1851 printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", pHba->name,sg_count);
1852 kfree (reply);
1853 return -EINVAL;
1854 }
1855
1856 for(i = 0; i < sg_count; i++) {
1857 int sg_size;
1858
1859 if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) {
1860 printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",pHba->name,i, sg[i].flag_count);
1861 rcode = -EINVAL;
1862 goto cleanup;
1863 }
1864 sg_size = sg[i].flag_count & 0xffffff;
1865 /* Allocate memory for the transfer */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001866 p = dma_alloc_coherent(&pHba->pDev->dev, sg_size, &addr, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 if(!p) {
1868 printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
1869 pHba->name,sg_size,i,sg_count);
1870 rcode = -ENOMEM;
1871 goto cleanup;
1872 }
1873 sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
1874 /* Copy in the user's SG buffer if necessary */
1875 if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001876 // sg_simple_element API is 32 bit
1877 if (copy_from_user(p,(void __user *)(ulong)sg[i].addr_bus, sg_size)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",pHba->name,i);
1879 rcode = -EFAULT;
1880 goto cleanup;
1881 }
1882 }
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001883 /* sg_simple_element API is 32 bit, but addr < 4GB */
1884 sg[i].addr_bus = addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 }
1886 }
1887
1888 do {
1889 if(pHba->host)
1890 spin_lock_irqsave(pHba->host->host_lock, flags);
1891 // This state stops any new commands from enterring the
1892 // controller while processing the ioctl
1893// pHba->state |= DPTI_STATE_IOCTL;
1894// We can't set this now - The scsi subsystem sets host_blocked and
1895// the queue empties and stops. We need a way to restart the queue
1896 rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER);
1897 if (rcode != 0)
1898 printk("adpt_i2o_passthru: post wait failed %d %p\n",
1899 rcode, reply);
1900// pHba->state &= ~DPTI_STATE_IOCTL;
1901 if(pHba->host)
1902 spin_unlock_irqrestore(pHba->host->host_lock, flags);
1903 } while(rcode == -ETIMEDOUT);
1904
1905 if(rcode){
1906 goto cleanup;
1907 }
1908
1909 if(sg_offset) {
1910 /* Copy back the Scatter Gather buffers back to user space */
1911 u32 j;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001912 // TODO add 64 bit API
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 struct sg_simple_element* sg;
1914 int sg_size;
1915
1916 // re-acquire the original message to handle correctly the sg copy operation
1917 memset(&msg, 0, MAX_MESSAGE_SIZE*4);
1918 // get user msg size in u32s
1919 if(get_user(size, &user_msg[0])){
1920 rcode = -EFAULT;
1921 goto cleanup;
1922 }
1923 size = size>>16;
1924 size *= 4;
Alan Coxef7562b2009-10-27 15:35:35 +00001925 if (size > MAX_MESSAGE_SIZE) {
OGAWA Hirofumiaefba412009-10-30 17:02:31 +09001926 rcode = -EINVAL;
Alan Coxef7562b2009-10-27 15:35:35 +00001927 goto cleanup;
1928 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 /* Copy in the user's I2O command */
1930 if (copy_from_user (msg, user_msg, size)) {
1931 rcode = -EFAULT;
1932 goto cleanup;
1933 }
1934 sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
1935
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001936 // TODO add 64 bit API
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 sg = (struct sg_simple_element*)(msg + sg_offset);
1938 for (j = 0; j < sg_count; j++) {
1939 /* Copy out the SG list to user's buffer if necessary */
1940 if(! (sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) {
1941 sg_size = sg[j].flag_count & 0xffffff;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02001942 // sg_simple_element API is 32 bit
1943 if (copy_to_user((void __user *)(ulong)sg[j].addr_bus,sg_list[j], sg_size)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",pHba->name, sg_list[j], sg[j].addr_bus);
1945 rcode = -EFAULT;
1946 goto cleanup;
1947 }
1948 }
1949 }
1950 }
1951
1952 /* Copy back the reply to user space */
1953 if (reply_size) {
1954 // we wrote our own values for context - now restore the user supplied ones
1955 if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) {
1956 printk(KERN_WARNING"%s: Could not copy message context FROM user\n",pHba->name);
1957 rcode = -EFAULT;
1958 }
1959 if(copy_to_user(user_reply, reply, reply_size)) {
1960 printk(KERN_WARNING"%s: Could not copy reply TO user\n",pHba->name);
1961 rcode = -EFAULT;
1962 }
1963 }
1964
1965
1966cleanup:
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001967 if (rcode != -ETIME && rcode != -EINTR) {
1968 struct sg_simple_element *sg =
1969 (struct sg_simple_element*) (msg +sg_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 kfree (reply);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02001971 while(sg_index) {
1972 if(sg_list[--sg_index]) {
1973 dma_free_coherent(&pHba->pDev->dev,
1974 sg[sg_index].flag_count & 0xffffff,
1975 sg_list[sg_index],
1976 sg[sg_index].addr_bus);
1977 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 }
1979 }
1980 return rcode;
1981}
1982
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983#if defined __ia64__
1984static void adpt_ia64_info(sysInfo_S* si)
1985{
1986 // This is all the info we need for now
1987 // We will add more info as our new
1988 // managmenent utility requires it
1989 si->processorType = PROC_IA64;
1990}
1991#endif
1992
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993#if defined __sparc__
1994static void adpt_sparc_info(sysInfo_S* si)
1995{
1996 // This is all the info we need for now
1997 // We will add more info as our new
1998 // managmenent utility requires it
1999 si->processorType = PROC_ULTRASPARC;
2000}
2001#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002#if defined __alpha__
2003static void adpt_alpha_info(sysInfo_S* si)
2004{
2005 // This is all the info we need for now
2006 // We will add more info as our new
2007 // managmenent utility requires it
2008 si->processorType = PROC_ALPHA;
2009}
2010#endif
2011
2012#if defined __i386__
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013static void adpt_i386_info(sysInfo_S* si)
2014{
2015 // This is all the info we need for now
2016 // We will add more info as our new
2017 // managmenent utility requires it
2018 switch (boot_cpu_data.x86) {
2019 case CPU_386:
2020 si->processorType = PROC_386;
2021 break;
2022 case CPU_486:
2023 si->processorType = PROC_486;
2024 break;
2025 case CPU_586:
2026 si->processorType = PROC_PENTIUM;
2027 break;
2028 default: // Just in case
2029 si->processorType = PROC_PENTIUM;
2030 break;
2031 }
2032}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033#endif
2034
Andrew Morton8b2cc912008-05-06 20:42:42 -07002035/*
2036 * This routine returns information about the system. This does not effect
2037 * any logic and if the info is wrong - it doesn't matter.
2038 */
2039
2040/* Get all the info we can not get from kernel services */
2041static int adpt_system_info(void __user *buffer)
2042{
2043 sysInfo_S si;
2044
2045 memset(&si, 0, sizeof(si));
2046
2047 si.osType = OS_LINUX;
2048 si.osMajorVersion = 0;
2049 si.osMinorVersion = 0;
2050 si.osRevision = 0;
2051 si.busType = SI_PCI_BUS;
2052 si.processorFamily = DPTI_sig.dsProcessorFamily;
2053
2054#if defined __i386__
2055 adpt_i386_info(&si);
2056#elif defined (__ia64__)
2057 adpt_ia64_info(&si);
2058#elif defined(__sparc__)
2059 adpt_sparc_info(&si);
2060#elif defined (__alpha__)
2061 adpt_alpha_info(&si);
2062#else
2063 si.processorType = 0xff ;
2064#endif
2065 if (copy_to_user(buffer, &si, sizeof(si))){
2066 printk(KERN_WARNING"dpti: Could not copy buffer TO user\n");
2067 return -EFAULT;
2068 }
2069
2070 return 0;
2071}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072
Arnd Bergmannf4927c42010-04-27 00:24:01 +02002073static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074{
2075 int minor;
2076 int error = 0;
2077 adpt_hba* pHba;
2078 ulong flags = 0;
2079 void __user *argp = (void __user *)arg;
2080
2081 minor = iminor(inode);
2082 if (minor >= DPTI_MAX_HBA){
2083 return -ENXIO;
2084 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01002085 mutex_lock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 for (pHba = hba_chain; pHba; pHba = pHba->next) {
2087 if (pHba->unit == minor) {
2088 break; /* found adapter */
2089 }
2090 }
Arjan van de Ven0b950672006-01-11 13:16:10 +01002091 mutex_unlock(&adpt_configuration_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 if(pHba == NULL){
2093 return -ENXIO;
2094 }
2095
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002096 while((volatile u32) pHba->state & DPTI_STATE_RESET )
2097 schedule_timeout_uninterruptible(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098
2099 switch (cmd) {
2100 // TODO: handle 3 cases
2101 case DPT_SIGNATURE:
2102 if (copy_to_user(argp, &DPTI_sig, sizeof(DPTI_sig))) {
2103 return -EFAULT;
2104 }
2105 break;
2106 case I2OUSRCMD:
2107 return adpt_i2o_passthru(pHba, argp);
2108
2109 case DPT_CTRLINFO:{
2110 drvrHBAinfo_S HbaInfo;
2111
2112#define FLG_OSD_PCI_VALID 0x0001
2113#define FLG_OSD_DMA 0x0002
2114#define FLG_OSD_I2O 0x0004
2115 memset(&HbaInfo, 0, sizeof(HbaInfo));
2116 HbaInfo.drvrHBAnum = pHba->unit;
2117 HbaInfo.baseAddr = (ulong) pHba->base_addr_phys;
2118 HbaInfo.blinkState = adpt_read_blink_led(pHba);
2119 HbaInfo.pciBusNum = pHba->pDev->bus->number;
2120 HbaInfo.pciDeviceNum=PCI_SLOT(pHba->pDev->devfn);
2121 HbaInfo.Interrupt = pHba->pDev->irq;
2122 HbaInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O;
2123 if(copy_to_user(argp, &HbaInfo, sizeof(HbaInfo))){
2124 printk(KERN_WARNING"%s: Could not copy HbaInfo TO user\n",pHba->name);
2125 return -EFAULT;
2126 }
2127 break;
2128 }
2129 case DPT_SYSINFO:
2130 return adpt_system_info(argp);
2131 case DPT_BLINKLED:{
2132 u32 value;
2133 value = (u32)adpt_read_blink_led(pHba);
2134 if (copy_to_user(argp, &value, sizeof(value))) {
2135 return -EFAULT;
2136 }
2137 break;
2138 }
2139 case I2ORESETCMD:
2140 if(pHba->host)
2141 spin_lock_irqsave(pHba->host->host_lock, flags);
2142 adpt_hba_reset(pHba);
2143 if(pHba->host)
2144 spin_unlock_irqrestore(pHba->host->host_lock, flags);
2145 break;
2146 case I2ORESCANCMD:
2147 adpt_rescan(pHba);
2148 break;
2149 default:
2150 return -EINVAL;
2151 }
2152
2153 return error;
2154}
2155
Arnd Bergmannf4927c42010-04-27 00:24:01 +02002156static long adpt_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
2157{
2158 struct inode *inode;
2159 long ret;
2160
2161 inode = file->f_dentry->d_inode;
2162
2163 lock_kernel();
2164 ret = adpt_ioctl(inode, file, cmd, arg);
2165 unlock_kernel();
2166
2167 return ret;
2168}
2169
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002170#ifdef CONFIG_COMPAT
2171static long compat_adpt_ioctl(struct file *file,
2172 unsigned int cmd, unsigned long arg)
2173{
2174 struct inode *inode;
2175 long ret;
2176
2177 inode = file->f_dentry->d_inode;
2178
2179 lock_kernel();
2180
2181 switch(cmd) {
2182 case DPT_SIGNATURE:
2183 case I2OUSRCMD:
2184 case DPT_CTRLINFO:
2185 case DPT_SYSINFO:
2186 case DPT_BLINKLED:
2187 case I2ORESETCMD:
2188 case I2ORESCANCMD:
2189 case (DPT_TARGET_BUSY & 0xFFFF):
2190 case DPT_TARGET_BUSY:
2191 ret = adpt_ioctl(inode, file, cmd, arg);
2192 break;
2193 default:
2194 ret = -ENOIOCTLCMD;
2195 }
2196
2197 unlock_kernel();
2198
2199 return ret;
2200}
2201#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202
David Howells7d12e782006-10-05 14:55:46 +01002203static irqreturn_t adpt_isr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204{
2205 struct scsi_cmnd* cmd;
2206 adpt_hba* pHba = dev_id;
2207 u32 m;
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002208 void __iomem *reply;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 u32 status=0;
2210 u32 context;
2211 ulong flags = 0;
2212 int handled = 0;
2213
2214 if (pHba == NULL){
2215 printk(KERN_WARNING"adpt_isr: NULL dev_id\n");
2216 return IRQ_NONE;
2217 }
2218 if(pHba->host)
2219 spin_lock_irqsave(pHba->host->host_lock, flags);
2220
2221 while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) {
2222 m = readl(pHba->reply_port);
2223 if(m == EMPTY_QUEUE){
2224 // Try twice then give up
2225 rmb();
2226 m = readl(pHba->reply_port);
2227 if(m == EMPTY_QUEUE){
2228 // This really should not happen
2229 printk(KERN_ERR"dpti: Could not get reply frame\n");
2230 goto out;
2231 }
2232 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002233 if (pHba->reply_pool_pa <= m &&
2234 m < pHba->reply_pool_pa +
2235 (pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4)) {
2236 reply = (u8 *)pHba->reply_pool +
2237 (m - pHba->reply_pool_pa);
2238 } else {
2239 /* Ick, we should *never* be here */
2240 printk(KERN_ERR "dpti: reply frame not from pool\n");
2241 reply = (u8 *)bus_to_virt(m);
2242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243
2244 if (readl(reply) & MSG_FAIL) {
2245 u32 old_m = readl(reply+28);
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002246 void __iomem *msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 u32 old_context;
2248 PDEBUG("%s: Failed message\n",pHba->name);
2249 if(old_m >= 0x100000){
2250 printk(KERN_ERR"%s: Bad preserved MFA (%x)- dropping frame\n",pHba->name,old_m);
2251 writel(m,pHba->reply_port);
2252 continue;
2253 }
2254 // Transaction context is 0 in failed reply frame
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002255 msg = pHba->msg_addr_virt + old_m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 old_context = readl(msg+12);
2257 writel(old_context, reply+12);
2258 adpt_send_nop(pHba, old_m);
2259 }
2260 context = readl(reply+8);
2261 if(context & 0x40000000){ // IOCTL
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002262 void *p = adpt_ioctl_from_context(pHba, readl(reply+12));
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002263 if( p != NULL) {
2264 memcpy_fromio(p, reply, REPLY_FRAME_SIZE * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 }
2266 // All IOCTLs will also be post wait
2267 }
2268 if(context & 0x80000000){ // Post wait message
2269 status = readl(reply+16);
2270 if(status >> 24){
2271 status &= 0xffff; /* Get detail status */
2272 } else {
2273 status = I2O_POST_WAIT_OK;
2274 }
2275 if(!(context & 0x40000000)) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002276 cmd = adpt_cmd_from_context(pHba,
2277 readl(reply+12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 if(cmd != NULL) {
2279 printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context);
2280 }
2281 }
2282 adpt_i2o_post_wait_complete(context, status);
2283 } else { // SCSI message
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002284 cmd = adpt_cmd_from_context (pHba, readl(reply+12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 if(cmd != NULL){
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002286 scsi_dma_unmap(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 if(cmd->serial_number != 0) { // If not timedout
2288 adpt_i2o_to_scsi(reply, cmd);
2289 }
2290 }
2291 }
2292 writel(m, pHba->reply_port);
2293 wmb();
2294 rmb();
2295 }
2296 handled = 1;
2297out: if(pHba->host)
2298 spin_unlock_irqrestore(pHba->host->host_lock, flags);
2299 return IRQ_RETVAL(handled);
2300}
2301
2302static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* d)
2303{
2304 int i;
2305 u32 msg[MAX_MESSAGE_SIZE];
2306 u32* mptr;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002307 u32* lptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 u32 *lenptr;
2309 int direction;
2310 int scsidir;
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002311 int nseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 u32 len;
2313 u32 reqlen;
2314 s32 rcode;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002315 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316
2317 memset(msg, 0 , sizeof(msg));
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002318 len = scsi_bufflen(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 direction = 0x00000000;
2320
2321 scsidir = 0x00000000; // DATA NO XFER
2322 if(len) {
2323 /*
2324 * Set SCBFlags to indicate if data is being transferred
2325 * in or out, or no data transfer
2326 * Note: Do not have to verify index is less than 0 since
2327 * cmd->cmnd[0] is an unsigned char
2328 */
2329 switch(cmd->sc_data_direction){
2330 case DMA_FROM_DEVICE:
2331 scsidir =0x40000000; // DATA IN (iop<--dev)
2332 break;
2333 case DMA_TO_DEVICE:
2334 direction=0x04000000; // SGL OUT
2335 scsidir =0x80000000; // DATA OUT (iop-->dev)
2336 break;
2337 case DMA_NONE:
2338 break;
2339 case DMA_BIDIRECTIONAL:
2340 scsidir =0x40000000; // DATA IN (iop<--dev)
2341 // Assume In - and continue;
2342 break;
2343 default:
2344 printk(KERN_WARNING"%s: scsi opcode 0x%x not supported.\n",
2345 pHba->name, cmd->cmnd[0]);
2346 cmd->result = (DID_OK <<16) | (INITIATOR_ERROR << 8);
2347 cmd->scsi_done(cmd);
2348 return 0;
2349 }
2350 }
2351 // msg[0] is set later
2352 // I2O_CMD_SCSI_EXEC
2353 msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid);
2354 msg[2] = 0;
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002355 msg[3] = adpt_cmd_to_context(cmd); /* Want SCSI control block back */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 // Our cards use the transaction context as the tag for queueing
2357 // Adaptec/DPT Private stuff
2358 msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16);
2359 msg[5] = d->tid;
2360 /* Direction, disconnect ok | sense data | simple queue , CDBLen */
2361 // I2O_SCB_FLAG_ENABLE_DISCONNECT |
2362 // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG |
2363 // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;
2364 msg[6] = scsidir|0x20a00000|cmd->cmd_len;
2365
2366 mptr=msg+7;
2367
2368 // Write SCSI command into the message - always 16 byte block
2369 memset(mptr, 0, 16);
2370 memcpy(mptr, cmd->cmnd, cmd->cmd_len);
2371 mptr+=4;
2372 lenptr=mptr++; /* Remember me - fill in when we know */
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002373 if (dpt_dma64(pHba)) {
2374 reqlen = 16; // SINGLE SGE
2375 *mptr++ = (0x7C<<24)+(2<<16)+0x02; /* Enable 64 bit */
2376 *mptr++ = 1 << PAGE_SHIFT;
2377 } else {
2378 reqlen = 14; // SINGLE SGE
2379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 /* Now fill in the SGList and command */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002382 nseg = scsi_dma_map(cmd);
2383 BUG_ON(nseg < 0);
2384 if (nseg) {
2385 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386
2387 len = 0;
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002388 scsi_for_each_sg(cmd, sg, nseg, i) {
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002389 lptr = mptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 *mptr++ = direction|0x10000000|sg_dma_len(sg);
2391 len+=sg_dma_len(sg);
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002392 addr = sg_dma_address(sg);
2393 *mptr++ = dma_low(addr);
2394 if (dpt_dma64(pHba))
2395 *mptr++ = dma_high(addr);
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002396 /* Make this an end of list */
2397 if (i == nseg - 1)
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02002398 *lptr = direction|0xD0000000|sg_dma_len(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 reqlen = mptr - msg;
2401 *lenptr = len;
2402
2403 if(cmd->underflow && len != cmd->underflow){
2404 printk(KERN_WARNING"Cmd len %08X Cmd underflow %08X\n",
2405 len, cmd->underflow);
2406 }
2407 } else {
FUJITA Tomonori10803de2007-05-26 02:08:10 +09002408 *lenptr = len = 0;
2409 reqlen = 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 }
2411
2412 /* Stick the headers on */
2413 msg[0] = reqlen<<16 | ((reqlen > 12) ? SGL_OFFSET_12 : SGL_OFFSET_0);
2414
2415 // Send it on it's way
2416 rcode = adpt_i2o_post_this(pHba, msg, reqlen<<2);
2417 if (rcode == 0) {
2418 return 0;
2419 }
2420 return rcode;
2421}
2422
2423
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002424static s32 adpt_scsi_host_alloc(adpt_hba* pHba, struct scsi_host_template *sht)
Andrew Morton24601bb2007-12-10 15:49:20 -08002425{
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002426 struct Scsi_Host *host;
Andrew Morton24601bb2007-12-10 15:49:20 -08002427
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002428 host = scsi_host_alloc(sht, sizeof(adpt_hba*));
Andrew Morton24601bb2007-12-10 15:49:20 -08002429 if (host == NULL) {
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02002430 printk("%s: scsi_host_alloc returned NULL\n", pHba->name);
Andrew Morton24601bb2007-12-10 15:49:20 -08002431 return -1;
2432 }
2433 host->hostdata[0] = (unsigned long)pHba;
2434 pHba->host = host;
2435
2436 host->irq = pHba->pDev->irq;
2437 /* no IO ports, so don't have to set host->io_port and
2438 * host->n_io_port
2439 */
2440 host->io_port = 0;
2441 host->n_io_port = 0;
2442 /* see comments in scsi_host.h */
2443 host->max_id = 16;
2444 host->max_lun = 256;
2445 host->max_channel = pHba->top_scsi_channel + 1;
2446 host->cmd_per_lun = 1;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002447 host->unique_id = (u32)sys_tbl_pa + pHba->unit;
Andrew Morton24601bb2007-12-10 15:49:20 -08002448 host->sg_tablesize = pHba->sg_tablesize;
2449 host->can_queue = pHba->post_fifo_size;
2450
2451 return 0;
2452}
2453
2454
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002455static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456{
2457 adpt_hba* pHba;
2458 u32 hba_status;
2459 u32 dev_status;
2460 u32 reply_flags = readl(reply) & 0xff00; // Leave it shifted up 8 bits
2461 // I know this would look cleaner if I just read bytes
2462 // but the model I have been using for all the rest of the
2463 // io is in 4 byte words - so I keep that model
2464 u16 detailed_status = readl(reply+16) &0xffff;
2465 dev_status = (detailed_status & 0xff);
2466 hba_status = detailed_status >> 8;
2467
2468 // calculate resid for sg
Miquel van Smoorenburgdf81d232008-11-05 00:09:12 +01002469 scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+20));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470
2471 pHba = (adpt_hba*) cmd->device->host->hostdata[0];
2472
2473 cmd->sense_buffer[0] = '\0'; // initialize sense valid flag to false
2474
2475 if(!(reply_flags & MSG_FAIL)) {
2476 switch(detailed_status & I2O_SCSI_DSC_MASK) {
2477 case I2O_SCSI_DSC_SUCCESS:
2478 cmd->result = (DID_OK << 16);
2479 // handle underflow
Miquel van Smoorenburgdf81d232008-11-05 00:09:12 +01002480 if (readl(reply+20) < cmd->underflow) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 cmd->result = (DID_ERROR <<16);
2482 printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name);
2483 }
2484 break;
2485 case I2O_SCSI_DSC_REQUEST_ABORTED:
2486 cmd->result = (DID_ABORT << 16);
2487 break;
2488 case I2O_SCSI_DSC_PATH_INVALID:
2489 case I2O_SCSI_DSC_DEVICE_NOT_PRESENT:
2490 case I2O_SCSI_DSC_SELECTION_TIMEOUT:
2491 case I2O_SCSI_DSC_COMMAND_TIMEOUT:
2492 case I2O_SCSI_DSC_NO_ADAPTER:
2493 case I2O_SCSI_DSC_RESOURCE_UNAVAILABLE:
2494 printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%d) hba status=0x%x, dev status=0x%x, cmd=0x%x\n",
2495 pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]);
2496 cmd->result = (DID_TIME_OUT << 16);
2497 break;
2498 case I2O_SCSI_DSC_ADAPTER_BUSY:
2499 case I2O_SCSI_DSC_BUS_BUSY:
2500 cmd->result = (DID_BUS_BUSY << 16);
2501 break;
2502 case I2O_SCSI_DSC_SCSI_BUS_RESET:
2503 case I2O_SCSI_DSC_BDR_MESSAGE_SENT:
2504 cmd->result = (DID_RESET << 16);
2505 break;
2506 case I2O_SCSI_DSC_PARITY_ERROR_FAILURE:
2507 printk(KERN_WARNING"%s: SCSI CMD parity error\n",pHba->name);
2508 cmd->result = (DID_PARITY << 16);
2509 break;
2510 case I2O_SCSI_DSC_UNABLE_TO_ABORT:
2511 case I2O_SCSI_DSC_COMPLETE_WITH_ERROR:
2512 case I2O_SCSI_DSC_UNABLE_TO_TERMINATE:
2513 case I2O_SCSI_DSC_MR_MESSAGE_RECEIVED:
2514 case I2O_SCSI_DSC_AUTOSENSE_FAILED:
2515 case I2O_SCSI_DSC_DATA_OVERRUN:
2516 case I2O_SCSI_DSC_UNEXPECTED_BUS_FREE:
2517 case I2O_SCSI_DSC_SEQUENCE_FAILURE:
2518 case I2O_SCSI_DSC_REQUEST_LENGTH_ERROR:
2519 case I2O_SCSI_DSC_PROVIDE_FAILURE:
2520 case I2O_SCSI_DSC_REQUEST_TERMINATED:
2521 case I2O_SCSI_DSC_IDE_MESSAGE_SENT:
2522 case I2O_SCSI_DSC_UNACKNOWLEDGED_EVENT:
2523 case I2O_SCSI_DSC_MESSAGE_RECEIVED:
2524 case I2O_SCSI_DSC_INVALID_CDB:
2525 case I2O_SCSI_DSC_LUN_INVALID:
2526 case I2O_SCSI_DSC_SCSI_TID_INVALID:
2527 case I2O_SCSI_DSC_FUNCTION_UNAVAILABLE:
2528 case I2O_SCSI_DSC_NO_NEXUS:
2529 case I2O_SCSI_DSC_CDB_RECEIVED:
2530 case I2O_SCSI_DSC_LUN_ALREADY_ENABLED:
2531 case I2O_SCSI_DSC_QUEUE_FROZEN:
2532 case I2O_SCSI_DSC_REQUEST_INVALID:
2533 default:
2534 printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
2535 pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun,
2536 hba_status, dev_status, cmd->cmnd[0]);
2537 cmd->result = (DID_ERROR << 16);
2538 break;
2539 }
2540
2541 // copy over the request sense data if it was a check
2542 // condition status
Salyzyn, Markd814c512008-01-14 11:04:40 -08002543 if (dev_status == SAM_STAT_CHECK_CONDITION) {
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +09002544 u32 len = min(SCSI_SENSE_BUFFERSIZE, 40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 // Copy over the sense data
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002546 memcpy_fromio(cmd->sense_buffer, (reply+28) , len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 if(cmd->sense_buffer[0] == 0x70 /* class 7 */ &&
2548 cmd->sense_buffer[2] == DATA_PROTECT ){
2549 /* This is to handle an array failed */
2550 cmd->result = (DID_TIME_OUT << 16);
2551 printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",
2552 pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun,
2553 hba_status, dev_status, cmd->cmnd[0]);
2554
2555 }
2556 }
2557 } else {
2558 /* In this condtion we could not talk to the tid
2559 * the card rejected it. We should signal a retry
2560 * for a limitted number of retries.
2561 */
2562 cmd->result = (DID_TIME_OUT << 16);
2563 printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%d) tid=%d, cmd=0x%x\n",
2564 pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun,
2565 ((struct adpt_device*)(cmd->device->hostdata))->tid, cmd->cmnd[0]);
2566 }
2567
2568 cmd->result |= (dev_status);
2569
2570 if(cmd->scsi_done != NULL){
2571 cmd->scsi_done(cmd);
2572 }
2573 return cmd->result;
2574}
2575
2576
2577static s32 adpt_rescan(adpt_hba* pHba)
2578{
2579 s32 rcode;
2580 ulong flags = 0;
2581
2582 if(pHba->host)
2583 spin_lock_irqsave(pHba->host->host_lock, flags);
2584 if ((rcode=adpt_i2o_lct_get(pHba)) < 0)
2585 goto out;
2586 if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0)
2587 goto out;
2588 rcode = 0;
2589out: if(pHba->host)
2590 spin_unlock_irqrestore(pHba->host->host_lock, flags);
2591 return rcode;
2592}
2593
2594
2595static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
2596{
2597 int i;
2598 int max;
2599 int tid;
2600 struct i2o_device *d;
2601 i2o_lct *lct = pHba->lct;
2602 u8 bus_no = 0;
2603 s16 scsi_id;
2604 s16 scsi_lun;
2605 u32 buf[10]; // at least 8 u32's
2606 struct adpt_device* pDev = NULL;
2607 struct i2o_device* pI2o_dev = NULL;
2608
2609 if (lct == NULL) {
2610 printk(KERN_ERR "%s: LCT is empty???\n",pHba->name);
2611 return -1;
2612 }
2613
2614 max = lct->table_size;
2615 max -= 3;
2616 max /= 9;
2617
2618 // Mark each drive as unscanned
2619 for (d = pHba->devices; d; d = d->next) {
2620 pDev =(struct adpt_device*) d->owner;
2621 if(!pDev){
2622 continue;
2623 }
2624 pDev->state |= DPTI_DEV_UNSCANNED;
2625 }
2626
2627 printk(KERN_INFO "%s: LCT has %d entries.\n", pHba->name,max);
2628
2629 for(i=0;i<max;i++) {
2630 if( lct->lct_entry[i].user_tid != 0xfff){
2631 continue;
2632 }
2633
2634 if( lct->lct_entry[i].class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE ||
2635 lct->lct_entry[i].class_id == I2O_CLASS_SCSI_PERIPHERAL ||
2636 lct->lct_entry[i].class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){
2637 tid = lct->lct_entry[i].tid;
2638 if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) {
2639 printk(KERN_ERR"%s: Could not query device\n",pHba->name);
2640 continue;
2641 }
2642 bus_no = buf[0]>>16;
2643 scsi_id = buf[1];
2644 scsi_lun = (buf[2]>>8 )&0xff;
2645 pDev = pHba->channel[bus_no].device[scsi_id];
2646 /* da lun */
2647 while(pDev) {
2648 if(pDev->scsi_lun == scsi_lun) {
2649 break;
2650 }
2651 pDev = pDev->next_lun;
2652 }
2653 if(!pDev ) { // Something new add it
Julia Lawallda2907f2010-05-30 15:49:22 +02002654 d = kmalloc(sizeof(struct i2o_device),
2655 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 if(d==NULL)
2657 {
2658 printk(KERN_CRIT "Out of memory for I2O device data.\n");
2659 return -ENOMEM;
2660 }
2661
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002662 d->controller = pHba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 d->next = NULL;
2664
2665 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
2666
2667 d->flags = 0;
2668 adpt_i2o_report_hba_unit(pHba, d);
2669 adpt_i2o_install_device(pHba, d);
2670
2671 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
2672 printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no);
2673 continue;
2674 }
2675 pDev = pHba->channel[bus_no].device[scsi_id];
2676 if( pDev == NULL){
Julia Lawallda2907f2010-05-30 15:49:22 +02002677 pDev =
2678 kzalloc(sizeof(struct adpt_device),
2679 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 if(pDev == NULL) {
2681 return -ENOMEM;
2682 }
2683 pHba->channel[bus_no].device[scsi_id] = pDev;
2684 } else {
2685 while (pDev->next_lun) {
2686 pDev = pDev->next_lun;
2687 }
Julia Lawallda2907f2010-05-30 15:49:22 +02002688 pDev = pDev->next_lun =
2689 kzalloc(sizeof(struct adpt_device),
2690 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 if(pDev == NULL) {
2692 return -ENOMEM;
2693 }
2694 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 pDev->tid = d->lct_data.tid;
2696 pDev->scsi_channel = bus_no;
2697 pDev->scsi_id = scsi_id;
2698 pDev->scsi_lun = scsi_lun;
2699 pDev->pI2o_dev = d;
2700 d->owner = pDev;
2701 pDev->type = (buf[0])&0xff;
2702 pDev->flags = (buf[0]>>8)&0xff;
2703 // Too late, SCSI system has made up it's mind, but what the hey ...
2704 if(scsi_id > pHba->top_scsi_id){
2705 pHba->top_scsi_id = scsi_id;
2706 }
2707 if(scsi_lun > pHba->top_scsi_lun){
2708 pHba->top_scsi_lun = scsi_lun;
2709 }
2710 continue;
2711 } // end of new i2o device
2712
2713 // We found an old device - check it
2714 while(pDev) {
2715 if(pDev->scsi_lun == scsi_lun) {
2716 if(!scsi_device_online(pDev->pScsi_dev)) {
2717 printk(KERN_WARNING"%s: Setting device (%d,%d,%d) back online\n",
2718 pHba->name,bus_no,scsi_id,scsi_lun);
2719 if (pDev->pScsi_dev) {
2720 scsi_device_set_state(pDev->pScsi_dev, SDEV_RUNNING);
2721 }
2722 }
2723 d = pDev->pI2o_dev;
2724 if(d->lct_data.tid != tid) { // something changed
2725 pDev->tid = tid;
2726 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
2727 if (pDev->pScsi_dev) {
2728 pDev->pScsi_dev->changed = TRUE;
2729 pDev->pScsi_dev->removable = TRUE;
2730 }
2731 }
2732 // Found it - mark it scanned
2733 pDev->state = DPTI_DEV_ONLINE;
2734 break;
2735 }
2736 pDev = pDev->next_lun;
2737 }
2738 }
2739 }
2740 for (pI2o_dev = pHba->devices; pI2o_dev; pI2o_dev = pI2o_dev->next) {
2741 pDev =(struct adpt_device*) pI2o_dev->owner;
2742 if(!pDev){
2743 continue;
2744 }
2745 // Drive offline drives that previously existed but could not be found
2746 // in the LCT table
2747 if (pDev->state & DPTI_DEV_UNSCANNED){
2748 pDev->state = DPTI_DEV_OFFLINE;
2749 printk(KERN_WARNING"%s: Device (%d,%d,%d) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun);
2750 if (pDev->pScsi_dev) {
2751 scsi_device_set_state(pDev->pScsi_dev, SDEV_OFFLINE);
2752 }
2753 }
2754 }
2755 return 0;
2756}
2757
2758static void adpt_fail_posted_scbs(adpt_hba* pHba)
2759{
2760 struct scsi_cmnd* cmd = NULL;
2761 struct scsi_device* d = NULL;
2762
2763 shost_for_each_device(d, pHba->host) {
2764 unsigned long flags;
2765 spin_lock_irqsave(&d->list_lock, flags);
2766 list_for_each_entry(cmd, &d->cmd_list, list) {
2767 if(cmd->serial_number == 0){
2768 continue;
2769 }
2770 cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1);
2771 cmd->scsi_done(cmd);
2772 }
2773 spin_unlock_irqrestore(&d->list_lock, flags);
2774 }
2775}
2776
2777
2778/*============================================================================
2779 * Routines from i2o subsystem
2780 *============================================================================
2781 */
2782
2783
2784
2785/*
2786 * Bring an I2O controller into HOLD state. See the spec.
2787 */
2788static int adpt_i2o_activate_hba(adpt_hba* pHba)
2789{
2790 int rcode;
2791
2792 if(pHba->initialized ) {
2793 if (adpt_i2o_status_get(pHba) < 0) {
2794 if((rcode = adpt_i2o_reset_hba(pHba)) != 0){
2795 printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name);
2796 return rcode;
2797 }
2798 if (adpt_i2o_status_get(pHba) < 0) {
2799 printk(KERN_INFO "HBA not responding.\n");
2800 return -1;
2801 }
2802 }
2803
2804 if(pHba->status_block->iop_state == ADAPTER_STATE_FAULTED) {
2805 printk(KERN_CRIT "%s: hardware fault\n", pHba->name);
2806 return -1;
2807 }
2808
2809 if (pHba->status_block->iop_state == ADAPTER_STATE_READY ||
2810 pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
2811 pHba->status_block->iop_state == ADAPTER_STATE_HOLD ||
2812 pHba->status_block->iop_state == ADAPTER_STATE_FAILED) {
2813 adpt_i2o_reset_hba(pHba);
2814 if (adpt_i2o_status_get(pHba) < 0 || pHba->status_block->iop_state != ADAPTER_STATE_RESET) {
2815 printk(KERN_ERR "%s: Failed to initialize.\n", pHba->name);
2816 return -1;
2817 }
2818 }
2819 } else {
2820 if((rcode = adpt_i2o_reset_hba(pHba)) != 0){
2821 printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name);
2822 return rcode;
2823 }
2824
2825 }
2826
2827 if (adpt_i2o_init_outbound_q(pHba) < 0) {
2828 return -1;
2829 }
2830
2831 /* In HOLD state */
2832
2833 if (adpt_i2o_hrt_get(pHba) < 0) {
2834 return -1;
2835 }
2836
2837 return 0;
2838}
2839
2840/*
2841 * Bring a controller online into OPERATIONAL state.
2842 */
2843
2844static int adpt_i2o_online_hba(adpt_hba* pHba)
2845{
2846 if (adpt_i2o_systab_send(pHba) < 0) {
2847 adpt_i2o_delete_hba(pHba);
2848 return -1;
2849 }
2850 /* In READY state */
2851
2852 if (adpt_i2o_enable_hba(pHba) < 0) {
2853 adpt_i2o_delete_hba(pHba);
2854 return -1;
2855 }
2856
2857 /* In OPERATIONAL state */
2858 return 0;
2859}
2860
2861static s32 adpt_send_nop(adpt_hba*pHba,u32 m)
2862{
2863 u32 __iomem *msg;
2864 ulong timeout = jiffies + 5*HZ;
2865
2866 while(m == EMPTY_QUEUE){
2867 rmb();
2868 m = readl(pHba->post_port);
2869 if(m != EMPTY_QUEUE){
2870 break;
2871 }
2872 if(time_after(jiffies,timeout)){
2873 printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name);
2874 return 2;
2875 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002876 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877 }
2878 msg = (u32 __iomem *)(pHba->msg_addr_virt + m);
2879 writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]);
2880 writel( I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0,&msg[1]);
2881 writel( 0,&msg[2]);
2882 wmb();
2883
2884 writel(m, pHba->post_port);
2885 wmb();
2886 return 0;
2887}
2888
2889static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba)
2890{
2891 u8 *status;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002892 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 u32 __iomem *msg = NULL;
2894 int i;
2895 ulong timeout = jiffies + TMOUT_INITOUTBOUND*HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896 u32 m;
2897
2898 do {
2899 rmb();
2900 m = readl(pHba->post_port);
2901 if (m != EMPTY_QUEUE) {
2902 break;
2903 }
2904
2905 if(time_after(jiffies,timeout)){
2906 printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name);
2907 return -ETIMEDOUT;
2908 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002909 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910 } while(m == EMPTY_QUEUE);
2911
2912 msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
2913
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002914 status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002915 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 adpt_send_nop(pHba, m);
2917 printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n",
2918 pHba->name);
2919 return -ENOMEM;
2920 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002921 memset(status, 0, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922
2923 writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]);
2924 writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]);
2925 writel(0, &msg[2]);
2926 writel(0x0106, &msg[3]); /* Transaction context */
2927 writel(4096, &msg[4]); /* Host page frame size */
2928 writel((REPLY_FRAME_SIZE)<<16|0x80, &msg[5]); /* Outbound msg frame size and Initcode */
2929 writel(0xD0000004, &msg[6]); /* Simple SG LE, EOB */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002930 writel((u32)addr, &msg[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931
2932 writel(m, pHba->post_port);
2933 wmb();
2934
2935 // Wait for the reply status to come back
2936 do {
2937 if (*status) {
2938 if (*status != 0x01 /*I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS*/) {
2939 break;
2940 }
2941 }
2942 rmb();
2943 if(time_after(jiffies,timeout)){
2944 printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002945 /* We lose 4 bytes of "status" here, but we
2946 cannot free these because controller may
2947 awake and corrupt those bytes at any time */
2948 /* dma_free_coherent(&pHba->pDev->dev, 4, status, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 return -ETIMEDOUT;
2950 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002951 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952 } while (1);
2953
2954 // If the command was successful, fill the fifo with our reply
2955 // message packets
2956 if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002957 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958 return -2;
2959 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002960 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002962 if(pHba->reply_pool != NULL) {
2963 dma_free_coherent(&pHba->pDev->dev,
2964 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
2965 pHba->reply_pool, pHba->reply_pool_pa);
2966 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002968 pHba->reply_pool = dma_alloc_coherent(&pHba->pDev->dev,
2969 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
2970 &pHba->reply_pool_pa, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002971 if (!pHba->reply_pool) {
2972 printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name);
2973 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002975 memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 for(i = 0; i < pHba->reply_fifo_size; i++) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002978 writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4),
2979 pHba->reply_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 }
2982 adpt_i2o_status_get(pHba);
2983 return 0;
2984}
2985
2986
2987/*
2988 * I2O System Table. Contains information about
2989 * all the IOPs in the system. Used to inform IOPs
2990 * about each other's existence.
2991 *
2992 * sys_tbl_ver is the CurrentChangeIndicator that is
2993 * used by IOPs to track changes.
2994 */
2995
2996
2997
2998static s32 adpt_i2o_status_get(adpt_hba* pHba)
2999{
3000 ulong timeout;
3001 u32 m;
3002 u32 __iomem *msg;
3003 u8 *status_block=NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004
3005 if(pHba->status_block == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003006 pHba->status_block = dma_alloc_coherent(&pHba->pDev->dev,
3007 sizeof(i2o_status_block),
3008 &pHba->status_block_pa, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 if(pHba->status_block == NULL) {
3010 printk(KERN_ERR
3011 "dpti%d: Get Status Block failed; Out of memory. \n",
3012 pHba->unit);
3013 return -ENOMEM;
3014 }
3015 }
3016 memset(pHba->status_block, 0, sizeof(i2o_status_block));
3017 status_block = (u8*)(pHba->status_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 timeout = jiffies+TMOUT_GETSTATUS*HZ;
3019 do {
3020 rmb();
3021 m = readl(pHba->post_port);
3022 if (m != EMPTY_QUEUE) {
3023 break;
3024 }
3025 if(time_after(jiffies,timeout)){
3026 printk(KERN_ERR "%s: Timeout waiting for message !\n",
3027 pHba->name);
3028 return -ETIMEDOUT;
3029 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08003030 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 } while(m==EMPTY_QUEUE);
3032
3033
3034 msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
3035
3036 writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]);
3037 writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]);
3038 writel(1, &msg[2]);
3039 writel(0, &msg[3]);
3040 writel(0, &msg[4]);
3041 writel(0, &msg[5]);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003042 writel( dma_low(pHba->status_block_pa), &msg[6]);
3043 writel( dma_high(pHba->status_block_pa), &msg[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044 writel(sizeof(i2o_status_block), &msg[8]); // 88 bytes
3045
3046 //post message
3047 writel(m, pHba->post_port);
3048 wmb();
3049
3050 while(status_block[87]!=0xff){
3051 if(time_after(jiffies,timeout)){
3052 printk(KERN_ERR"dpti%d: Get status timeout.\n",
3053 pHba->unit);
3054 return -ETIMEDOUT;
3055 }
3056 rmb();
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08003057 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058 }
3059
3060 // Set up our number of outbound and inbound messages
3061 pHba->post_fifo_size = pHba->status_block->max_inbound_frames;
3062 if (pHba->post_fifo_size > MAX_TO_IOP_MESSAGES) {
3063 pHba->post_fifo_size = MAX_TO_IOP_MESSAGES;
3064 }
3065
3066 pHba->reply_fifo_size = pHba->status_block->max_outbound_frames;
3067 if (pHba->reply_fifo_size > MAX_FROM_IOP_MESSAGES) {
3068 pHba->reply_fifo_size = MAX_FROM_IOP_MESSAGES;
3069 }
3070
3071 // Calculate the Scatter Gather list size
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02003072 if (dpt_dma64(pHba)) {
3073 pHba->sg_tablesize
3074 = ((pHba->status_block->inbound_frame_size * 4
3075 - 14 * sizeof(u32))
3076 / (sizeof(struct sg_simple_element) + sizeof(u32)));
3077 } else {
3078 pHba->sg_tablesize
3079 = ((pHba->status_block->inbound_frame_size * 4
3080 - 12 * sizeof(u32))
3081 / sizeof(struct sg_simple_element));
3082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083 if (pHba->sg_tablesize > SG_LIST_ELEMENTS) {
3084 pHba->sg_tablesize = SG_LIST_ELEMENTS;
3085 }
3086
3087
3088#ifdef DEBUG
3089 printk("dpti%d: State = ",pHba->unit);
3090 switch(pHba->status_block->iop_state) {
3091 case 0x01:
3092 printk("INIT\n");
3093 break;
3094 case 0x02:
3095 printk("RESET\n");
3096 break;
3097 case 0x04:
3098 printk("HOLD\n");
3099 break;
3100 case 0x05:
3101 printk("READY\n");
3102 break;
3103 case 0x08:
3104 printk("OPERATIONAL\n");
3105 break;
3106 case 0x10:
3107 printk("FAILED\n");
3108 break;
3109 case 0x11:
3110 printk("FAULTED\n");
3111 break;
3112 default:
3113 printk("%x (unknown!!)\n",pHba->status_block->iop_state);
3114 }
3115#endif
3116 return 0;
3117}
3118
3119/*
3120 * Get the IOP's Logical Configuration Table
3121 */
3122static int adpt_i2o_lct_get(adpt_hba* pHba)
3123{
3124 u32 msg[8];
3125 int ret;
3126 u32 buf[16];
3127
3128 if ((pHba->lct_size == 0) || (pHba->lct == NULL)){
3129 pHba->lct_size = pHba->status_block->expected_lct_size;
3130 }
3131 do {
3132 if (pHba->lct == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003133 pHba->lct = dma_alloc_coherent(&pHba->pDev->dev,
3134 pHba->lct_size, &pHba->lct_pa,
Julia Lawallda2907f2010-05-30 15:49:22 +02003135 GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 if(pHba->lct == NULL) {
3137 printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n",
3138 pHba->name);
3139 return -ENOMEM;
3140 }
3141 }
3142 memset(pHba->lct, 0, pHba->lct_size);
3143
3144 msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
3145 msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
3146 msg[2] = 0;
3147 msg[3] = 0;
3148 msg[4] = 0xFFFFFFFF; /* All devices */
3149 msg[5] = 0x00000000; /* Report now */
3150 msg[6] = 0xD0000000|pHba->lct_size;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003151 msg[7] = (u32)pHba->lct_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152
3153 if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 360))) {
3154 printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n",
3155 pHba->name, ret);
3156 printk(KERN_ERR"Adaptec: Error Reading Hardware.\n");
3157 return ret;
3158 }
3159
3160 if ((pHba->lct->table_size << 2) > pHba->lct_size) {
3161 pHba->lct_size = pHba->lct->table_size << 2;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003162 dma_free_coherent(&pHba->pDev->dev, pHba->lct_size,
3163 pHba->lct, pHba->lct_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 pHba->lct = NULL;
3165 }
3166 } while (pHba->lct == NULL);
3167
3168 PDEBUG("%s: Hardware resource table read.\n", pHba->name);
3169
3170
3171 // I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO;
3172 if(adpt_i2o_query_scalar(pHba, 0 , 0x8000, -1, buf, sizeof(buf))>=0) {
3173 pHba->FwDebugBufferSize = buf[1];
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02003174 pHba->FwDebugBuffer_P = ioremap(pHba->base_addr_phys + buf[0],
3175 pHba->FwDebugBufferSize);
3176 if (pHba->FwDebugBuffer_P) {
3177 pHba->FwDebugFlags_P = pHba->FwDebugBuffer_P +
3178 FW_DEBUG_FLAGS_OFFSET;
3179 pHba->FwDebugBLEDvalue_P = pHba->FwDebugBuffer_P +
3180 FW_DEBUG_BLED_OFFSET;
3181 pHba->FwDebugBLEDflag_P = pHba->FwDebugBLEDvalue_P + 1;
3182 pHba->FwDebugStrLength_P = pHba->FwDebugBuffer_P +
3183 FW_DEBUG_STR_LENGTH_OFFSET;
3184 pHba->FwDebugBuffer_P += buf[2];
3185 pHba->FwDebugFlags = 0;
3186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 }
3188
3189 return 0;
3190}
3191
3192static int adpt_i2o_build_sys_table(void)
3193{
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003194 adpt_hba* pHba = hba_chain;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195 int count = 0;
3196
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003197 if (sys_tbl)
3198 dma_free_coherent(&pHba->pDev->dev, sys_tbl_len,
3199 sys_tbl, sys_tbl_pa);
3200
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs
3202 (hba_count) * sizeof(struct i2o_sys_tbl_entry);
3203
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003204 sys_tbl = dma_alloc_coherent(&pHba->pDev->dev,
3205 sys_tbl_len, &sys_tbl_pa, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02003206 if (!sys_tbl) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207 printk(KERN_WARNING "SysTab Set failed. Out of memory.\n");
3208 return -ENOMEM;
3209 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003210 memset(sys_tbl, 0, sys_tbl_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211
3212 sys_tbl->num_entries = hba_count;
3213 sys_tbl->version = I2OVERSION;
3214 sys_tbl->change_ind = sys_tbl_ind++;
3215
3216 for(pHba = hba_chain; pHba; pHba = pHba->next) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003217 u64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 // Get updated Status Block so we have the latest information
3219 if (adpt_i2o_status_get(pHba)) {
3220 sys_tbl->num_entries--;
3221 continue; // try next one
3222 }
3223
3224 sys_tbl->iops[count].org_id = pHba->status_block->org_id;
3225 sys_tbl->iops[count].iop_id = pHba->unit + 2;
3226 sys_tbl->iops[count].seg_num = 0;
3227 sys_tbl->iops[count].i2o_version = pHba->status_block->i2o_version;
3228 sys_tbl->iops[count].iop_state = pHba->status_block->iop_state;
3229 sys_tbl->iops[count].msg_type = pHba->status_block->msg_type;
3230 sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size;
3231 sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
3232 sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003233 addr = pHba->base_addr_phys + 0x40;
3234 sys_tbl->iops[count].inbound_low = dma_low(addr);
3235 sys_tbl->iops[count].inbound_high = dma_high(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236
3237 count++;
3238 }
3239
3240#ifdef DEBUG
3241{
3242 u32 *table = (u32*)sys_tbl;
3243 printk(KERN_DEBUG"sys_tbl_len=%d in 32bit words\n",(sys_tbl_len >>2));
3244 for(count = 0; count < (sys_tbl_len >>2); count++) {
3245 printk(KERN_INFO "sys_tbl[%d] = %0#10x\n",
3246 count, table[count]);
3247 }
3248}
3249#endif
3250
3251 return 0;
3252}
3253
3254
3255/*
3256 * Dump the information block associated with a given unit (TID)
3257 */
3258
3259static void adpt_i2o_report_hba_unit(adpt_hba* pHba, struct i2o_device *d)
3260{
3261 char buf[64];
3262 int unit = d->lct_data.tid;
3263
3264 printk(KERN_INFO "TID %3.3d ", unit);
3265
3266 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 3, buf, 16)>=0)
3267 {
3268 buf[16]=0;
3269 printk(" Vendor: %-12.12s", buf);
3270 }
3271 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 4, buf, 16)>=0)
3272 {
3273 buf[16]=0;
3274 printk(" Device: %-12.12s", buf);
3275 }
3276 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 6, buf, 8)>=0)
3277 {
3278 buf[8]=0;
3279 printk(" Rev: %-12.12s\n", buf);
3280 }
3281#ifdef DEBUG
3282 printk(KERN_INFO "\tClass: %.21s\n", adpt_i2o_get_class_name(d->lct_data.class_id));
3283 printk(KERN_INFO "\tSubclass: 0x%04X\n", d->lct_data.sub_class);
3284 printk(KERN_INFO "\tFlags: ");
3285
3286 if(d->lct_data.device_flags&(1<<0))
3287 printk("C"); // ConfigDialog requested
3288 if(d->lct_data.device_flags&(1<<1))
3289 printk("U"); // Multi-user capable
3290 if(!(d->lct_data.device_flags&(1<<4)))
3291 printk("P"); // Peer service enabled!
3292 if(!(d->lct_data.device_flags&(1<<5)))
3293 printk("M"); // Mgmt service enabled!
3294 printk("\n");
3295#endif
3296}
3297
3298#ifdef DEBUG
3299/*
3300 * Do i2o class name lookup
3301 */
3302static const char *adpt_i2o_get_class_name(int class)
3303{
3304 int idx = 16;
3305 static char *i2o_class_name[] = {
3306 "Executive",
3307 "Device Driver Module",
3308 "Block Device",
3309 "Tape Device",
3310 "LAN Interface",
3311 "WAN Interface",
3312 "Fibre Channel Port",
3313 "Fibre Channel Device",
3314 "SCSI Device",
3315 "ATE Port",
3316 "ATE Device",
3317 "Floppy Controller",
3318 "Floppy Device",
3319 "Secondary Bus Port",
3320 "Peer Transport Agent",
3321 "Peer Transport",
3322 "Unknown"
3323 };
3324
3325 switch(class&0xFFF) {
3326 case I2O_CLASS_EXECUTIVE:
3327 idx = 0; break;
3328 case I2O_CLASS_DDM:
3329 idx = 1; break;
3330 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
3331 idx = 2; break;
3332 case I2O_CLASS_SEQUENTIAL_STORAGE:
3333 idx = 3; break;
3334 case I2O_CLASS_LAN:
3335 idx = 4; break;
3336 case I2O_CLASS_WAN:
3337 idx = 5; break;
3338 case I2O_CLASS_FIBRE_CHANNEL_PORT:
3339 idx = 6; break;
3340 case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
3341 idx = 7; break;
3342 case I2O_CLASS_SCSI_PERIPHERAL:
3343 idx = 8; break;
3344 case I2O_CLASS_ATE_PORT:
3345 idx = 9; break;
3346 case I2O_CLASS_ATE_PERIPHERAL:
3347 idx = 10; break;
3348 case I2O_CLASS_FLOPPY_CONTROLLER:
3349 idx = 11; break;
3350 case I2O_CLASS_FLOPPY_DEVICE:
3351 idx = 12; break;
3352 case I2O_CLASS_BUS_ADAPTER_PORT:
3353 idx = 13; break;
3354 case I2O_CLASS_PEER_TRANSPORT_AGENT:
3355 idx = 14; break;
3356 case I2O_CLASS_PEER_TRANSPORT:
3357 idx = 15; break;
3358 }
3359 return i2o_class_name[idx];
3360}
3361#endif
3362
3363
3364static s32 adpt_i2o_hrt_get(adpt_hba* pHba)
3365{
3366 u32 msg[6];
3367 int ret, size = sizeof(i2o_hrt);
3368
3369 do {
3370 if (pHba->hrt == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003371 pHba->hrt = dma_alloc_coherent(&pHba->pDev->dev,
3372 size, &pHba->hrt_pa, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 if (pHba->hrt == NULL) {
3374 printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", pHba->name);
3375 return -ENOMEM;
3376 }
3377 }
3378
3379 msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
3380 msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
3381 msg[2]= 0;
3382 msg[3]= 0;
3383 msg[4]= (0xD0000000 | size); /* Simple transaction */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003384 msg[5]= (u32)pHba->hrt_pa; /* Dump it here */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385
3386 if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg),20))) {
3387 printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n", pHba->name, ret);
3388 return ret;
3389 }
3390
3391 if (pHba->hrt->num_entries * pHba->hrt->entry_len << 2 > size) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003392 int newsize = pHba->hrt->num_entries * pHba->hrt->entry_len << 2;
3393 dma_free_coherent(&pHba->pDev->dev, size,
3394 pHba->hrt, pHba->hrt_pa);
3395 size = newsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396 pHba->hrt = NULL;
3397 }
3398 } while(pHba->hrt == NULL);
3399 return 0;
3400}
3401
3402/*
3403 * Query one scalar group value or a whole scalar group.
3404 */
3405static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid,
3406 int group, int field, void *buf, int buflen)
3407{
3408 u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003409 u8 *opblk_va;
3410 dma_addr_t opblk_pa;
3411 u8 *resblk_va;
3412 dma_addr_t resblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413
3414 int size;
3415
3416 /* 8 bytes for header */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003417 resblk_va = dma_alloc_coherent(&pHba->pDev->dev,
3418 sizeof(u8) * (8 + buflen), &resblk_pa, GFP_KERNEL);
3419 if (resblk_va == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420 printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name);
3421 return -ENOMEM;
3422 }
3423
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003424 opblk_va = dma_alloc_coherent(&pHba->pDev->dev,
3425 sizeof(opblk), &opblk_pa, GFP_KERNEL);
3426 if (opblk_va == NULL) {
3427 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3428 resblk_va, resblk_pa);
3429 printk(KERN_CRIT "%s: query operatio failed; Out of memory.\n",
3430 pHba->name);
3431 return -ENOMEM;
3432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433 if (field == -1) /* whole group */
3434 opblk[4] = -1;
3435
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003436 memcpy(opblk_va, opblk, sizeof(opblk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437 size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid,
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003438 opblk_va, opblk_pa, sizeof(opblk),
3439 resblk_va, resblk_pa, sizeof(u8)*(8+buflen));
3440 dma_free_coherent(&pHba->pDev->dev, sizeof(opblk), opblk_va, opblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 if (size == -ETIME) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003442 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3443 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444 printk(KERN_WARNING "%s: issue params failed; Timed out.\n", pHba->name);
3445 return -ETIME;
3446 } else if (size == -EINTR) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003447 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3448 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 printk(KERN_WARNING "%s: issue params failed; Interrupted.\n", pHba->name);
3450 return -EINTR;
3451 }
3452
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003453 memcpy(buf, resblk_va+8, buflen); /* cut off header */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003455 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3456 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 if (size < 0)
3458 return size;
3459
3460 return buflen;
3461}
3462
3463
3464/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
3465 *
3466 * This function can be used for all UtilParamsGet/Set operations.
3467 * The OperationBlock is given in opblk-buffer,
3468 * and results are returned in resblk-buffer.
3469 * Note that the minimum sized resblk is 8 bytes and contains
3470 * ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
3471 */
3472static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid,
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003473 void *opblk_va, dma_addr_t opblk_pa, int oplen,
3474 void *resblk_va, dma_addr_t resblk_pa, int reslen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475{
3476 u32 msg[9];
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003477 u32 *res = (u32 *)resblk_va;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 int wait_status;
3479
3480 msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
3481 msg[1] = cmd << 24 | HOST_TID << 12 | tid;
3482 msg[2] = 0;
3483 msg[3] = 0;
3484 msg[4] = 0;
3485 msg[5] = 0x54000000 | oplen; /* OperationBlock */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003486 msg[6] = (u32)opblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 msg[7] = 0xD0000000 | reslen; /* ResultBlock */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003488 msg[8] = (u32)resblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489
3490 if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003491 printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk_va);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492 return wait_status; /* -DetailedStatus */
3493 }
3494
3495 if (res[1]&0x00FF0000) { /* BlockStatus != SUCCESS */
3496 printk(KERN_WARNING "%s: %s - Error:\n ErrorInfoSize = 0x%02x, "
3497 "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
3498 pHba->name,
3499 (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"
3500 : "PARAMS_GET",
3501 res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
3502 return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
3503 }
3504
3505 return 4 + ((res[1] & 0x0000FFFF) << 2); /* bytes used in resblk */
3506}
3507
3508
3509static s32 adpt_i2o_quiesce_hba(adpt_hba* pHba)
3510{
3511 u32 msg[4];
3512 int ret;
3513
3514 adpt_i2o_status_get(pHba);
3515
3516 /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */
3517
3518 if((pHba->status_block->iop_state != ADAPTER_STATE_READY) &&
3519 (pHba->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)){
3520 return 0;
3521 }
3522
3523 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
3524 msg[1] = I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
3525 msg[2] = 0;
3526 msg[3] = 0;
3527
3528 if((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) {
3529 printk(KERN_INFO"dpti%d: Unable to quiesce (status=%#x).\n",
3530 pHba->unit, -ret);
3531 } else {
3532 printk(KERN_INFO"dpti%d: Quiesced.\n",pHba->unit);
3533 }
3534
3535 adpt_i2o_status_get(pHba);
3536 return ret;
3537}
3538
3539
3540/*
3541 * Enable IOP. Allows the IOP to resume external operations.
3542 */
3543static int adpt_i2o_enable_hba(adpt_hba* pHba)
3544{
3545 u32 msg[4];
3546 int ret;
3547
3548 adpt_i2o_status_get(pHba);
3549 if(!pHba->status_block){
3550 return -ENOMEM;
3551 }
3552 /* Enable only allowed on READY state */
3553 if(pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)
3554 return 0;
3555
3556 if(pHba->status_block->iop_state != ADAPTER_STATE_READY)
3557 return -EINVAL;
3558
3559 msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
3560 msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
3561 msg[2]= 0;
3562 msg[3]= 0;
3563
3564 if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) {
3565 printk(KERN_WARNING"%s: Could not enable (status=%#10x).\n",
3566 pHba->name, ret);
3567 } else {
3568 PDEBUG("%s: Enabled.\n", pHba->name);
3569 }
3570
3571 adpt_i2o_status_get(pHba);
3572 return ret;
3573}
3574
3575
3576static int adpt_i2o_systab_send(adpt_hba* pHba)
3577{
3578 u32 msg[12];
3579 int ret;
3580
3581 msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
3582 msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
3583 msg[2] = 0;
3584 msg[3] = 0;
3585 msg[4] = (0<<16) | ((pHba->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */
3586 msg[5] = 0; /* Segment 0 */
3587
3588 /*
3589 * Provide three SGL-elements:
3590 * System table (SysTab), Private memory space declaration and
3591 * Private i/o space declaration
3592 */
3593 msg[6] = 0x54000000 | sys_tbl_len;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003594 msg[7] = (u32)sys_tbl_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003595 msg[8] = 0x54000000 | 0;
3596 msg[9] = 0;
3597 msg[10] = 0xD4000000 | 0;
3598 msg[11] = 0;
3599
3600 if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 120))) {
3601 printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n",
3602 pHba->name, ret);
3603 }
3604#ifdef DEBUG
3605 else {
3606 PINFO("%s: SysTab set.\n", pHba->name);
3607 }
3608#endif
3609
3610 return ret;
3611 }
3612
3613
3614/*============================================================================
3615 *
3616 *============================================================================
3617 */
3618
3619
3620#ifdef UARTDELAY
3621
3622static static void adpt_delay(int millisec)
3623{
3624 int i;
3625 for (i = 0; i < millisec; i++) {
3626 udelay(1000); /* delay for one millisecond */
3627 }
3628}
3629
3630#endif
3631
Andrew Morton24601bb2007-12-10 15:49:20 -08003632static struct scsi_host_template driver_template = {
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02003633 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634 .name = "dpt_i2o",
3635 .proc_name = "dpt_i2o",
3636 .proc_info = adpt_proc_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 .info = adpt_info,
3638 .queuecommand = adpt_queue,
3639 .eh_abort_handler = adpt_abort,
3640 .eh_device_reset_handler = adpt_device_reset,
3641 .eh_bus_reset_handler = adpt_bus_reset,
3642 .eh_host_reset_handler = adpt_reset,
3643 .bios_param = adpt_bios_param,
3644 .slave_configure = adpt_slave_configure,
3645 .can_queue = MAX_TO_IOP_MESSAGES,
3646 .this_id = 7,
3647 .cmd_per_lun = 1,
3648 .use_clustering = ENABLE_CLUSTERING,
3649};
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02003650
3651static int __init adpt_init(void)
3652{
3653 int error;
3654 adpt_hba *pHba, *next;
3655
3656 printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n");
3657
3658 error = adpt_detect(&driver_template);
3659 if (error < 0)
3660 return error;
3661 if (hba_chain == NULL)
3662 return -ENODEV;
3663
3664 for (pHba = hba_chain; pHba; pHba = pHba->next) {
3665 error = scsi_add_host(pHba->host, &pHba->pDev->dev);
3666 if (error)
3667 goto fail;
3668 scsi_scan_host(pHba->host);
3669 }
3670 return 0;
3671fail:
3672 for (pHba = hba_chain; pHba; pHba = next) {
3673 next = pHba->next;
3674 scsi_remove_host(pHba->host);
3675 }
3676 return error;
3677}
3678
3679static void __exit adpt_exit(void)
3680{
3681 adpt_hba *pHba, *next;
3682
3683 for (pHba = hba_chain; pHba; pHba = pHba->next)
3684 scsi_remove_host(pHba->host);
3685 for (pHba = hba_chain; pHba; pHba = next) {
3686 next = pHba->next;
3687 adpt_release(pHba->host);
3688 }
3689}
3690
3691module_init(adpt_init);
3692module_exit(adpt_exit);
3693
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694MODULE_LICENSE("GPL");