OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [fc4/] [fc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* fc.c: Generic Fibre Channel and FC4 SCSI driver.
2
 *
3
 * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
4
 * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz)
5
 *
6
 * There are two kinds of Fibre Channel adapters used in Linux. Either
7
 * the adapter is "smart" and does all FC bookkeeping by itself and
8
 * just presents a standard SCSI interface to the operating system
9
 * (that's e.g. the case with Qlogic FC cards), or leaves most of the FC
10
 * bookkeeping to the OS (e.g. soc, socal). Drivers for the former adapters
11
 * will look like normal SCSI drivers (with the exception of max_id will be
12
 * usually 127), the latter on the other side allows SCSI, IP over FC and other
13
 * protocols. This driver tree is for the latter adapters.
14
 *
15
 * This file should support both Point-to-Point and Arbitrated Loop topologies.
16
 *
17
 * Sources:
18
 *      Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
19
 *      dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
20
 *      Fibre Channel Arbitrated Loop (FC-AL), Rev. 4.5, 1995
21
 *      Fibre Channel Private Loop SCSI Direct Attach (FC-PLDA), Rev. 2.1, 1997
22
 */
23
 
24
#include <linux/module.h>
25
#include <linux/kernel.h>
26
#include <linux/sched.h>
27
#include <linux/types.h>
28
#include <linux/fcntl.h>
29
#include <linux/interrupt.h>
30
#include <linux/ptrace.h>
31
#include <linux/ioport.h>
32
#include <linux/in.h>
33
#include <linux/slab.h>
34
#include <linux/string.h>
35
#include <linux/init.h>
36
#include <linux/blk.h>
37
 
38
#include <asm/pgtable.h>
39
#include <asm/irq.h>
40
#include <asm/semaphore.h>
41
#include "fcp_impl.h"
42
#include "../scsi/hosts.h"
43
 
44
/* #define FCDEBUG */
45
 
46
#define fc_printk printk ("%s: ", fc->name); printk 
47
 
48
#ifdef FCDEBUG
49
#define FCD(x)  fc_printk x;
50
#define FCND(x) printk ("FC: "); printk x;
51
#else
52
#define FCD(x)
53
#define FCND(x)
54
#endif
55
 
56
#ifdef __sparc__
57
#define dma_alloc_consistent(d,s,p) sbus_alloc_consistent(d,s,p)
58
#define dma_free_consistent(d,s,v,h) sbus_free_consistent(d,s,v,h)
59
#define dma_map_single(d,v,s,dir) sbus_map_single(d,v,s,dir)
60
#define dma_unmap_single(d,h,s,dir) sbus_unmap_single(d,h,s,dir)
61
#define dma_map_sg(d,s,n,dir) sbus_map_sg(d,s,n,dir)
62
#define dma_unmap_sg(d,s,n,dir) sbus_unmap_sg(d,s,n,dir)
63
#define scsi_to_fc_dma_dir(dir) scsi_to_sbus_dma_dir(dir)
64
#define FC_DMA_BIDIRECTIONAL    SBUS_DMA_BIDIRECTIONAL
65
#else
66
#define dma_alloc_consistent(d,s,p) pci_alloc_consistent(d,s,p)
67
#define dma_free_consistent(d,s,v,h) pci_free_consistent(d,s,v,h)
68
#define dma_map_single(d,v,s,dir) pci_map_single(d,v,s,dir)
69
#define dma_unmap_single(d,h,s,dir) pci_unmap_single(d,h,s,dir)
70
#define dma_map_sg(d,s,n,dir) pci_map_sg(d,s,n,dir)
71
#define dma_unmap_sg(d,s,n,dir) pci_unmap_sg(d,s,n,dir)
72
#define scsi_to_fc_dma_dir(dir) scsi_to_pci_dma_dir(dir)
73
#define FC_DMA_BIDIRECTIONAL    PCI_DMA_BIDIRECTIONAL
74
#endif                                                         
75
 
76
#define FCP_CMND(SCpnt) ((fcp_cmnd *)&(SCpnt->SCp))
77
#define FC_SCMND(SCpnt) ((fc_channel *)(SCpnt->host->hostdata[0]))
78
#define SC_FCMND(fcmnd) ((Scsi_Cmnd *)((long)fcmnd - (long)&(((Scsi_Cmnd *)0)->SCp)))
79
 
80
static int fcp_scsi_queue_it(fc_channel *, Scsi_Cmnd *, fcp_cmnd *, int);
81
void fcp_queue_empty(fc_channel *);
82
 
83
static void fcp_scsi_insert_queue (fc_channel *fc, fcp_cmnd *fcmd)
84
{
85
        if (!fc->scsi_que) {
86
                fc->scsi_que = fcmd;
87
                fcmd->next = fcmd;
88
                fcmd->prev = fcmd;
89
        } else {
90
                fc->scsi_que->prev->next = fcmd;
91
                fcmd->prev = fc->scsi_que->prev;
92
                fc->scsi_que->prev = fcmd;
93
                fcmd->next = fc->scsi_que;
94
        }
95
}
96
 
97
static void fcp_scsi_remove_queue (fc_channel *fc, fcp_cmnd *fcmd)
98
{
99
        if (fcmd == fcmd->next) {
100
                fc->scsi_que = NULL;
101
                return;
102
        }
103
        if (fcmd == fc->scsi_que)
104
                fc->scsi_que = fcmd->next;
105
        fcmd->prev->next = fcmd->next;
106
        fcmd->next->prev = fcmd->prev;
107
}
108
 
109
fc_channel *fc_channels = NULL;
110
 
111
#define LSMAGIC 620829043
112
typedef struct {
113
        /* Must be first */
114
        struct semaphore sem;
115
        int magic;
116
        int count;
117
        logi *logi;
118
        fcp_cmnd *fcmds;
119
        atomic_t todo;
120
        struct timer_list timer;
121
        unsigned char grace[0];
122
} ls;
123
 
124
#define LSOMAGIC 654907799
125
typedef struct {
126
        /* Must be first */
127
        struct semaphore sem;
128
        int magic;
129
        int count;
130
        fcp_cmnd *fcmds;
131
        atomic_t todo;
132
        struct timer_list timer;
133
} lso;
134
 
135
#define LSEMAGIC 84482456
136
typedef struct {
137
        /* Must be first */
138
        struct semaphore sem;
139
        int magic;
140
        int status;
141
        struct timer_list timer;
142
} lse;
143
 
144
static void fcp_login_timeout(unsigned long data)
145
{
146
        ls *l = (ls *)data;
147
        FCND(("Login timeout\n"))
148
        up(&l->sem);
149
}
150
 
151
static void fcp_login_done(fc_channel *fc, int i, int status)
152
{
153
        fcp_cmnd *fcmd;
154
        logi *plogi;
155
        fc_hdr *fch;
156
        ls *l = (ls *)fc->ls;
157
 
158
        FCD(("Login done %d %d\n", i, status))
159
        if (i < l->count) {
160
                if (fc->state == FC_STATE_FPORT_OK) {
161
                        FCD(("Additional FPORT_OK received with status %d\n", status))
162
                        return;
163
                }
164
                switch (status) {
165
                case FC_STATUS_OK: /* Oh, we found a fabric */
166
                case FC_STATUS_P_RJT: /* Oh, we haven't found any */
167
                        fc->state = FC_STATE_FPORT_OK;
168
                        fcmd = l->fcmds + i;
169
                        plogi = l->logi + 3 * i;
170
                        dma_unmap_single (fc->dev, fcmd->cmd, 3 * sizeof(logi),
171
                                          FC_DMA_BIDIRECTIONAL);
172
                        plogi->code = LS_PLOGI;
173
                        memcpy (&plogi->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
174
                        memcpy (&plogi->node_wwn, &fc->wwn_node, sizeof(fc_wwn));
175
                        memcpy (&plogi->common, fc->common_svc, sizeof(common_svc_parm));
176
                        memcpy (&plogi->class1, fc->class_svcs, 3*sizeof(svc_parm));
177
                        fch = &fcmd->fch;
178
                        fcmd->token += l->count;
179
                        FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, fc->did);
180
                        FILL_FCHDR_SID(fch, fc->sid);
181
#ifdef FCDEBUG
182
                        {
183
                                int i;
184
                                unsigned *x = (unsigned *)plogi;
185
                                printk ("logi: ");
186
                                for (i = 0; i < 21; i++)
187
                                        printk ("%08x ", x[i]);
188
                                printk ("\n");
189
                        }
190
#endif                  
191
                        fcmd->cmd = dma_map_single (fc->dev, plogi, 3 * sizeof(logi),
192
                                                    FC_DMA_BIDIRECTIONAL);
193
                        fcmd->rsp = fcmd->cmd + 2 * sizeof(logi);
194
                        if (fc->hw_enque (fc, fcmd))
195
                                printk ("FC: Cannot enque PLOGI packet on %s\n", fc->name);
196
                        break;
197
                case FC_STATUS_ERR_OFFLINE:
198
                        fc->state = FC_STATE_MAYBEOFFLINE;
199
                        FCD (("FC is offline %d\n", l->grace[i]))
200
                        break;
201
                default:
202
                        printk ("FLOGI failed for %s with status %d\n", fc->name, status);
203
                        /* Do some sort of error recovery here */
204
                        break;
205
                }
206
        } else {
207
                i -= l->count;
208
                if (fc->state != FC_STATE_FPORT_OK) {
209
                        FCD(("Unexpected N-PORT rsp received"))
210
                        return;
211
                }
212
                switch (status) {
213
                case FC_STATUS_OK:
214
                        plogi = l->logi + 3 * i;
215
                        dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
216
                                          FC_DMA_BIDIRECTIONAL);
217
                        if (!fc->wwn_dest.lo && !fc->wwn_dest.hi) {
218
                                memcpy (&fc->wwn_dest, &plogi[1].node_wwn, sizeof(fc_wwn));
219
                                FCD(("Dest WWN %08x%08x\n", *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo))
220
                        } else if (fc->wwn_dest.lo != plogi[1].node_wwn.lo ||
221
                                   fc->wwn_dest.hi != plogi[1].node_wwn.hi) {
222
                                printk ("%s: mismatch in wwns. Got %08x%08x, expected %08x%08x\n",
223
                                        fc->name,
224
                                        *(u32 *)&plogi[1].node_wwn, plogi[1].node_wwn.lo,
225
                                        *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo);
226
                        }
227
                        fc->state = FC_STATE_ONLINE;
228
                        printk ("%s: ONLINE\n", fc->name);
229
                        if (atomic_dec_and_test (&l->todo))
230
                                up(&l->sem);
231
                        break;
232
                case FC_STATUS_ERR_OFFLINE:
233
                        fc->state = FC_STATE_OFFLINE;
234
                        dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
235
                                          FC_DMA_BIDIRECTIONAL);
236
                        printk ("%s: FC is offline\n", fc->name);
237
                        if (atomic_dec_and_test (&l->todo))
238
                                up(&l->sem);
239
                        break;
240
                default:
241
                        printk ("PLOGI failed for %s with status %d\n", fc->name, status);
242
                        /* Do some sort of error recovery here */
243
                        break;
244
                }
245
        }
