blob: b0c576f84b2863a0e523f51f743ee402222e8396 [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-Hartmand73a1a672008-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 =
1293 kmalloc(sizeof(struct adpt_i2o_post_wait_data),GFP_KERNEL);
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
Robert P. J. Day5cbded52006-12-13 00:35:56 -08002654 d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 if(d==NULL)
2656 {
2657 printk(KERN_CRIT "Out of memory for I2O device data.\n");
2658 return -ENOMEM;
2659 }
2660
Benoit Boissinot 1c2fb3f2005-04-25 19:46:48 -07002661 d->controller = pHba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 d->next = NULL;
2663
2664 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
2665
2666 d->flags = 0;
2667 adpt_i2o_report_hba_unit(pHba, d);
2668 adpt_i2o_install_device(pHba, d);
2669
2670 if(bus_no >= MAX_CHANNEL) { // Something wrong skip it
2671 printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no);
2672 continue;
2673 }
2674 pDev = pHba->channel[bus_no].device[scsi_id];
2675 if( pDev == NULL){
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05302676 pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 if(pDev == NULL) {
2678 return -ENOMEM;
2679 }
2680 pHba->channel[bus_no].device[scsi_id] = pDev;
2681 } else {
2682 while (pDev->next_lun) {
2683 pDev = pDev->next_lun;
2684 }
vignesh.babu@wipro.comab552202007-04-16 11:35:38 +05302685 pDev = pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 if(pDev == NULL) {
2687 return -ENOMEM;
2688 }
2689 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 pDev->tid = d->lct_data.tid;
2691 pDev->scsi_channel = bus_no;
2692 pDev->scsi_id = scsi_id;
2693 pDev->scsi_lun = scsi_lun;
2694 pDev->pI2o_dev = d;
2695 d->owner = pDev;
2696 pDev->type = (buf[0])&0xff;
2697 pDev->flags = (buf[0]>>8)&0xff;
2698 // Too late, SCSI system has made up it's mind, but what the hey ...
2699 if(scsi_id > pHba->top_scsi_id){
2700 pHba->top_scsi_id = scsi_id;
2701 }
2702 if(scsi_lun > pHba->top_scsi_lun){
2703 pHba->top_scsi_lun = scsi_lun;
2704 }
2705 continue;
2706 } // end of new i2o device
2707
2708 // We found an old device - check it
2709 while(pDev) {
2710 if(pDev->scsi_lun == scsi_lun) {
2711 if(!scsi_device_online(pDev->pScsi_dev)) {
2712 printk(KERN_WARNING"%s: Setting device (%d,%d,%d) back online\n",
2713 pHba->name,bus_no,scsi_id,scsi_lun);
2714 if (pDev->pScsi_dev) {
2715 scsi_device_set_state(pDev->pScsi_dev, SDEV_RUNNING);
2716 }
2717 }
2718 d = pDev->pI2o_dev;
2719 if(d->lct_data.tid != tid) { // something changed
2720 pDev->tid = tid;
2721 memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
2722 if (pDev->pScsi_dev) {
2723 pDev->pScsi_dev->changed = TRUE;
2724 pDev->pScsi_dev->removable = TRUE;
2725 }
2726 }
2727 // Found it - mark it scanned
2728 pDev->state = DPTI_DEV_ONLINE;
2729 break;
2730 }
2731 pDev = pDev->next_lun;
2732 }
2733 }
2734 }
2735 for (pI2o_dev = pHba->devices; pI2o_dev; pI2o_dev = pI2o_dev->next) {
2736 pDev =(struct adpt_device*) pI2o_dev->owner;
2737 if(!pDev){
2738 continue;
2739 }
2740 // Drive offline drives that previously existed but could not be found
2741 // in the LCT table
2742 if (pDev->state & DPTI_DEV_UNSCANNED){
2743 pDev->state = DPTI_DEV_OFFLINE;
2744 printk(KERN_WARNING"%s: Device (%d,%d,%d) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun);
2745 if (pDev->pScsi_dev) {
2746 scsi_device_set_state(pDev->pScsi_dev, SDEV_OFFLINE);
2747 }
2748 }
2749 }
2750 return 0;
2751}
2752
2753static void adpt_fail_posted_scbs(adpt_hba* pHba)
2754{
2755 struct scsi_cmnd* cmd = NULL;
2756 struct scsi_device* d = NULL;
2757
2758 shost_for_each_device(d, pHba->host) {
2759 unsigned long flags;
2760 spin_lock_irqsave(&d->list_lock, flags);
2761 list_for_each_entry(cmd, &d->cmd_list, list) {
2762 if(cmd->serial_number == 0){
2763 continue;
2764 }
2765 cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1);
2766 cmd->scsi_done(cmd);
2767 }
2768 spin_unlock_irqrestore(&d->list_lock, flags);
2769 }
2770}
2771
2772
2773/*============================================================================
2774 * Routines from i2o subsystem
2775 *============================================================================
2776 */
2777
2778
2779
2780/*
2781 * Bring an I2O controller into HOLD state. See the spec.
2782 */
2783static int adpt_i2o_activate_hba(adpt_hba* pHba)
2784{
2785 int rcode;
2786
2787 if(pHba->initialized ) {
2788 if (adpt_i2o_status_get(pHba) < 0) {
2789 if((rcode = adpt_i2o_reset_hba(pHba)) != 0){
2790 printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name);
2791 return rcode;
2792 }
2793 if (adpt_i2o_status_get(pHba) < 0) {
2794 printk(KERN_INFO "HBA not responding.\n");
2795 return -1;
2796 }
2797 }
2798
2799 if(pHba->status_block->iop_state == ADAPTER_STATE_FAULTED) {
2800 printk(KERN_CRIT "%s: hardware fault\n", pHba->name);
2801 return -1;
2802 }
2803
2804 if (pHba->status_block->iop_state == ADAPTER_STATE_READY ||
2805 pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
2806 pHba->status_block->iop_state == ADAPTER_STATE_HOLD ||
2807 pHba->status_block->iop_state == ADAPTER_STATE_FAILED) {
2808 adpt_i2o_reset_hba(pHba);
2809 if (adpt_i2o_status_get(pHba) < 0 || pHba->status_block->iop_state != ADAPTER_STATE_RESET) {
2810 printk(KERN_ERR "%s: Failed to initialize.\n", pHba->name);
2811 return -1;
2812 }
2813 }
2814 } else {
2815 if((rcode = adpt_i2o_reset_hba(pHba)) != 0){
2816 printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name);
2817 return rcode;
2818 }
2819
2820 }
2821
2822 if (adpt_i2o_init_outbound_q(pHba) < 0) {
2823 return -1;
2824 }
2825
2826 /* In HOLD state */
2827
2828 if (adpt_i2o_hrt_get(pHba) < 0) {
2829 return -1;
2830 }
2831
2832 return 0;
2833}
2834
2835/*
2836 * Bring a controller online into OPERATIONAL state.
2837 */
2838
2839static int adpt_i2o_online_hba(adpt_hba* pHba)
2840{
2841 if (adpt_i2o_systab_send(pHba) < 0) {
2842 adpt_i2o_delete_hba(pHba);
2843 return -1;
2844 }
2845 /* In READY state */
2846
2847 if (adpt_i2o_enable_hba(pHba) < 0) {
2848 adpt_i2o_delete_hba(pHba);
2849 return -1;
2850 }
2851
2852 /* In OPERATIONAL state */
2853 return 0;
2854}
2855
2856static s32 adpt_send_nop(adpt_hba*pHba,u32 m)
2857{
2858 u32 __iomem *msg;
2859 ulong timeout = jiffies + 5*HZ;
2860
2861 while(m == EMPTY_QUEUE){
2862 rmb();
2863 m = readl(pHba->post_port);
2864 if(m != EMPTY_QUEUE){
2865 break;
2866 }
2867 if(time_after(jiffies,timeout)){
2868 printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name);
2869 return 2;
2870 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002871 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872 }
2873 msg = (u32 __iomem *)(pHba->msg_addr_virt + m);
2874 writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]);
2875 writel( I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0,&msg[1]);
2876 writel( 0,&msg[2]);
2877 wmb();
2878
2879 writel(m, pHba->post_port);
2880 wmb();
2881 return 0;
2882}
2883
2884static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba)
2885{
2886 u8 *status;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002887 dma_addr_t addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888 u32 __iomem *msg = NULL;
2889 int i;
2890 ulong timeout = jiffies + TMOUT_INITOUTBOUND*HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 u32 m;
2892
2893 do {
2894 rmb();
2895 m = readl(pHba->post_port);
2896 if (m != EMPTY_QUEUE) {
2897 break;
2898 }
2899
2900 if(time_after(jiffies,timeout)){
2901 printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name);
2902 return -ETIMEDOUT;
2903 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002904 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 } while(m == EMPTY_QUEUE);
2906
2907 msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
2908
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002909 status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002910 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911 adpt_send_nop(pHba, m);
2912 printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n",
2913 pHba->name);
2914 return -ENOMEM;
2915 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002916 memset(status, 0, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917
2918 writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]);
2919 writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]);
2920 writel(0, &msg[2]);
2921 writel(0x0106, &msg[3]); /* Transaction context */
2922 writel(4096, &msg[4]); /* Host page frame size */
2923 writel((REPLY_FRAME_SIZE)<<16|0x80, &msg[5]); /* Outbound msg frame size and Initcode */
2924 writel(0xD0000004, &msg[6]); /* Simple SG LE, EOB */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002925 writel((u32)addr, &msg[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926
2927 writel(m, pHba->post_port);
2928 wmb();
2929
2930 // Wait for the reply status to come back
2931 do {
2932 if (*status) {
2933 if (*status != 0x01 /*I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS*/) {
2934 break;
2935 }
2936 }
2937 rmb();
2938 if(time_after(jiffies,timeout)){
2939 printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002940 /* We lose 4 bytes of "status" here, but we
2941 cannot free these because controller may
2942 awake and corrupt those bytes at any time */
2943 /* dma_free_coherent(&pHba->pDev->dev, 4, status, addr); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 return -ETIMEDOUT;
2945 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08002946 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 } while (1);
2948
2949 // If the command was successful, fill the fifo with our reply
2950 // message packets
2951 if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002952 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 return -2;
2954 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002955 dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002957 if(pHba->reply_pool != NULL) {
2958 dma_free_coherent(&pHba->pDev->dev,
2959 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
2960 pHba->reply_pool, pHba->reply_pool_pa);
2961 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002963 pHba->reply_pool = dma_alloc_coherent(&pHba->pDev->dev,
2964 pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
2965 &pHba->reply_pool_pa, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002966 if (!pHba->reply_pool) {
2967 printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name);
2968 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002970 memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972 for(i = 0; i < pHba->reply_fifo_size; i++) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02002973 writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4),
2974 pHba->reply_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 }
2977 adpt_i2o_status_get(pHba);
2978 return 0;
2979}
2980
2981
2982/*
2983 * I2O System Table. Contains information about
2984 * all the IOPs in the system. Used to inform IOPs
2985 * about each other's existence.
2986 *
2987 * sys_tbl_ver is the CurrentChangeIndicator that is
2988 * used by IOPs to track changes.
2989 */
2990
2991
2992
2993static s32 adpt_i2o_status_get(adpt_hba* pHba)
2994{
2995 ulong timeout;
2996 u32 m;
2997 u32 __iomem *msg;
2998 u8 *status_block=NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999
3000 if(pHba->status_block == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003001 pHba->status_block = dma_alloc_coherent(&pHba->pDev->dev,
3002 sizeof(i2o_status_block),
3003 &pHba->status_block_pa, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 if(pHba->status_block == NULL) {
3005 printk(KERN_ERR
3006 "dpti%d: Get Status Block failed; Out of memory. \n",
3007 pHba->unit);
3008 return -ENOMEM;
3009 }
3010 }
3011 memset(pHba->status_block, 0, sizeof(i2o_status_block));
3012 status_block = (u8*)(pHba->status_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 timeout = jiffies+TMOUT_GETSTATUS*HZ;
3014 do {
3015 rmb();
3016 m = readl(pHba->post_port);
3017 if (m != EMPTY_QUEUE) {
3018 break;
3019 }
3020 if(time_after(jiffies,timeout)){
3021 printk(KERN_ERR "%s: Timeout waiting for message !\n",
3022 pHba->name);
3023 return -ETIMEDOUT;
3024 }
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08003025 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 } while(m==EMPTY_QUEUE);
3027
3028
3029 msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
3030
3031 writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]);
3032 writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]);
3033 writel(1, &msg[2]);
3034 writel(0, &msg[3]);
3035 writel(0, &msg[4]);
3036 writel(0, &msg[5]);
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003037 writel( dma_low(pHba->status_block_pa), &msg[6]);
3038 writel( dma_high(pHba->status_block_pa), &msg[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 writel(sizeof(i2o_status_block), &msg[8]); // 88 bytes
3040
3041 //post message
3042 writel(m, pHba->post_port);
3043 wmb();
3044
3045 while(status_block[87]!=0xff){
3046 if(time_after(jiffies,timeout)){
3047 printk(KERN_ERR"dpti%d: Get status timeout.\n",
3048 pHba->unit);
3049 return -ETIMEDOUT;
3050 }
3051 rmb();
Nishanth Aravamudana9a30472005-11-07 01:01:20 -08003052 schedule_timeout_uninterruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 }
3054
3055 // Set up our number of outbound and inbound messages
3056 pHba->post_fifo_size = pHba->status_block->max_inbound_frames;
3057 if (pHba->post_fifo_size > MAX_TO_IOP_MESSAGES) {
3058 pHba->post_fifo_size = MAX_TO_IOP_MESSAGES;
3059 }
3060
3061 pHba->reply_fifo_size = pHba->status_block->max_outbound_frames;
3062 if (pHba->reply_fifo_size > MAX_FROM_IOP_MESSAGES) {
3063 pHba->reply_fifo_size = MAX_FROM_IOP_MESSAGES;
3064 }
3065
3066 // Calculate the Scatter Gather list size
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02003067 if (dpt_dma64(pHba)) {
3068 pHba->sg_tablesize
3069 = ((pHba->status_block->inbound_frame_size * 4
3070 - 14 * sizeof(u32))
3071 / (sizeof(struct sg_simple_element) + sizeof(u32)));
3072 } else {
3073 pHba->sg_tablesize
3074 = ((pHba->status_block->inbound_frame_size * 4
3075 - 12 * sizeof(u32))
3076 / sizeof(struct sg_simple_element));
3077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 if (pHba->sg_tablesize > SG_LIST_ELEMENTS) {
3079 pHba->sg_tablesize = SG_LIST_ELEMENTS;
3080 }
3081
3082
3083#ifdef DEBUG
3084 printk("dpti%d: State = ",pHba->unit);
3085 switch(pHba->status_block->iop_state) {
3086 case 0x01:
3087 printk("INIT\n");
3088 break;
3089 case 0x02:
3090 printk("RESET\n");
3091 break;
3092 case 0x04:
3093 printk("HOLD\n");
3094 break;
3095 case 0x05:
3096 printk("READY\n");
3097 break;
3098 case 0x08:
3099 printk("OPERATIONAL\n");
3100 break;
3101 case 0x10:
3102 printk("FAILED\n");
3103 break;
3104 case 0x11:
3105 printk("FAULTED\n");
3106 break;
3107 default:
3108 printk("%x (unknown!!)\n",pHba->status_block->iop_state);
3109 }
3110#endif
3111 return 0;
3112}
3113
3114/*
3115 * Get the IOP's Logical Configuration Table
3116 */
3117static int adpt_i2o_lct_get(adpt_hba* pHba)
3118{
3119 u32 msg[8];
3120 int ret;
3121 u32 buf[16];
3122
3123 if ((pHba->lct_size == 0) || (pHba->lct == NULL)){
3124 pHba->lct_size = pHba->status_block->expected_lct_size;
3125 }
3126 do {
3127 if (pHba->lct == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003128 pHba->lct = dma_alloc_coherent(&pHba->pDev->dev,
3129 pHba->lct_size, &pHba->lct_pa,
3130 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 if(pHba->lct == NULL) {
3132 printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n",
3133 pHba->name);
3134 return -ENOMEM;
3135 }
3136 }
3137 memset(pHba->lct, 0, pHba->lct_size);
3138
3139 msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
3140 msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
3141 msg[2] = 0;
3142 msg[3] = 0;
3143 msg[4] = 0xFFFFFFFF; /* All devices */
3144 msg[5] = 0x00000000; /* Report now */
3145 msg[6] = 0xD0000000|pHba->lct_size;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003146 msg[7] = (u32)pHba->lct_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147
3148 if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 360))) {
3149 printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n",
3150 pHba->name, ret);
3151 printk(KERN_ERR"Adaptec: Error Reading Hardware.\n");
3152 return ret;
3153 }
3154
3155 if ((pHba->lct->table_size << 2) > pHba->lct_size) {
3156 pHba->lct_size = pHba->lct->table_size << 2;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003157 dma_free_coherent(&pHba->pDev->dev, pHba->lct_size,
3158 pHba->lct, pHba->lct_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 pHba->lct = NULL;
3160 }
3161 } while (pHba->lct == NULL);
3162
3163 PDEBUG("%s: Hardware resource table read.\n", pHba->name);
3164
3165
3166 // I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO;
3167 if(adpt_i2o_query_scalar(pHba, 0 , 0x8000, -1, buf, sizeof(buf))>=0) {
3168 pHba->FwDebugBufferSize = buf[1];
Miquel van Smoorenburg62ac5ae2008-05-02 01:07:27 +02003169 pHba->FwDebugBuffer_P = ioremap(pHba->base_addr_phys + buf[0],
3170 pHba->FwDebugBufferSize);
3171 if (pHba->FwDebugBuffer_P) {
3172 pHba->FwDebugFlags_P = pHba->FwDebugBuffer_P +
3173 FW_DEBUG_FLAGS_OFFSET;
3174 pHba->FwDebugBLEDvalue_P = pHba->FwDebugBuffer_P +
3175 FW_DEBUG_BLED_OFFSET;
3176 pHba->FwDebugBLEDflag_P = pHba->FwDebugBLEDvalue_P + 1;
3177 pHba->FwDebugStrLength_P = pHba->FwDebugBuffer_P +
3178 FW_DEBUG_STR_LENGTH_OFFSET;
3179 pHba->FwDebugBuffer_P += buf[2];
3180 pHba->FwDebugFlags = 0;
3181 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182 }
3183
3184 return 0;
3185}
3186
3187static int adpt_i2o_build_sys_table(void)
3188{
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003189 adpt_hba* pHba = hba_chain;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190 int count = 0;
3191
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003192 if (sys_tbl)
3193 dma_free_coherent(&pHba->pDev->dev, sys_tbl_len,
3194 sys_tbl, sys_tbl_pa);
3195
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196 sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs
3197 (hba_count) * sizeof(struct i2o_sys_tbl_entry);
3198
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003199 sys_tbl = dma_alloc_coherent(&pHba->pDev->dev,
3200 sys_tbl_len, &sys_tbl_pa, GFP_KERNEL);
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02003201 if (!sys_tbl) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202 printk(KERN_WARNING "SysTab Set failed. Out of memory.\n");
3203 return -ENOMEM;
3204 }
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003205 memset(sys_tbl, 0, sys_tbl_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206
3207 sys_tbl->num_entries = hba_count;
3208 sys_tbl->version = I2OVERSION;
3209 sys_tbl->change_ind = sys_tbl_ind++;
3210
3211 for(pHba = hba_chain; pHba; pHba = pHba->next) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003212 u64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213 // Get updated Status Block so we have the latest information
3214 if (adpt_i2o_status_get(pHba)) {
3215 sys_tbl->num_entries--;
3216 continue; // try next one
3217 }
3218
3219 sys_tbl->iops[count].org_id = pHba->status_block->org_id;
3220 sys_tbl->iops[count].iop_id = pHba->unit + 2;
3221 sys_tbl->iops[count].seg_num = 0;
3222 sys_tbl->iops[count].i2o_version = pHba->status_block->i2o_version;
3223 sys_tbl->iops[count].iop_state = pHba->status_block->iop_state;
3224 sys_tbl->iops[count].msg_type = pHba->status_block->msg_type;
3225 sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size;
3226 sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
3227 sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003228 addr = pHba->base_addr_phys + 0x40;
3229 sys_tbl->iops[count].inbound_low = dma_low(addr);
3230 sys_tbl->iops[count].inbound_high = dma_high(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231
3232 count++;
3233 }
3234
3235#ifdef DEBUG
3236{
3237 u32 *table = (u32*)sys_tbl;
3238 printk(KERN_DEBUG"sys_tbl_len=%d in 32bit words\n",(sys_tbl_len >>2));
3239 for(count = 0; count < (sys_tbl_len >>2); count++) {
3240 printk(KERN_INFO "sys_tbl[%d] = %0#10x\n",
3241 count, table[count]);
3242 }
3243}
3244#endif
3245
3246 return 0;
3247}
3248
3249
3250/*
3251 * Dump the information block associated with a given unit (TID)
3252 */
3253
3254static void adpt_i2o_report_hba_unit(adpt_hba* pHba, struct i2o_device *d)
3255{
3256 char buf[64];
3257 int unit = d->lct_data.tid;
3258
3259 printk(KERN_INFO "TID %3.3d ", unit);
3260
3261 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 3, buf, 16)>=0)
3262 {
3263 buf[16]=0;
3264 printk(" Vendor: %-12.12s", buf);
3265 }
3266 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 4, buf, 16)>=0)
3267 {
3268 buf[16]=0;
3269 printk(" Device: %-12.12s", buf);
3270 }
3271 if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 6, buf, 8)>=0)
3272 {
3273 buf[8]=0;
3274 printk(" Rev: %-12.12s\n", buf);
3275 }
3276#ifdef DEBUG
3277 printk(KERN_INFO "\tClass: %.21s\n", adpt_i2o_get_class_name(d->lct_data.class_id));
3278 printk(KERN_INFO "\tSubclass: 0x%04X\n", d->lct_data.sub_class);
3279 printk(KERN_INFO "\tFlags: ");
3280
3281 if(d->lct_data.device_flags&(1<<0))
3282 printk("C"); // ConfigDialog requested
3283 if(d->lct_data.device_flags&(1<<1))
3284 printk("U"); // Multi-user capable
3285 if(!(d->lct_data.device_flags&(1<<4)))
3286 printk("P"); // Peer service enabled!
3287 if(!(d->lct_data.device_flags&(1<<5)))
3288 printk("M"); // Mgmt service enabled!
3289 printk("\n");
3290#endif
3291}
3292
3293#ifdef DEBUG
3294/*
3295 * Do i2o class name lookup
3296 */
3297static const char *adpt_i2o_get_class_name(int class)
3298{
3299 int idx = 16;
3300 static char *i2o_class_name[] = {
3301 "Executive",
3302 "Device Driver Module",
3303 "Block Device",
3304 "Tape Device",
3305 "LAN Interface",
3306 "WAN Interface",
3307 "Fibre Channel Port",
3308 "Fibre Channel Device",
3309 "SCSI Device",
3310 "ATE Port",
3311 "ATE Device",
3312 "Floppy Controller",
3313 "Floppy Device",
3314 "Secondary Bus Port",
3315 "Peer Transport Agent",
3316 "Peer Transport",
3317 "Unknown"
3318 };
3319
3320 switch(class&0xFFF) {
3321 case I2O_CLASS_EXECUTIVE:
3322 idx = 0; break;
3323 case I2O_CLASS_DDM:
3324 idx = 1; break;
3325 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
3326 idx = 2; break;
3327 case I2O_CLASS_SEQUENTIAL_STORAGE:
3328 idx = 3; break;
3329 case I2O_CLASS_LAN:
3330 idx = 4; break;
3331 case I2O_CLASS_WAN:
3332 idx = 5; break;
3333 case I2O_CLASS_FIBRE_CHANNEL_PORT:
3334 idx = 6; break;
3335 case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
3336 idx = 7; break;
3337 case I2O_CLASS_SCSI_PERIPHERAL:
3338 idx = 8; break;
3339 case I2O_CLASS_ATE_PORT:
3340 idx = 9; break;
3341 case I2O_CLASS_ATE_PERIPHERAL:
3342 idx = 10; break;
3343 case I2O_CLASS_FLOPPY_CONTROLLER:
3344 idx = 11; break;
3345 case I2O_CLASS_FLOPPY_DEVICE:
3346 idx = 12; break;
3347 case I2O_CLASS_BUS_ADAPTER_PORT:
3348 idx = 13; break;
3349 case I2O_CLASS_PEER_TRANSPORT_AGENT:
3350 idx = 14; break;
3351 case I2O_CLASS_PEER_TRANSPORT:
3352 idx = 15; break;
3353 }
3354 return i2o_class_name[idx];
3355}
3356#endif
3357
3358
3359static s32 adpt_i2o_hrt_get(adpt_hba* pHba)
3360{
3361 u32 msg[6];
3362 int ret, size = sizeof(i2o_hrt);
3363
3364 do {
3365 if (pHba->hrt == NULL) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003366 pHba->hrt = dma_alloc_coherent(&pHba->pDev->dev,
3367 size, &pHba->hrt_pa, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368 if (pHba->hrt == NULL) {
3369 printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", pHba->name);
3370 return -ENOMEM;
3371 }
3372 }
3373
3374 msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
3375 msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
3376 msg[2]= 0;
3377 msg[3]= 0;
3378 msg[4]= (0xD0000000 | size); /* Simple transaction */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003379 msg[5]= (u32)pHba->hrt_pa; /* Dump it here */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380
3381 if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg),20))) {
3382 printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n", pHba->name, ret);
3383 return ret;
3384 }
3385
3386 if (pHba->hrt->num_entries * pHba->hrt->entry_len << 2 > size) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003387 int newsize = pHba->hrt->num_entries * pHba->hrt->entry_len << 2;
3388 dma_free_coherent(&pHba->pDev->dev, size,
3389 pHba->hrt, pHba->hrt_pa);
3390 size = newsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 pHba->hrt = NULL;
3392 }
3393 } while(pHba->hrt == NULL);
3394 return 0;
3395}
3396
3397/*
3398 * Query one scalar group value or a whole scalar group.
3399 */
3400static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid,
3401 int group, int field, void *buf, int buflen)
3402{
3403 u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003404 u8 *opblk_va;
3405 dma_addr_t opblk_pa;
3406 u8 *resblk_va;
3407 dma_addr_t resblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408
3409 int size;
3410
3411 /* 8 bytes for header */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003412 resblk_va = dma_alloc_coherent(&pHba->pDev->dev,
3413 sizeof(u8) * (8 + buflen), &resblk_pa, GFP_KERNEL);
3414 if (resblk_va == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name);
3416 return -ENOMEM;
3417 }
3418
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003419 opblk_va = dma_alloc_coherent(&pHba->pDev->dev,
3420 sizeof(opblk), &opblk_pa, GFP_KERNEL);
3421 if (opblk_va == NULL) {
3422 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3423 resblk_va, resblk_pa);
3424 printk(KERN_CRIT "%s: query operatio failed; Out of memory.\n",
3425 pHba->name);
3426 return -ENOMEM;
3427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428 if (field == -1) /* whole group */
3429 opblk[4] = -1;
3430
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003431 memcpy(opblk_va, opblk, sizeof(opblk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432 size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid,
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003433 opblk_va, opblk_pa, sizeof(opblk),
3434 resblk_va, resblk_pa, sizeof(u8)*(8+buflen));
3435 dma_free_coherent(&pHba->pDev->dev, sizeof(opblk), opblk_va, opblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436 if (size == -ETIME) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003437 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3438 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439 printk(KERN_WARNING "%s: issue params failed; Timed out.\n", pHba->name);
3440 return -ETIME;
3441 } else if (size == -EINTR) {
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; Interrupted.\n", pHba->name);
3445 return -EINTR;
3446 }
3447
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003448 memcpy(buf, resblk_va+8, buflen); /* cut off header */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003450 dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
3451 resblk_va, resblk_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452 if (size < 0)
3453 return size;
3454
3455 return buflen;
3456}
3457
3458
3459/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
3460 *
3461 * This function can be used for all UtilParamsGet/Set operations.
3462 * The OperationBlock is given in opblk-buffer,
3463 * and results are returned in resblk-buffer.
3464 * Note that the minimum sized resblk is 8 bytes and contains
3465 * ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
3466 */
3467static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid,
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003468 void *opblk_va, dma_addr_t opblk_pa, int oplen,
3469 void *resblk_va, dma_addr_t resblk_pa, int reslen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470{
3471 u32 msg[9];
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003472 u32 *res = (u32 *)resblk_va;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473 int wait_status;
3474
3475 msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
3476 msg[1] = cmd << 24 | HOST_TID << 12 | tid;
3477 msg[2] = 0;
3478 msg[3] = 0;
3479 msg[4] = 0;
3480 msg[5] = 0x54000000 | oplen; /* OperationBlock */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003481 msg[6] = (u32)opblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482 msg[7] = 0xD0000000 | reslen; /* ResultBlock */
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003483 msg[8] = (u32)resblk_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484
3485 if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) {
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003486 printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk_va);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 return wait_status; /* -DetailedStatus */
3488 }
3489
3490 if (res[1]&0x00FF0000) { /* BlockStatus != SUCCESS */
3491 printk(KERN_WARNING "%s: %s - Error:\n ErrorInfoSize = 0x%02x, "
3492 "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
3493 pHba->name,
3494 (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"
3495 : "PARAMS_GET",
3496 res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
3497 return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
3498 }
3499
3500 return 4 + ((res[1] & 0x0000FFFF) << 2); /* bytes used in resblk */
3501}
3502
3503
3504static s32 adpt_i2o_quiesce_hba(adpt_hba* pHba)
3505{
3506 u32 msg[4];
3507 int ret;
3508
3509 adpt_i2o_status_get(pHba);
3510
3511 /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */
3512
3513 if((pHba->status_block->iop_state != ADAPTER_STATE_READY) &&
3514 (pHba->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)){
3515 return 0;
3516 }
3517
3518 msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
3519 msg[1] = I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
3520 msg[2] = 0;
3521 msg[3] = 0;
3522
3523 if((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) {
3524 printk(KERN_INFO"dpti%d: Unable to quiesce (status=%#x).\n",
3525 pHba->unit, -ret);
3526 } else {
3527 printk(KERN_INFO"dpti%d: Quiesced.\n",pHba->unit);
3528 }
3529
3530 adpt_i2o_status_get(pHba);
3531 return ret;
3532}
3533
3534
3535/*
3536 * Enable IOP. Allows the IOP to resume external operations.
3537 */
3538static int adpt_i2o_enable_hba(adpt_hba* pHba)
3539{
3540 u32 msg[4];
3541 int ret;
3542
3543 adpt_i2o_status_get(pHba);
3544 if(!pHba->status_block){
3545 return -ENOMEM;
3546 }
3547 /* Enable only allowed on READY state */
3548 if(pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)
3549 return 0;
3550
3551 if(pHba->status_block->iop_state != ADAPTER_STATE_READY)
3552 return -EINVAL;
3553
3554 msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
3555 msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
3556 msg[2]= 0;
3557 msg[3]= 0;
3558
3559 if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) {
3560 printk(KERN_WARNING"%s: Could not enable (status=%#10x).\n",
3561 pHba->name, ret);
3562 } else {
3563 PDEBUG("%s: Enabled.\n", pHba->name);
3564 }
3565
3566 adpt_i2o_status_get(pHba);
3567 return ret;
3568}
3569
3570
3571static int adpt_i2o_systab_send(adpt_hba* pHba)
3572{
3573 u32 msg[12];
3574 int ret;
3575
3576 msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
3577 msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
3578 msg[2] = 0;
3579 msg[3] = 0;
3580 msg[4] = (0<<16) | ((pHba->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */
3581 msg[5] = 0; /* Segment 0 */
3582
3583 /*
3584 * Provide three SGL-elements:
3585 * System table (SysTab), Private memory space declaration and
3586 * Private i/o space declaration
3587 */
3588 msg[6] = 0x54000000 | sys_tbl_len;
Miquel van Smoorenburg67af2b02008-05-02 01:06:39 +02003589 msg[7] = (u32)sys_tbl_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590 msg[8] = 0x54000000 | 0;
3591 msg[9] = 0;
3592 msg[10] = 0xD4000000 | 0;
3593 msg[11] = 0;
3594
3595 if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 120))) {
3596 printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n",
3597 pHba->name, ret);
3598 }
3599#ifdef DEBUG
3600 else {
3601 PINFO("%s: SysTab set.\n", pHba->name);
3602 }
3603#endif
3604
3605 return ret;
3606 }
3607
3608
3609/*============================================================================
3610 *
3611 *============================================================================
3612 */
3613
3614
3615#ifdef UARTDELAY
3616
3617static static void adpt_delay(int millisec)
3618{
3619 int i;
3620 for (i = 0; i < millisec; i++) {
3621 udelay(1000); /* delay for one millisecond */
3622 }
3623}
3624
3625#endif
3626
Andrew Morton24601bb2007-12-10 15:49:20 -08003627static struct scsi_host_template driver_template = {
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02003628 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 .name = "dpt_i2o",
3630 .proc_name = "dpt_i2o",
3631 .proc_info = adpt_proc_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632 .info = adpt_info,
3633 .queuecommand = adpt_queue,
3634 .eh_abort_handler = adpt_abort,
3635 .eh_device_reset_handler = adpt_device_reset,
3636 .eh_bus_reset_handler = adpt_bus_reset,
3637 .eh_host_reset_handler = adpt_reset,
3638 .bios_param = adpt_bios_param,
3639 .slave_configure = adpt_slave_configure,
3640 .can_queue = MAX_TO_IOP_MESSAGES,
3641 .this_id = 7,
3642 .cmd_per_lun = 1,
3643 .use_clustering = ENABLE_CLUSTERING,
3644};
Miquel van Smoorenburgc864cb12008-05-02 01:05:33 +02003645
3646static int __init adpt_init(void)
3647{
3648 int error;
3649 adpt_hba *pHba, *next;
3650
3651 printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n");
3652
3653 error = adpt_detect(&driver_template);
3654 if (error < 0)
3655 return error;
3656 if (hba_chain == NULL)
3657 return -ENODEV;
3658
3659 for (pHba = hba_chain; pHba; pHba = pHba->next) {
3660 error = scsi_add_host(pHba->host, &pHba->pDev->dev);
3661 if (error)
3662 goto fail;
3663 scsi_scan_host(pHba->host);
3664 }
3665 return 0;
3666fail:
3667 for (pHba = hba_chain; pHba; pHba = next) {
3668 next = pHba->next;
3669 scsi_remove_host(pHba->host);
3670 }
3671 return error;
3672}
3673
3674static void __exit adpt_exit(void)
3675{
3676 adpt_hba *pHba, *next;
3677
3678 for (pHba = hba_chain; pHba; pHba = pHba->next)
3679 scsi_remove_host(pHba->host);
3680 for (pHba = hba_chain; pHba; pHba = next) {
3681 next = pHba->next;
3682 adpt_release(pHba->host);
3683 }
3684}
3685
3686module_init(adpt_init);
3687module_exit(adpt_exit);
3688
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689MODULE_LICENSE("GPL");