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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [fcal.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* fcal.c: Fibre Channel Arbitrated Loop SCSI host adapter driver.
2
 *
3
 * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
4
 *
5
 */
6
 
7
#include <linux/kernel.h>
8
#include <linux/delay.h>
9
#include <linux/types.h>
10
#include <linux/string.h>
11
#include <linux/slab.h>
12
#include <linux/blk.h>
13
#include <linux/proc_fs.h>
14
#include <linux/stat.h>
15
#include <linux/init.h>
16
#include <linux/config.h>
17
#ifdef CONFIG_KMOD
18
#include <linux/kmod.h>
19
#endif
20
 
21
#include <asm/irq.h>
22
 
23
#include "scsi.h"
24
#include "hosts.h"
25
#include "../fc4/fcp_impl.h"
26
#include "fcal.h"
27
 
28
#include <linux/module.h>
29
 
30
/* #define FCAL_DEBUG */
31
 
32
#define fcal_printk printk ("FCAL %s: ", fc->name); printk
33
 
34
#ifdef FCAL_DEBUG
35
#define FCALD(x)  fcal_printk x;
36
#define FCALND(x) printk ("FCAL: "); printk x;
37
#else
38
#define FCALD(x)
39
#define FCALND(x)
40
#endif
41
 
42
static unsigned char alpa2target[] = {
43
0x7e, 0x7d, 0x7c, 0xff, 0x7b, 0xff, 0xff, 0xff, 0x7a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79,
44
0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x77, 0x76, 0xff, 0xff, 0x75, 0xff, 0x74, 0x73, 0x72,
45
0xff, 0xff, 0xff, 0x71, 0xff, 0x70, 0x6f, 0x6e, 0xff, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0xff,
46
0xff, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0xff, 0xff, 0x61, 0x60, 0xff, 0x5f, 0xff, 0xff, 0xff,
47
0xff, 0xff, 0xff, 0x5e, 0xff, 0x5d, 0x5c, 0x5b, 0xff, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0xff,
48
0xff, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0xff, 0xff, 0x4e, 0x4d, 0xff, 0x4c, 0xff, 0xff, 0xff,
49
0xff, 0xff, 0xff, 0x4b, 0xff, 0x4a, 0x49, 0x48, 0xff, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0xff,
50
0xff, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0xff, 0xff, 0x3b, 0x3a, 0xff, 0x39, 0xff, 0xff, 0xff,
51
0x38, 0x37, 0x36, 0xff, 0x35, 0xff, 0xff, 0xff, 0x34, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33,
52
0x32, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0x30, 0xff, 0xff, 0x2f, 0xff, 0x2e, 0x2d, 0x2c,
53
0xff, 0xff, 0xff, 0x2b, 0xff, 0x2a, 0x29, 0x28, 0xff, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0xff,
54
0xff, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0xff, 0xff, 0x1b, 0x1a, 0xff, 0x19, 0xff, 0xff, 0xff,
55
0xff, 0xff, 0xff, 0x18, 0xff, 0x17, 0x16, 0x15, 0xff, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0xff,
56
0xff, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0xff, 0xff, 0x08, 0x07, 0xff, 0x06, 0xff, 0xff, 0xff,
57
0x05, 0x04, 0x03, 0xff, 0x02, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
58
};
59
 
60
static unsigned char target2alpa[] = {
61
0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
62
0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
63
0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
64
0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
65
0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
66
0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
67
0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
68
0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
69
};
70
 
71
static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
72
 
73
static void fcal_select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist)
74
{
75
        Scsi_Device *device;
76
 
77
        for (device = devlist; device; device = device->next) {
78
                if (device->host != host) continue;
79
                if (device->tagged_supported)
80
                        device->queue_depth = /* 254 */ 8;
81
                else
82
                        device->queue_depth = 2;
83
        }
84
}
85
 
86
/* Detect all FC Arbitrated Loops attached to the machine.
87
   fc4 module has done all the work for us... */