246
}
247
 
248
static void fcp_report_map_done(fc_channel *fc, int i, int status)
249
{
250
        fcp_cmnd *fcmd;
251
        fc_hdr *fch;
252
        unsigned char j;
253
        ls *l = (ls *)fc->ls;
254
        fc_al_posmap *p;
255
 
256
        FCD(("Report map done %d %d\n", i, status))
257
        switch (status) {
258
        case FC_STATUS_OK: /* Ok, let's have a fun on a loop */
259
                dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
260
                                  FC_DMA_BIDIRECTIONAL);
261
                p = (fc_al_posmap *)(l->logi + 3 * i);
262
#ifdef FCDEBUG
263
                {
264
                u32 *u = (u32 *)p;
265
                FCD(("%08x\n", u[0]))
266
                u ++;
267
                FCD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
268
                }
269
#endif          
270
                if ((p->magic & 0xffff0000) != FC_AL_LILP || !p->len) {
271
                        printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic);
272
                        fc->state = FC_STATE_OFFLINE;
273
                } else {
274
                        fc->posmap = (fcp_posmap *)kmalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
275
                        if (!fc->posmap) {
276
                                printk("FC: Not enough memory, offlining channel\n");
277
                                fc->state = FC_STATE_OFFLINE;
278
                        } else {
279
                                int k;
280
                                memset(fc->posmap, 0, sizeof(fcp_posmap)+p->len);
281
                                /* FIXME: This is where SOCAL transfers our AL-PA.
282
                                   Keep it here till we found out what other cards do... */
283
                                fc->sid = (p->magic & 0xff);
284
                                for (i = 0; i < p->len; i++)
285
                                        if (p->alpa[i] == fc->sid)
286
                                                break;
287
                                k = p->len;
288
                                if (i == p->len)
289
                                        i = 0;
290
                                else {
291
                                        p->len--;
292
                                        i++;
293
                                }
294
                                fc->posmap->len = p->len;
295
                                for (j = 0; j < p->len; j++) {
296
                                        if (i == k) i = 0;
297
                                        fc->posmap->list[j] = p->alpa[i++];
298
                                }
299
                                fc->state = FC_STATE_ONLINE;
300
                        }
301
                }
302
                printk ("%s: ONLINE\n", fc->name);
303
                if (atomic_dec_and_test (&l->todo))
304
                        up(&l->sem);
305
                break;
306
        case FC_STATUS_POINTTOPOINT: /* We're Point-to-Point, no AL... */
307
                FCD(("SID %d DID %d\n", fc->sid, fc->did))
308
                fcmd = l->fcmds + i;
309
                dma_unmap_single(fc->dev, fcmd->cmd, 3 * sizeof(logi),
310
                                 FC_DMA_BIDIRECTIONAL);
311
                fch = &fcmd->fch;
312
                memset(l->logi + 3 * i, 0, 3 * sizeof(logi));
313
                FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT);
314
                FILL_FCHDR_SID(fch, 0);
315
                FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
316
                FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
317
                FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
318
                fch->param = 0;
319
                l->logi [3 * i].code = LS_FLOGI;
320
                fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi),
321
                                            FC_DMA_BIDIRECTIONAL);
322
                fcmd->rsp = fcmd->cmd + sizeof(logi);
323
                fcmd->cmdlen = sizeof(logi);
324
                fcmd->rsplen = sizeof(logi);
325
                fcmd->data = (dma_addr_t)NULL;
326
                fcmd->class = FC_CLASS_SIMPLE;
327
                fcmd->proto = TYPE_EXTENDED_LS;
328
                if (fc->hw_enque (fc, fcmd))
329
                        printk ("FC: Cannot enque FLOGI packet on %s\n", fc->name);
330
                break;
331
        case FC_STATUS_ERR_OFFLINE:
332
                fc->state = FC_STATE_MAYBEOFFLINE;
333
                FCD (("FC is offline %d\n", l->grace[i]))
334
                break;
335
        default:
336
                printk ("FLOGI failed for %s with status %d\n", fc->name, status);
337
                /* Do some sort of error recovery here */
338
                break;
339
        }
340
}
341
 
342
void fcp_register(fc_channel *fc, u8 type, int unregister)
343
{
344
        int size, i;
345
        int slots = (fc->can_queue * 3) >> 1;
346
 
347
        FCND(("Going to %sregister\n", unregister ? "un" : ""))
348
 
349
        if (type == TYPE_SCSI_FCP) {
350
                if (!unregister) {
351
                        fc->scsi_cmd_pool = (fcp_cmd *)
352
                                dma_alloc_consistent (fc->dev,
353
                                                      slots * (sizeof (fcp_cmd) + fc->rsp_size),
354
                                                      &fc->dma_scsi_cmd);
355
                        fc->scsi_rsp_pool = (char *)(fc->scsi_cmd_pool + slots);
356
                        fc->dma_scsi_rsp = fc->dma_scsi_cmd + slots * sizeof (fcp_cmd);
357
                        fc->scsi_bitmap_end = (slots + 63) & ~63;
358
                        size = fc->scsi_bitmap_end / 8;
359
                        fc->scsi_bitmap = kmalloc (size, GFP_KERNEL);
360
                        memset (fc->scsi_bitmap, 0, size);
361
                        set_bit (0, fc->scsi_bitmap);
362
                        for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++)
363
                                set_bit (i, fc->scsi_bitmap);
364
                        fc->scsi_free = fc->can_queue;
365
                        fc->cmd_slots = (fcp_cmnd **)kmalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
366
                        memset(fc->cmd_slots, 0, slots * sizeof(fcp_cmnd*));
367
                        fc->abort_count = 0;
368
                } else {
369
                        fc->scsi_name[0] = 0;
370
                        kfree (fc->scsi_bitmap);
371
                        kfree (fc->cmd_slots);
372
                        FCND(("Unregistering\n"));
373
                        if (fc->rst_pkt) {
374
                                if (fc->rst_pkt->eh_state == SCSI_STATE_UNUSED)
375
                                        kfree(fc->rst_pkt);
376
                                else {
377
                                        /* Can't happen. Some memory would be lost. */
378
                                        printk("FC: Reset in progress. Now?!");
379
                                }
380
                        }
381
                        FCND(("Unregistered\n"));
382
                }
383
        } else
384
                printk ("FC: %segistering unknown type %02x\n", unregister ? "Unr" : "R", type);
385
}
386
 
387
static void fcp_scsi_done(Scsi_Cmnd *SCpnt);
388
 