88
int __init fcal_detect(Scsi_Host_Template *tpnt)
89
{
90
        int nfcals = 0;
91
        fc_channel *fc;
92
        int fcalcount;
93
        int i;
94
 
95
        tpnt->proc_name = "fcal";
96
        fcalcount = 0;
97
        for_each_online_fc_channel(fc)
98
                if (fc->posmap)
99
                        fcalcount++;
100
        FCALND(("%d channels online\n", fcalcount))
101
        if (!fcalcount) {
102
#if defined(MODULE) && defined(CONFIG_FC4_SOCAL_MODULE) && defined(CONFIG_KMOD)
103
                request_module("socal");
104
 
105
                for_each_online_fc_channel(fc)
106
                        if (fc->posmap)
107
                                fcalcount++;
108
                if (!fcalcount)
109
#endif
110
                        return 0;
111
        }
112
        for_each_online_fc_channel(fc) {
113
                struct Scsi_Host *host;
114
                long *ages;
115
                struct fcal *fcal;
116
 
117
                if (!fc->posmap) continue;
118
 
119
                /* Strange, this is already registered to some other SCSI host, then it cannot be fcal */
120
                if (fc->scsi_name[0]) continue;
121
                memcpy (fc->scsi_name, "FCAL", 4);
122
 
123
                fc->can_queue = FCAL_CAN_QUEUE;
124
                fc->rsp_size = 64;
125
                fc->encode_addr = fcal_encode_addr;
126
 
127
                ages = kmalloc (128 * sizeof(long), GFP_KERNEL);
128
                if (!ages) continue;
129
 
130
                host = scsi_register (tpnt, sizeof (struct fcal));
131
                if (!host)
132
                {
133
                        kfree(ages);
134
                        continue;
135
                }
136
 
137
                nfcals++;
138
 
139
                if (fc->module) __MOD_INC_USE_COUNT(fc->module);
140
 
141
                fcal = (struct fcal *)host->hostdata;
142
 
143
                fc->fcp_register(fc, TYPE_SCSI_FCP, 0);
144
 
145
                for (i = 0; i < fc->posmap->len; i++) {
146
                        int status, target, alpa;
147
 
148
                        alpa = fc->posmap->list[i];
149
                        FCALD(("Sending PLOGI to %02x\n", alpa))
150
                        target = alpa2target[alpa];
151
                        status = fc_do_plogi(fc, alpa, fcal->node_wwn + target,
152
                                             fcal->nport_wwn + target);
153
                        FCALD(("PLOGI returned with status %d\n", status))
154
                        if (status != FC_STATUS_OK)
155
                                continue;
156
                        FCALD(("Sending PRLI to %02x\n", alpa))
157
                        status = fc_do_prli(fc, alpa);
158
                        FCALD(("PRLI returned with status %d\n", status))
159
                        if (status == FC_STATUS_OK)
160
                                fcal->map[target] = 1;
161
                }
162
 
163
                host->max_id = 127;
164
                host->irq = fc->irq;
165
#ifdef __sparc_v9__
166
                host->unchecked_isa_dma = 1;
167
#endif
168
                host->select_queue_depths = fcal_select_queue_depths;
169
 
170
                fc->channels = 1;
171
                fc->targets = 127;
172
                fc->ages = ages;
173
                memset (ages, 0, 128 * sizeof(long));
174
 
175
                fcal->fc = fc;
176
 
177
                FCALD(("Found FCAL\n"))
178
        }
179
        if (nfcals)
180
#ifdef __sparc__
181
                printk ("FCAL: Total of %d Sun Enterprise Network Array (A5000 or EX500) channels found\n", nfcals);
182
#else
183
                printk ("FCAL: Total of %d Fibre Channel Arbitrated Loops found\n", nfcals);
184
#endif
185
        return nfcals;
186
}
187
 
188
int fcal_release(struct Scsi_Host *host)
189
{
190
        struct fcal *fcal = (struct fcal *)host->hostdata;
191
        fc_channel *fc = fcal->fc;
192
 
193
        if (fc->module) __MOD_DEC_USE_COUNT(fc->module);
194
 
195
        fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
196
        FCALND((" releasing fcal.\n"));
197
        kfree (fc->ages);
198
        FCALND(("released fcal!\n"));
199
        return 0;
200
}
201
 
202
#undef SPRINTF
203
#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
204
 