389
static inline void fcp_scsi_receive(fc_channel *fc, int token, int status, fc_hdr *fch)
390
{
391
        fcp_cmnd *fcmd;
392
        fcp_rsp  *rsp;
393
        int host_status;
394
        Scsi_Cmnd *SCpnt;
395
        int sense_len;
396
        int rsp_status;
397
 
398
        fcmd = fc->cmd_slots[token];
399
        if (!fcmd) return;
400
        rsp = (fcp_rsp *) (fc->scsi_rsp_pool + fc->rsp_size * token);
401
        SCpnt = SC_FCMND(fcmd);
402
 
403
        if (SCpnt->done != fcp_scsi_done)
404
                return;
405
 
406
        rsp_status = rsp->fcp_status;
407
        FCD(("rsp_status %08x status %08x\n", rsp_status, status))
408
        switch (status) {
409
        case FC_STATUS_OK:
410
                host_status=DID_OK;
411
 
412
                if (rsp_status & FCP_STATUS_RESID) {
413
#ifdef FCDEBUG
414
                        FCD(("Resid %d\n", rsp->fcp_resid))
415
                        {
416
                                fcp_cmd *cmd = fc->scsi_cmd_pool + token;
417
                                int i;
418
 
419
                                printk ("Command ");
420
                                for (i = 0; i < sizeof(fcp_cmd); i+=4)
421
                                        printk ("%08x ", *(u32 *)(((char *)cmd)+i));
422
                                printk ("\nResponse ");
423
                                for (i = 0; i < fc->rsp_size; i+=4)
424
                                        printk ("%08x ", *(u32 *)(((char *)rsp)+i));
425
                                printk ("\n");
426
                        }
427
#endif                  
428
                }
429
 
430
                if (rsp_status & FCP_STATUS_SENSE_LEN) {
431
                        sense_len = rsp->fcp_sense_len;
432
                        if (sense_len > sizeof(SCpnt->sense_buffer)) sense_len = sizeof(SCpnt->sense_buffer);
433
                        memcpy(SCpnt->sense_buffer, ((char *)(rsp+1)), sense_len);
434
                }
435
 
436
                if (fcmd->data) {
437
                        if (SCpnt->use_sg)
438
                                dma_unmap_sg(fc->dev, (struct scatterlist *)SCpnt->buffer, SCpnt->use_sg,
439
                                             scsi_to_fc_dma_dir(SCpnt->sc_data_direction));
440
                        else
441
                                dma_unmap_single(fc->dev, fcmd->data, SCpnt->request_bufflen,
442
                                                 scsi_to_fc_dma_dir(SCpnt->sc_data_direction));
443
                }
444
                break;
445
        default:
446
                host_status=DID_ERROR; /* FIXME */
447
                FCD(("Wrong FC status %d for token %d\n", status, token))
448
                break;
449
        }
450
 
451
        if (status_byte(rsp_status) == QUEUE_FULL) {
452
                printk ("%s: (%d,%d) Received rsp_status 0x%x\n", fc->name, SCpnt->channel, SCpnt->target, rsp_status);
453
        }
454
 
455
        SCpnt->result = (host_status << 16) | (rsp_status & 0xff);
456
#ifdef FCDEBUG  
457
        if (host_status || SCpnt->result || rsp_status) printk("FC: host_status %d, packet status %d\n",
458
                        host_status, SCpnt->result);
459
#endif
460
        SCpnt->done = fcmd->done;
461
        fcmd->done=NULL;
462
        clear_bit(token, fc->scsi_bitmap);
463
        fc->scsi_free++;
464
        FCD(("Calling scsi_done with %08x\n", SCpnt->result))
465
        SCpnt->scsi_done(SCpnt);
466
}
467
 
468
void fcp_receive_solicited(fc_channel *fc, int proto, int token, int status, fc_hdr *fch)
469
{
470
        int magic;
471
        FCD(("receive_solicited %d %d %d\n", proto, token, status))
472
        switch (proto) {
473
        case TYPE_SCSI_FCP:
474
                fcp_scsi_receive(fc, token, status, fch); break;
475
        case TYPE_EXTENDED_LS:
476
        case PROTO_REPORT_AL_MAP:
477
                magic = 0;
478
                if (fc->ls)
479
                        magic = ((ls *)(fc->ls))->magic;
480
                if (magic == LSMAGIC) {
481
                        ls *l = (ls *)fc->ls;
482
                        int i = (token >= l->count) ? token - l->count : token;
483
 
484
                        /* Let's be sure */
485
                        if ((unsigned)i < l->count && l->fcmds[i].fc == fc) {
486
                                if (proto == TYPE_EXTENDED_LS)
487
                                        fcp_login_done(fc, token, status);
488
                                else
489
                                        fcp_report_map_done(fc, token, status);
490
                                break;
491
                        }
492
                }
493
                FCD(("fc %p fc->ls %p fc->cmd_slots %p\n", fc, fc->ls, fc->cmd_slots))
494
                if (proto == TYPE_EXTENDED_LS && !fc->ls && fc->cmd_slots) {
495
                        fcp_cmnd *fcmd;
496
 
497
                        fcmd = fc->cmd_slots[token];
498
                        if (fcmd && fcmd->ls && ((ls *)(fcmd->ls))->magic == LSEMAGIC) {
499
                                lse *l = (lse *)fcmd->ls;
500
 
501
                                l->status = status;
502
                                up (&l->sem);
503
                        }
504
                }
505
                break;
506
        case PROTO_OFFLINE:
507
                if (fc->ls && ((lso *)(fc->ls))->magic == LSOMAGIC) {
508
                        lso *l = (lso *)fc->ls;
509
 
510
                        if ((unsigned)token < l->count && l->fcmds[token].fc == fc) {
511
                                /* Wow, OFFLINE response arrived :) */
512
                                FCD(("OFFLINE Response arrived\n"))
513
                                fc->state = FC_STATE_OFFLINE;
514
                                if (atomic_dec_and_test (&l->todo))
515
                                        up(&l->sem);
516
                        }
517
                }
518
                break;
519
 
520
        default:
521
                break;
522
        }
523
}
524
 
525
void fcp_state_change(fc_channel *fc, int state)
526
{
527
        FCD(("state_change %d %d\n", state, fc->state))
528
        if (state == FC_STATE_ONLINE && fc->state == FC_STATE_MAYBEOFFLINE)
529
                fc->state = FC_STATE_UNINITED;
530
        else if (state == FC_STATE_ONLINE)
531
                printk (KERN_WARNING "%s: state change to ONLINE\n", fc->name);
532
        else
533
                printk (KERN_ERR "%s: state change to OFFLINE\n", fc->name);
534
}
535
 
536
int fcp_initialize(fc_channel *fcchain, int count)
537
{
538
        fc_channel *fc;
539
        fcp_cmnd *fcmd;
540
        int i, retry, ret;
541
        ls *l;
542
 
543
        FCND(("fcp_inititialize %08lx\n", (long)fcp_init))
544
        FCND(("fc_channels %08lx\n", (long)fc_channels))
545
        FCND((" SID %d DID %d\n", fcchain->sid, fcchain->did))
546
        l = kmalloc(sizeof (ls) + count, GFP_KERNEL);
547
        if (!l) {
548
                printk ("FC: Cannot allocate memory for initialization\n");
549
                return -ENOMEM;
550
        }
551
        memset (l, 0, sizeof(ls) + count);
552
        l->magic = LSMAGIC;
553
        l->count = count;
554
        FCND(("FCP Init for %d channels\n", count))
555
        init_MUTEX_LOCKED(&l->sem);
556
        l->timer.function = fcp_login_timeout;
557
        l->timer.data = (unsigned long)l;
558
        atomic_set (&l->todo, count);
559
        l->logi = kmalloc (count * 3 * sizeof(logi), GFP_KERNEL);
560
        l->fcmds = kmalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
561
        if (!l->logi || !l->fcmds) {
562
                if (l->logi) kfree (l->logi);
563
                if (l->fcmds) kfree (l->fcmds);
564
                kfree (l);
565
                printk ("FC: Cannot allocate DMA memory for initialization\n");
566
                return -ENOMEM;
567
        }
568
        memset (l->logi, 0, count * 3 * sizeof(logi));
569
        memset (l->fcmds, 0, count * sizeof(fcp_cmnd));
570
        for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
571
                fc->state = FC_STATE_UNINITED;
572
                fc->rst_pkt = NULL;     /* kmalloc when first used */
573
        }
574
        /* First try if we are in a AL topology */
575
        FCND(("Initializing REPORT_MAP packets\n"))
576
        for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
577
                fcmd = l->fcmds + i;
578
                fc->login = fcmd;
579
                fc->ls = (void *)l;
580
                /* Assumes sizeof(fc_al_posmap) < 3 * sizeof(logi), which is true */
581
                fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi),
582
                                            FC_DMA_BIDIRECTIONAL);
583
                fcmd->proto = PROTO_REPORT_AL_MAP;
584
                fcmd->token = i;
585
                fcmd->fc = fc;
586
        }
587
        for (retry = 0; retry < 8; retry++) {
588
                int nqueued = 0;
589
                FCND(("Sending REPORT_MAP/FLOGI/PLOGI packets\n"))
590
                for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
591
                        if (fc->state == FC_STATE_ONLINE || fc->state == FC_STATE_OFFLINE)
592
                                continue;
593
                        disable_irq(fc->irq);
594
                        if (fc->state == FC_STATE_MAYBEOFFLINE) {
595
                                if (!l->grace[i]) {
596
                                        l->grace[i]++;
597
                                        FCD(("Grace\n"))
598
                                } else {
599
                                        fc->state = FC_STATE_OFFLINE;
600
                                        enable_irq(fc->irq);
601
                                        dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), FC_DMA_BIDIRECTIONAL);
602
                                        if (atomic_dec_and_test (&l->todo))
603
                                                goto all_done;
604
                                }
605
                        }
606
                        ret = fc->hw_enque (fc, fc->login);
607
                        enable_irq(fc->irq);
608
                        if (!ret) {
609
                                nqueued++;
610
                                continue;
611
                        }
612
                        if (ret == -ENOSYS && fc->login->proto == PROTO_REPORT_AL_MAP) {
613
                                /* Oh yes, this card handles Point-to-Point only, so let's try that. */
614
                                fc_hdr *fch;
615
 
616
                                FCD(("SID %d DID %d\n", fc->sid, fc->did))
617
                                fcmd = l->fcmds + i;
618
                                dma_unmap_single(fc->dev, fcmd->cmd, 3 * sizeof(logi), FC_DMA_BIDIRECTIONAL);
619
                                fch = &fcmd->fch;
620
                                FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT);
621
                                FILL_FCHDR_SID(fch, 0);
622
                                FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
623
                                FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
624
                                FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
625
                                fch->param = 0;
626
                                l->logi [3 * i].code = LS_FLOGI;
627
                                fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi), FC_DMA_BIDIRECTIONAL);
628
                                fcmd->rsp = fcmd->cmd + sizeof(logi);
629
                                fcmd->cmdlen = sizeof(logi);
630
                                fcmd->rsplen = sizeof(logi);
631
                                fcmd->data = (dma_addr_t)NULL;
632
                                fcmd->class = FC_CLASS_SIMPLE;
633
                                fcmd->proto = TYPE_EXTENDED_LS;
634
                        } else
635
                                printk ("FC: Cannot enque FLOGI/REPORT_MAP packet on %s\n", fc->name);
636
                }
637
 
638
                if (nqueued) {
639
                        l->timer.expires = jiffies + 5 * HZ;
640
                        add_timer(&l->timer);
641
 
642
                        down(&l->sem);
643
                        if (!atomic_read(&l->todo)) {
644
                                FCND(("All channels answered in time\n"))
645
                                break; /* All fc channels have answered us */
646
                        }
647
                }
648
        }
649
all_done:
650
        for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
651
                fc->ls = NULL;
652
                switch (fc->state) {
653
                case FC_STATE_ONLINE: break;
654
                case FC_STATE_OFFLINE: break;
655
                default: dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), FC_DMA_BIDIRECTIONAL);
656
                        break;
657
                }
658
        }
659
        del_timer(&l->timer);
660
        kfree (l->logi);
661
        kfree (l->fcmds);
662
        kfree (l);
663
        return 0;
664
}
665
 
666
int fcp_forceoffline(fc_channel *fcchain, int count)
667
{
668
        fc_channel *fc;
669
        fcp_cmnd *fcmd;
670
        int i, ret;
671
        lso l;
672
 
673
        memset (&l, 0, sizeof(lso));
674
        l.count = count;
675
        l.magic = LSOMAGIC;
676
        FCND(("FCP Force Offline for %d channels\n", count))
677
        init_MUTEX_LOCKED(&l.sem);
678
        l.timer.function = fcp_login_timeout;
679
        l.timer.data = (unsigned long)&l;
680
        atomic_set (&l.todo, count);
681
        l.fcmds = kmalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
682
        if (!l.fcmds) {
683
                kfree (l.fcmds);
684
                printk ("FC: Cannot allocate memory for forcing offline\n");
685
                return -ENOMEM;
686
        }
687
        memset (l.fcmds, 0, count * sizeof(fcp_cmnd));
688
        FCND(("Initializing OFFLINE packets\n"))
689
        for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
690
                fc->state = FC_STATE_UNINITED;
691
                fcmd = l.fcmds + i;
692
                fc->login = fcmd;
693
                fc->ls = (void *)&l;
694
                fcmd->did = fc->did;
695
                fcmd->class = FC_CLASS_OFFLINE;
696
                fcmd->proto = PROTO_OFFLINE;
697
                fcmd->token = i;
698
                fcmd->fc = fc;
699
                disable_irq(fc->irq);
700
                ret = fc->hw_enque (fc, fc->login);
701
                enable_irq(fc->irq);
702
                if (ret) printk ("FC: Cannot enque OFFLINE packet on %s\n", fc->name);
703
        }
704
 
705
        l.timer.expires = jiffies + 5 * HZ;
706
        add_timer(&l.timer);
707
        down(&l.sem);
708
        del_timer(&l.timer);
709
 
710
        for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++)
711
                fc->ls = NULL;
712
        kfree (l.fcmds);
713
        return 0;
714
}
715
 
716
int fcp_init(fc_channel *fcchain)
717
{
718
        fc_channel *fc;
719
        int count=0;
720
        int ret;
721
 
722
        for (fc = fcchain; fc; fc = fc->next) {
723
                fc->fcp_register = fcp_register;
724
                count++;
725
        }
726
 
727
        ret = fcp_initialize (fcchain, count);
728
        if (ret)
729
                return ret;
730
 
731
        if (!fc_channels)
732
                fc_channels = fcchain;
733
        else {
734
                for (fc = fc_channels; fc->next; fc = fc->next);
735
                fc->next = fcchain;
736
        }
737
        return ret;
738
}
739
 