205
int fcal_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout)
206
{
207
        struct Scsi_Host *host = NULL;
208
        struct fcal *fcal;
209
        fc_channel *fc;
210
        char *pos = buffer;
211
        int i, j;
212
 
213
        for (host=scsi_hostlist; host; host=host->next)
214
                if (host->host_no == hostno)
215
                      break;
216
 
217
        if (!host) return -ESRCH;
218
 
219
        if (inout) return length;
220
 
221
        fcal = (struct fcal *)host->hostdata;
222
        fc = fcal->fc;
223
 
224
#ifdef __sparc__
225
        SPRINTF ("Sun Enterprise Network Array (A5000 or E?500) on %s PROM node %x\n", fc->name, fc->dev->prom_node);
226
#else
227
        SPRINTF ("Fibre Channel Arbitrated Loop on %s\n", fc->name);
228
#endif
229
        SPRINTF ("Initiator AL-PA: %02x\n", fc->sid);
230
 
231
        SPRINTF ("\nAttached devices: %s\n", host->host_queue ? "" : "none");
232
 
233
        for (i = 0; i < fc->posmap->len; i++) {
234
                unsigned char alpa = fc->posmap->list[i];
235
                unsigned char target;
236
                u32 *u1, *u2;
237
 
238
                target = alpa2target[alpa];
239
                u1 = (u32 *)&fcal->nport_wwn[target];
240
                u2 = (u32 *)&fcal->node_wwn[target];
241
                if (!u1[0] && !u1[1]) {
242
                        SPRINTF ("  [AL-PA: %02x] Not responded to PLOGI\n", alpa);
243
                } else if (!fcal->map[target]) {
244
                        SPRINTF ("  [AL-PA: %02x, Port WWN: %08x%08x, Node WWN: %08x%08x] Not responded to PRLI\n",
245
                                 alpa, u1[0], u1[1], u2[0], u2[1]);
246
                } else {
247
                        Scsi_Device *scd;
248
                        for (scd = host->host_queue ; scd; scd = scd->next)
249
                                if (scd->host->host_no == hostno && scd->id == target) {
250
                                        SPRINTF ("  [AL-PA: %02x, Id: %02d, Port WWN: %08x%08x, Node WWN: %08x%08x]  ",
251
                                                alpa, target, u1[0], u1[1], u2[0], u2[1]);
252
                                        SPRINTF ("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ?
253
                                                scsi_device_types[(short) scd->type] : "Unknown device");
254
 
255
                                        for (j = 0; (j < 8) && (scd->vendor[j] >= 0x20); j++)
256
                                                SPRINTF ("%c", scd->vendor[j]);
257
                                        SPRINTF (" ");
258
 
259
                                        for (j = 0; (j < 16) && (scd->model[j] >= 0x20); j++)
260
                                                SPRINTF ("%c", scd->model[j]);
261
 
262
                                        SPRINTF ("\n");
263
                                }
264
                }
265
        }
266
        SPRINTF ("\n");
267
 
268
        *start = buffer + offset;
269
 
270
        if ((pos - buffer) < offset)
271
                return 0;
272
        else if (pos - buffer - offset < length)
273
                return pos - buffer - offset;
274
        else
275
                return length;
276
}
277
 
278
/*
279
   For FC-AL, we use a simple addressing: we have just one channel 0,
280
   and all AL-PAs are mapped to targets 0..0x7e
281
 */
282
static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd)
283
{
284
        struct fcal *f;
285
 
286
        /* We don't support LUNs yet - I'm not sure if LUN should be in SCSI fcp_cdb, or in second byte of addr[0] */
287
        if (SCpnt->cmnd[1] & 0xe0) return -EINVAL;
288
        /* FC-PLDA tells us... */
289
        memset(addr, 0, 8);
290
        f = (struct fcal *)SCpnt->host->hostdata;
291
        if (!f->map[SCpnt->target]) return -EINVAL;
292
        /* Now, determine DID: It will be Native Identifier, so we zero upper
293
           2 bytes of the 3 byte DID, lowest byte will be AL-PA */
294
        fcmd->did = target2alpa[SCpnt->target];
295
        FCALD(("trying DID %06x\n", fcmd->did))
296
        return 0;
297
}
298
 
299
static Scsi_Host_Template driver_template = FCAL;
300
 
301
#include "scsi_module.c"
302
 
303
EXPORT_NO_SYMBOLS;

powered by: WebSVN 2.1.0

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