740
void fcp_release(fc_channel *fcchain, int count)  /* count must > 0 */
741
{
742
        fc_channel *fc;
743
        fc_channel *fcx;
744
 
745
        for (fc = fcchain; --count && fc->next; fc = fc->next);
746
        if (count) {
747
                printk("FC: nothing to release\n");
748
                return;
749
        }
750
 
751
        if (fc_channels == fcchain)
752
                fc_channels = fc->next;
753
        else {
754
                for (fcx = fc_channels; fcx->next != fcchain; fcx = fcx->next);
755
                fcx->next = fc->next;
756
        }
757
        fc->next = NULL;
758
 
759
        /*
760
         *  We've just grabbed fcchain out of the fc_channel list
761
         *  and zero-terminated it, while destroying the count.
762
         *
763
         *  Freeing the fc's is the low level driver's responsibility.
764
         */
765
}
766
 
767
 
768
static void fcp_scsi_done (Scsi_Cmnd *SCpnt)
769
{
770
        if (FCP_CMND(SCpnt)->done)
771
                FCP_CMND(SCpnt)->done(SCpnt);
772
}
773
 
774
static int fcp_scsi_queue_it(fc_channel *fc, Scsi_Cmnd *SCpnt, fcp_cmnd *fcmd, int prepare)
775
{
776
        long i;
777
        fcp_cmd *cmd;
778
        u32 fcp_cntl;
779
        if (prepare) {
780
                i = find_first_zero_bit (fc->scsi_bitmap, fc->scsi_bitmap_end);
781
                set_bit (i, fc->scsi_bitmap);
782
                fcmd->token = i;
783
                cmd = fc->scsi_cmd_pool + i;
784
 
785
                if (fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd)) {
786
                        /* Invalid channel/id/lun and couldn't map it into fcp_addr */
787
                        clear_bit (i, fc->scsi_bitmap);
788
                        SCpnt->result = (DID_BAD_TARGET << 16);
789
                        SCpnt->scsi_done(SCpnt);
790
                        return 0;
791
                }
792
                fc->scsi_free--;
793
                fc->cmd_slots[fcmd->token] = fcmd;
794
 
795
                if (SCpnt->device->tagged_supported) {
796
                        if (jiffies - fc->ages[SCpnt->channel * fc->targets + SCpnt->target] > (5 * 60 * HZ)) {
797
                                fc->ages[SCpnt->channel * fc->targets + SCpnt->target] = jiffies;
798
                                fcp_cntl = FCP_CNTL_QTYPE_ORDERED;
799
                        } else
800
                                fcp_cntl = FCP_CNTL_QTYPE_SIMPLE;
801
                } else
802
                        fcp_cntl = FCP_CNTL_QTYPE_UNTAGGED;
803
                if (!SCpnt->request_bufflen && !SCpnt->use_sg) {
804
                        cmd->fcp_cntl = fcp_cntl;
805
                        fcmd->data = (dma_addr_t)NULL;
806
                } else {
807
                        switch (SCpnt->cmnd[0]) {
808
                        case WRITE_6:
809
                        case WRITE_10:
810
                        case WRITE_12:
811
                                cmd->fcp_cntl = (FCP_CNTL_WRITE | fcp_cntl); break;
812
                        default:
813
                                cmd->fcp_cntl = (FCP_CNTL_READ | fcp_cntl); break;
814
                        }
815
                        if (!SCpnt->use_sg) {
816
                                cmd->fcp_data_len = SCpnt->request_bufflen;
817
                                fcmd->data = dma_map_single (fc->dev, (char *)SCpnt->request_buffer,
818
                                                             SCpnt->request_bufflen,
819
                                                             scsi_to_fc_dma_dir(SCpnt->sc_data_direction));
820
                        } else {
821
                                struct scatterlist *sg = (struct scatterlist *)SCpnt->buffer;
822
                                int nents;
823
 
824
                                FCD(("XXX: Use_sg %d %d\n", SCpnt->use_sg, sg->length))
825
                                nents = dma_map_sg (fc->dev, sg, SCpnt->use_sg,
826
                                                    scsi_to_fc_dma_dir(SCpnt->sc_data_direction));
827
                                if (nents > 1) printk ("%s: SG for nents %d (use_sg %d) not handled yet\n", fc->name, nents, SCpnt->use_sg);
828
                                fcmd->data = sg_dma_address(sg);
829
                                cmd->fcp_data_len = sg_dma_len(sg);
830
                        }
831
                }
832
                memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len);
833
                memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);
834
                FCD(("XXX: %04x.%04x.%04x.%04x - %08x%08x%08x\n", cmd->fcp_addr[0], cmd->fcp_addr[1], cmd->fcp_addr[2], cmd->fcp_addr[3], *(u32 *)SCpnt->cmnd, *(u32 *)(SCpnt->cmnd+4), *(u32 *)(SCpnt->cmnd+8)))
835
        }
836
        FCD(("Trying to enque %p\n", fcmd))
837
        if (!fc->scsi_que) {
838
                if (!fc->hw_enque (fc, fcmd)) {
839
                        FCD(("hw_enque succeeded for %p\n", fcmd))
840
                        return 0;
841
                }
842
        }
843
        FCD(("Putting into que1 %p\n", fcmd))
844
        fcp_scsi_insert_queue (fc, fcmd);
845
        return 0;
846
}
847
 
848
int fcp_scsi_queuecommand(Scsi_Cmnd *SCpnt, void (* done)(Scsi_Cmnd *))
849
{
850
        fcp_cmnd *fcmd = FCP_CMND(SCpnt);
851
        fc_channel *fc = FC_SCMND(SCpnt);
852
 
853
        FCD(("Entering SCSI queuecommand %p\n", fcmd))
854
        if (SCpnt->done != fcp_scsi_done) {
855
                fcmd->done = SCpnt->done;
856
                SCpnt->done = fcp_scsi_done;
857
                SCpnt->scsi_done = done;
858
                fcmd->proto = TYPE_SCSI_FCP;
859
                if (!fc->scsi_free) {
860
                        FCD(("FC: !scsi_free, putting cmd on ML queue\n"))
861
#if (FCP_SCSI_USE_NEW_EH_CODE == 0)
862
                        printk("fcp_scsi_queue_command: queue full, losing cmd, bad\n");
863
#endif
864
                        return 1;
865
                }
866
                return fcp_scsi_queue_it(fc, SCpnt, fcmd, 1);
867
        }
868
        return fcp_scsi_queue_it(fc, SCpnt, fcmd, 0);
869
}
870
 
871
void fcp_queue_empty(fc_channel *fc)
872
{
873
        fcp_cmnd *fcmd;
874
 
875
        FCD(("Queue empty\n"))
876
        while ((fcmd = fc->scsi_que)) {
877
                /* The hw told us we can try again queue some packet */
878
                if (fc->hw_enque (fc, fcmd))
879
                        break;
880
                fcp_scsi_remove_queue (fc, fcmd);
881
        }
882
}
883
 
884
int fcp_old_abort(Scsi_Cmnd *SCpnt)
885
{
886
        printk("FC: Abort not implemented\n");
887
        return 1;
888
}
889
 
890
int fcp_scsi_abort(Scsi_Cmnd *SCpnt)
891
{
892
        /* Internal bookkeeping only. Lose 1 cmd_slots slot. */
893
        fcp_cmnd *fcmd = FCP_CMND(SCpnt);
894
        fc_channel *fc = FC_SCMND(SCpnt);
895
 
896
        /*
897
         * We react to abort requests by simply forgetting
898
         * about the command and pretending everything's sweet.
899
         * This may or may not be silly. We can't, however,
900
         * immediately reuse the command's cmd_slots slot,
901
         * as its result may arrive later and we cannot
902
         * check whether it is the aborted one, can't we?
903
         *
904
         * Therefore, after the first few aborts are done,
905
         * we tell the scsi error handler to do something clever.
906
         * It will eventually call host reset, refreshing
907
         * cmd_slots for us.
908
         *
909
         * There is a theoretical chance that we sometimes allow
910
         * more than can_queue packets to the jungle this way,
911
         * but the worst outcome possible is a series of
912
         * more aborts and eventually the dev_reset catharsis.
913
         */
914
 
915
        if (++fc->abort_count < (fc->can_queue >> 1)) {
916
                SCpnt->result = DID_ABORT;
917
                fcmd->done(SCpnt);
918
                printk("FC: soft abort\n");
919
                return SUCCESS;
920
        } else {
921
                printk("FC: hard abort refused\n");
922
                return FAILED;
923
        }
924
}
925
 
926
void fcp_scsi_reset_done(Scsi_Cmnd *SCpnt)
927
{
928
        fc_channel *fc = FC_SCMND(SCpnt);
929
 
930
        fc->rst_pkt->eh_state = SCSI_STATE_FINISHED;
931
        up(fc->rst_pkt->host->eh_action);
932
}
933
 
934
#define FCP_RESET_TIMEOUT (2*HZ)
935
 
936
int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
937
{
938
        fcp_cmd *cmd;
939
        fcp_cmnd *fcmd;
940
        fc_channel *fc = FC_SCMND(SCpnt);
941
        DECLARE_MUTEX_LOCKED(sem);
942
 
943
        if (!fc->rst_pkt) {
944
                fc->rst_pkt = (Scsi_Cmnd *) kmalloc(sizeof(SCpnt), GFP_KERNEL);
945
                if (!fc->rst_pkt) return FAILED;
946
 
947
                fcmd = FCP_CMND(fc->rst_pkt);
948
 
949
 
950
                fcmd->token = 0;
951
                cmd = fc->scsi_cmd_pool + 0;
952
                FCD(("Preparing rst packet\n"))
953
                fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd);
954
                fc->rst_pkt->channel = SCpnt->channel;
955
                fc->rst_pkt->target = SCpnt->target;
956
                fc->rst_pkt->lun = 0;
957
                fc->rst_pkt->cmd_len = 0;
958
 
959
                fc->cmd_slots[0] = fcmd;
960
 
961
                cmd->fcp_cntl = FCP_CNTL_QTYPE_ORDERED | FCP_CNTL_RESET;
962
                fcmd->data = (dma_addr_t)NULL;
963
                fcmd->proto = TYPE_SCSI_FCP;
964
 
965
                memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len);
966
                memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);
967
                FCD(("XXX: %04x.%04x.%04x.%04x - %08x%08x%08x\n", cmd->fcp_addr[0], cmd->fcp_addr[1], cmd->fcp_addr[2], cmd->fcp_addr[3], *(u32 *)SCpnt->cmnd, *(u32 *)(SCpnt->cmnd+4), *(u32 *)(SCpnt->cmnd+8)))
968
        } else {
969
                fcmd = FCP_CMND(fc->rst_pkt);
970
                if (fc->rst_pkt->eh_state == SCSI_STATE_QUEUED)
971
                        return FAILED; /* or SUCCESS. Only these */
972
        }
973
        fc->rst_pkt->done = NULL;
974
 
975
 
976
        fc->rst_pkt->eh_state = SCSI_STATE_QUEUED;
977
 
978
        fc->rst_pkt->eh_timeout.data = (unsigned long) fc->rst_pkt;
979
        fc->rst_pkt->eh_timeout.expires = jiffies + FCP_RESET_TIMEOUT;
980
        fc->rst_pkt->eh_timeout.function = (void (*)(unsigned long))fcp_scsi_reset_done;
981
 
982
        add_timer(&fc->rst_pkt->eh_timeout);
983
 
984
        /*
985
         * Set up the semaphore so we wait for the command to complete.
986
         */
987
 
988
        fc->rst_pkt->host->eh_action = &sem;
989
        fc->rst_pkt->request.rq_status = RQ_SCSI_BUSY;
990
 
991
        fc->rst_pkt->done = fcp_scsi_reset_done;
992
        fcp_scsi_queue_it(fc, fc->rst_pkt, fcmd, 0);
993
 
994
        down(&sem);
995
 
996
        fc->rst_pkt->host->eh_action = NULL;
997
        del_timer(&fc->rst_pkt->eh_timeout);
998
 
999
        /*
1000
         * See if timeout.  If so, tell the host to forget about it.
1001
         * In other words, we don't want a callback any more.
1002
         */
1003
        if (fc->rst_pkt->eh_state == SCSI_STATE_TIMEOUT ) {
1004
                fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
1005
                return FAILED;
1006
        }
1007
        fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
1008
        return SUCCESS;
1009
}
1010
 
1011
int fcp_scsi_bus_reset(Scsi_Cmnd *SCpnt)
1012
{
1013
        printk ("FC: bus reset!\n");
1014
        return FAILED;
1015
}
1016
 
1017
int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
1018
{
1019
        fc_channel *fc = FC_SCMND(SCpnt);
1020
        fcp_cmnd *fcmd = FCP_CMND(SCpnt);
1021
        int i;
1022
 
1023
        printk ("FC: host reset\n");
1024
 
1025
        for (i=0; i < fc->can_queue; i++) {
1026
                if (fc->cmd_slots[i] && SCpnt->result != DID_ABORT) {
1027
                        SCpnt->result = DID_RESET;
1028
                        fcmd->done(SCpnt);
1029
                        fc->cmd_slots[i] = NULL;
1030
                }
1031
        }
1032
        fc->reset(fc);
1033
        fc->abort_count = 0;
1034
        if (fcp_initialize(fc, 1)) return SUCCESS;
1035
        else return FAILED;
1036
}
1037
 
1038
static int fcp_els_queue_it(fc_channel *fc, fcp_cmnd *fcmd)
1039
{
1040
        long i;
1041
 
1042
        i = find_first_zero_bit (fc->scsi_bitmap, fc->scsi_bitmap_end);
1043
        set_bit (i, fc->scsi_bitmap);
1044
        fcmd->token = i;
1045
        fc->scsi_free--;
1046
        fc->cmd_slots[fcmd->token] = fcmd;
1047
        return fcp_scsi_queue_it(fc, NULL, fcmd, 0);
1048
}
1049
 
1050
static int fc_do_els(fc_channel *fc, unsigned int alpa, void *data, int len)
1051
{
1052
        fcp_cmnd _fcmd, *fcmd;
1053
        fc_hdr *fch;
1054
        lse l;
1055
        int i;
1056
 
1057
        fcmd = &_fcmd;
1058
        memset(fcmd, 0, sizeof(fcmd));
1059
        FCD(("PLOGI SID %d DID %d\n", fc->sid, alpa))
1060
        fch = &fcmd->fch;
1061
        FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, alpa);
1062
        FILL_FCHDR_SID(fch, fc->sid);
1063
        FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
1064
        FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
1065
        FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
1066
        fch->param = 0;
1067
        fcmd->cmd = dma_map_single (fc->dev, data, 2 * len, FC_DMA_BIDIRECTIONAL);
1068
        fcmd->rsp = fcmd->cmd + len;
1069
        fcmd->cmdlen = len;
1070
        fcmd->rsplen = len;
1071
        fcmd->data = (dma_addr_t)NULL;
1072
        fcmd->fc = fc;
1073
        fcmd->class = FC_CLASS_SIMPLE;
1074
        fcmd->proto = TYPE_EXTENDED_LS;
1075
 
1076
        memset (&l, 0, sizeof(lse));
1077
        l.magic = LSEMAGIC;
1078
        init_MUTEX_LOCKED(&l.sem);
1079
        l.timer.function = fcp_login_timeout;
1080
        l.timer.data = (unsigned long)&l;
1081
        l.status = FC_STATUS_TIMED_OUT;
1082
        fcmd->ls = (void *)&l;
1083
 
1084
        disable_irq(fc->irq);
1085
        fcp_els_queue_it(fc, fcmd);
1086
        enable_irq(fc->irq);
1087
 
1088
        for (i = 0;;) {
1089
                l.timer.expires = jiffies + 5 * HZ;
1090
                add_timer(&l.timer);
1091
                down(&l.sem);
1092
                del_timer(&l.timer);
1093
                if (l.status != FC_STATUS_TIMED_OUT) break;
1094
                if (++i == 3) break;
1095
                disable_irq(fc->irq);
1096
                fcp_scsi_queue_it(fc, NULL, fcmd, 0);
1097
                enable_irq(fc->irq);
1098
        }
1099
 
1100
        clear_bit(fcmd->token, fc->scsi_bitmap);
1101
        fc->scsi_free++;
1102
        dma_unmap_single (fc->dev, fcmd->cmd, 2 * len, FC_DMA_BIDIRECTIONAL);
1103
        return l.status;
1104
}
1105
 
1106
int fc_do_plogi(fc_channel *fc, unsigned char alpa, fc_wwn *node, fc_wwn *nport)
1107
{
1108
        logi *l;
1109
        int status;
1110
 
1111
        l = (logi *)kmalloc(2 * sizeof(logi), GFP_KERNEL);
1112
        if (!l) return -ENOMEM;
1113
        memset(l, 0, 2 * sizeof(logi));
1114
        l->code = LS_PLOGI;
1115
        memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
1116
        memcpy (&l->node_wwn, &fc->wwn_node, sizeof(fc_wwn));
1117
        memcpy (&l->common, fc->common_svc, sizeof(common_svc_parm));
1118
        memcpy (&l->class1, fc->class_svcs, 3*sizeof(svc_parm));
1119
        status = fc_do_els(fc, alpa, l, sizeof(logi));
1120
        if (status == FC_STATUS_OK) {
1121
                if (l[1].code == LS_ACC) {
1122
#ifdef FCDEBUG
1123
                        u32 *u = (u32 *)&l[1].nport_wwn;
1124
                        FCD(("AL-PA %02x: Port WWN %08x%08x Node WWN %08x%08x\n", alpa,
1125
                                u[0], u[1], u[2], u[3]))
1126
#endif
1127
                        memcpy(nport, &l[1].nport_wwn, sizeof(fc_wwn));
1128
                        memcpy(node, &l[1].node_wwn, sizeof(fc_wwn));
1129
                } else
1130
                        status = FC_STATUS_BAD_RSP;
1131
        }
1132
        kfree(l);
1133
        return status;
1134
}
1135
 
1136
typedef struct {
1137
        unsigned int code;
1138
        unsigned params[4];
1139
} prli;
1140
 
1141
int fc_do_prli(fc_channel *fc, unsigned char alpa)
1142
{
1143
        prli *p;
1144
        int status;
1145
 
1146
        p = (prli *)kmalloc(2 * sizeof(prli), GFP_KERNEL);
1147
        if (!p) return -ENOMEM;
1148
        memset(p, 0, 2 * sizeof(prli));
1149
        p->code = LS_PRLI;
1150
        p->params[0] = 0x08002000;
1151
        p->params[3] = 0x00000022;
1152
        status = fc_do_els(fc, alpa, p, sizeof(prli));
1153
        if (status == FC_STATUS_OK && p[1].code != LS_PRLI_ACC && p[1].code != LS_ACC)
1154
                status = FC_STATUS_BAD_RSP;
1155
        kfree(p);
1156
        return status;
1157
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.