Commit 1ecd3902c6e16c2445165b872c49e73770b72da7

Authored by Matthew Wilcox
Committed by James Bottomley
1 parent d85714d81c

[SCSI] fc4: remove this and all associated drivers

This code has been slowly rotting for about eight years.  It's currently
impeding a few SCSI cleanups, and nobody seems to have hardware to test
it any more.  I talked to Dave Miller about it, and he agrees we can
delete it.  If anyone wants a software FC stack in future, they can
retrieve this driver from git.

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>

Showing 19 changed files with 0 additions and 4809 deletions Side-by-side Diff

arch/sparc64/Kconfig
... ... @@ -456,8 +456,6 @@
456 456  
457 457 source "drivers/sbus/char/Kconfig"
458 458  
459   -source "drivers/fc4/Kconfig"
460   -
461 459 source "fs/Kconfig"
462 460  
463 461 menu "Instrumentation Support"
... ... @@ -34,7 +34,6 @@
34 34 obj-$(CONFIG_ATM) += atm/
35 35 obj-y += macintosh/
36 36 obj-$(CONFIG_IDE) += ide/
37   -obj-$(CONFIG_FC4) += fc4/
38 37 obj-$(CONFIG_SCSI) += scsi/
39 38 obj-$(CONFIG_ATA) += ata/
40 39 obj-$(CONFIG_FUSION) += message/
drivers/fc4/Kconfig
1   -#
2   -# FC4 device configuration
3   -#
4   -
5   -menu "Fibre Channel support"
6   -
7   -config FC4
8   - tristate "Fibre Channel and FC4 SCSI support"
9   - ---help---
10   - Fibre Channel is a high speed serial protocol mainly used to
11   - connect large storage devices to the computer; it is compatible with
12   - and intended to replace SCSI.
13   -
14   - This is an experimental support for storage arrays connected to your
15   - computer using optical fibre cables and the "X3.269-199X Fibre
16   - Channel Protocol for SCSI" specification. If you want to use this,
17   - you need to say Y here and to "SCSI support" as well as to the
18   - drivers for the storage array itself and for the interface adapter
19   - such as SOC or SOC+. This subsystem could even serve for IP
20   - networking, with some code extensions.
21   -
22   - If unsure, say N.
23   -
24   -comment "FC4 drivers"
25   - depends on FC4
26   -
27   -config FC4_SOC
28   - tristate "Sun SOC/Sbus"
29   - depends on FC4!=n && SPARC
30   - help
31   - Serial Optical Channel is an interface card with one or two Fibre
32   - Optic ports, each of which can be connected to a disk array. Note
33   - that if you have older firmware in the card, you'll need the
34   - microcode from the Solaris driver to make it work.
35   -
36   - To compile this support as a module, choose M here: the module will
37   - be called soc.
38   -
39   -config FC4_SOCAL
40   - tristate "Sun SOC+ (aka SOCAL)"
41   - depends on FC4!=n && SPARC
42   - ---help---
43   - Serial Optical Channel Plus is an interface card with up to two
44   - Fibre Optic ports. This card supports FC Arbitrated Loop (usually
45   - A5000 or internal FC disks in E[3-6]000 machines through the
46   - Interface Board). You'll probably need the microcode from the
47   - Solaris driver to make it work.
48   -
49   - To compile this support as a module, choose M here: the module will
50   - be called socal.
51   -
52   -comment "FC4 targets"
53   - depends on FC4
54   -
55   -config SCSI_PLUTO
56   - tristate "SparcSTORAGE Array 100 and 200 series"
57   - depends on FC4!=n && SCSI
58   - help
59   - If you never bought a disk array made by Sun, go with N.
60   -
61   - To compile this support as a module, choose M here: the module will
62   - be called pluto.
63   -
64   -config SCSI_FCAL
65   - tristate "Sun Enterprise Network Array (A5000 and EX500)" if SPARC
66   - depends on FC4!=n && SCSI
67   - help
68   - This driver drives FC-AL disks connected through a Fibre Channel
69   - card using the drivers/fc4 layer (currently only SOCAL). The most
70   - common is either A5000 array or internal disks in E[3-6]000
71   - machines.
72   -
73   - To compile this support as a module, choose M here: the module will
74   - be called fcal.
75   -
76   -config SCSI_FCAL
77   - prompt "Generic FC-AL disk driver"
78   - depends on FC4!=n && SCSI && !SPARC
79   -
80   -endmenu
drivers/fc4/Makefile
1   -#
2   -# Makefile for the Linux Fibre Channel device drivers.
3   -#
4   -
5   -fc4-objs := fc.o fc_syms.o
6   -
7   -obj-$(CONFIG_FC4) += fc4.o
8   -obj-$(CONFIG_FC4_SOC) += soc.o
9   -obj-$(CONFIG_FC4_SOCAL) += socal.o
drivers/fc4/fc-al.h
1   -/* fc-al.h: Definitions for Fibre Channel Arbitrated Loop topology.
2   - *
3   - * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
4   - *
5   - * Sources:
6   - * Fibre Channel Arbitrated Loop (FC-AL), ANSI, Rev. 4.5, 1995
7   - */
8   -
9   -#ifndef __FC_AL_H
10   -#define __FC_AL_H
11   -
12   -/* Loop initialization payloads */
13   -#define FC_AL_LISM 0x11010000 /* Select Master, 12B payload */
14   -#define FC_AL_LIFA 0x11020000 /* Fabric Assign AL_PA bitmap, 20B payload */
15   -#define FC_AL_LIPA 0x11030000 /* Previously Acquired AL_PA bitmap, 20B payload */
16   -#define FC_AL_LIHA 0x11040000 /* Hard Assigned AL_PA bitmap, 20B payload */
17   -#define FC_AL_LISA 0x11050000 /* Soft Assigned AL_PA bitmap, 20B payload */
18   -#define FC_AL_LIRP 0x11060000 /* Report AL_PA position map, 132B payload */
19   -#define FC_AL_LILP 0x11070000 /* Loop AL_PA position map, 132B payload */
20   -
21   -typedef struct {
22   - u32 magic;
23   - u8 len;
24   - u8 alpa[127];
25   -} fc_al_posmap;
26   -
27   -#endif /* !(__FC_H) */
drivers/fc4/fc.c
Changes suppressed. Click to show
1   -/* 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/jiffies.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   -
37   -#include <asm/pgtable.h>
38   -#include <asm/irq.h>
39   -#include <asm/semaphore.h>
40   -#include "fcp_impl.h"
41   -#include <scsi/scsi_host.h>
42   -
43   -/* #define FCDEBUG */
44   -
45   -#define fc_printk printk ("%s: ", fc->name); printk
46   -
47   -#ifdef FCDEBUG
48   -#define FCD(x) fc_printk x;
49   -#define FCND(x) printk ("FC: "); printk x;
50   -#else
51   -#define FCD(x)
52   -#define FCND(x)
53   -#endif
54   -
55   -#ifdef __sparc__
56   -#define dma_alloc_consistent(d,s,p) sbus_alloc_consistent(d,s,p)
57   -#define dma_free_consistent(d,s,v,h) sbus_free_consistent(d,s,v,h)
58   -#define dma_map_single(d,v,s,dir) sbus_map_single(d,v,s,dir)
59   -#define dma_unmap_single(d,h,s,dir) sbus_unmap_single(d,h,s,dir)
60   -#define dma_map_sg(d,s,n,dir) sbus_map_sg(d,s,n,dir)
61   -#define dma_unmap_sg(d,s,n,dir) sbus_unmap_sg(d,s,n,dir)
62   -#else
63   -#define dma_alloc_consistent(d,s,p) pci_alloc_consistent(d,s,p)
64   -#define dma_free_consistent(d,s,v,h) pci_free_consistent(d,s,v,h)
65   -#define dma_map_single(d,v,s,dir) pci_map_single(d,v,s,dir)
66   -#define dma_unmap_single(d,h,s,dir) pci_unmap_single(d,h,s,dir)
67   -#define dma_map_sg(d,s,n,dir) pci_map_sg(d,s,n,dir)
68   -#define dma_unmap_sg(d,s,n,dir) pci_unmap_sg(d,s,n,dir)
69   -#endif
70   -
71   -#define FCP_CMND(SCpnt) ((fcp_cmnd *)&(SCpnt->SCp))
72   -#define FC_SCMND(SCpnt) ((fc_channel *)(SCpnt->device->host->hostdata[0]))
73   -#define SC_FCMND(fcmnd) ((struct scsi_cmnd *)((long)fcmnd - (long)&(((struct scsi_cmnd *)0)->SCp)))
74   -
75   -static int fcp_scsi_queue_it(fc_channel *, struct scsi_cmnd *, fcp_cmnd *, int);
76   -void fcp_queue_empty(fc_channel *);
77   -
78   -static void fcp_scsi_insert_queue (fc_channel *fc, fcp_cmnd *fcmd)
79   -{
80   - if (!fc->scsi_que) {
81   - fc->scsi_que = fcmd;
82   - fcmd->next = fcmd;
83   - fcmd->prev = fcmd;
84   - } else {
85   - fc->scsi_que->prev->next = fcmd;
86   - fcmd->prev = fc->scsi_que->prev;
87   - fc->scsi_que->prev = fcmd;
88   - fcmd->next = fc->scsi_que;
89   - }
90   -}
91   -
92   -static void fcp_scsi_remove_queue (fc_channel *fc, fcp_cmnd *fcmd)
93   -{
94   - if (fcmd == fcmd->next) {
95   - fc->scsi_que = NULL;
96   - return;
97   - }
98   - if (fcmd == fc->scsi_que)
99   - fc->scsi_que = fcmd->next;
100   - fcmd->prev->next = fcmd->next;
101   - fcmd->next->prev = fcmd->prev;
102   -}
103   -
104   -fc_channel *fc_channels = NULL;
105   -
106   -#define LSMAGIC 620829043
107   -typedef struct {
108   - /* Must be first */
109   - struct semaphore sem;
110   - int magic;
111   - int count;
112   - logi *logi;
113   - fcp_cmnd *fcmds;
114   - atomic_t todo;
115   - struct timer_list timer;
116   - unsigned char grace[0];
117   -} ls;
118   -
119   -#define LSOMAGIC 654907799
120   -typedef struct {
121   - /* Must be first */
122   - struct semaphore sem;
123   - int magic;
124   - int count;
125   - fcp_cmnd *fcmds;
126   - atomic_t todo;
127   - struct timer_list timer;
128   -} lso;
129   -
130   -#define LSEMAGIC 84482456
131   -typedef struct {
132   - /* Must be first */
133   - struct semaphore sem;
134   - int magic;
135   - int status;
136   - struct timer_list timer;
137   -} lse;
138   -
139   -static void fcp_login_timeout(unsigned long data)
140   -{
141   - ls *l = (ls *)data;
142   - FCND(("Login timeout\n"))
143   - up(&l->sem);
144   -}
145   -
146   -static void fcp_login_done(fc_channel *fc, int i, int status)
147   -{
148   - fcp_cmnd *fcmd;
149   - logi *plogi;
150   - fc_hdr *fch;
151   - ls *l = (ls *)fc->ls;
152   -
153   - FCD(("Login done %d %d\n", i, status))
154   - if (i < l->count) {
155   - if (fc->state == FC_STATE_FPORT_OK) {
156   - FCD(("Additional FPORT_OK received with status %d\n", status))
157   - return;
158   - }
159   - switch (status) {
160   - case FC_STATUS_OK: /* Oh, we found a fabric */
161   - case FC_STATUS_P_RJT: /* Oh, we haven't found any */
162   - fc->state = FC_STATE_FPORT_OK;
163   - fcmd = l->fcmds + i;
164   - plogi = l->logi + 3 * i;
165   - dma_unmap_single (fc->dev, fcmd->cmd, 3 * sizeof(logi),
166   - DMA_BIDIRECTIONAL);
167   - plogi->code = LS_PLOGI;
168   - memcpy (&plogi->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
169   - memcpy (&plogi->node_wwn, &fc->wwn_node, sizeof(fc_wwn));
170   - memcpy (&plogi->common, fc->common_svc, sizeof(common_svc_parm));
171   - memcpy (&plogi->class1, fc->class_svcs, 3*sizeof(svc_parm));
172   - fch = &fcmd->fch;
173   - fcmd->token += l->count;
174   - FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, fc->did);
175   - FILL_FCHDR_SID(fch, fc->sid);
176   -#ifdef FCDEBUG
177   - {
178   - int i;
179   - unsigned *x = (unsigned *)plogi;
180   - printk ("logi: ");
181   - for (i = 0; i < 21; i++)
182   - printk ("%08x ", x[i]);
183   - printk ("\n");
184   - }
185   -#endif
186   - fcmd->cmd = dma_map_single (fc->dev, plogi, 3 * sizeof(logi),
187   - DMA_BIDIRECTIONAL);
188   - fcmd->rsp = fcmd->cmd + 2 * sizeof(logi);
189   - if (fc->hw_enque (fc, fcmd))
190   - printk ("FC: Cannot enque PLOGI packet on %s\n", fc->name);
191   - break;
192   - case FC_STATUS_ERR_OFFLINE:
193   - fc->state = FC_STATE_MAYBEOFFLINE;
194   - FCD (("FC is offline %d\n", l->grace[i]))
195   - break;
196   - default:
197   - printk ("FLOGI failed for %s with status %d\n", fc->name, status);
198   - /* Do some sort of error recovery here */
199   - break;
200   - }
201   - } else {
202   - i -= l->count;
203   - if (fc->state != FC_STATE_FPORT_OK) {
204   - FCD(("Unexpected N-PORT rsp received"))
205   - return;
206   - }
207   - switch (status) {
208   - case FC_STATUS_OK:
209   - plogi = l->logi + 3 * i;
210   - dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
211   - DMA_BIDIRECTIONAL);
212   - if (!fc->wwn_dest.lo && !fc->wwn_dest.hi) {
213   - memcpy (&fc->wwn_dest, &plogi[1].node_wwn, sizeof(fc_wwn));
214   - FCD(("Dest WWN %08x%08x\n", *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo))
215   - } else if (fc->wwn_dest.lo != plogi[1].node_wwn.lo ||
216   - fc->wwn_dest.hi != plogi[1].node_wwn.hi) {
217   - printk ("%s: mismatch in wwns. Got %08x%08x, expected %08x%08x\n",
218   - fc->name,
219   - *(u32 *)&plogi[1].node_wwn, plogi[1].node_wwn.lo,
220   - *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo);
221   - }
222   - fc->state = FC_STATE_ONLINE;
223   - printk ("%s: ONLINE\n", fc->name);
224   - if (atomic_dec_and_test (&l->todo))
225   - up(&l->sem);
226   - break;
227   - case FC_STATUS_ERR_OFFLINE:
228   - fc->state = FC_STATE_OFFLINE;
229   - dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
230   - DMA_BIDIRECTIONAL);
231   - printk ("%s: FC is offline\n", fc->name);
232   - if (atomic_dec_and_test (&l->todo))
233   - up(&l->sem);
234   - break;
235   - default:
236   - printk ("PLOGI failed for %s with status %d\n", fc->name, status);
237   - /* Do some sort of error recovery here */
238   - break;
239   - }
240   - }
241   -}
242   -
243   -static void fcp_report_map_done(fc_channel *fc, int i, int status)
244   -{
245   - fcp_cmnd *fcmd;
246   - fc_hdr *fch;
247   - unsigned char j;
248   - ls *l = (ls *)fc->ls;
249   - fc_al_posmap *p;
250   -
251   - FCD(("Report map done %d %d\n", i, status))
252   - switch (status) {
253   - case FC_STATUS_OK: /* Ok, let's have a fun on a loop */
254   - dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
255   - DMA_BIDIRECTIONAL);
256   - p = (fc_al_posmap *)(l->logi + 3 * i);
257   -#ifdef FCDEBUG
258   - {
259   - u32 *u = (u32 *)p;
260   - FCD(("%08x\n", u[0]))
261   - u ++;
262   - 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]))
263   - }
264   -#endif
265   - if ((p->magic & 0xffff0000) != FC_AL_LILP || !p->len) {
266   - printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic);
267   - fc->state = FC_STATE_OFFLINE;
268   - } else {
269   - fc->posmap = kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
270   - if (!fc->posmap) {
271   - printk("FC: Not enough memory, offlining channel\n");
272   - fc->state = FC_STATE_OFFLINE;
273   - } else {
274   - int k;
275   - /* FIXME: This is where SOCAL transfers our AL-PA.
276   - Keep it here till we found out what other cards do... */
277   - fc->sid = (p->magic & 0xff);
278   - for (i = 0; i < p->len; i++)
279   - if (p->alpa[i] == fc->sid)
280   - break;
281   - k = p->len;
282   - if (i == p->len)
283   - i = 0;
284   - else {
285   - p->len--;
286   - i++;
287   - }
288   - fc->posmap->len = p->len;
289   - for (j = 0; j < p->len; j++) {
290   - if (i == k) i = 0;
291   - fc->posmap->list[j] = p->alpa[i++];
292   - }
293   - fc->state = FC_STATE_ONLINE;
294   - }
295   - }
296   - printk ("%s: ONLINE\n", fc->name);
297   - if (atomic_dec_and_test (&l->todo))
298   - up(&l->sem);
299   - break;
300   - case FC_STATUS_POINTTOPOINT: /* We're Point-to-Point, no AL... */
301   - FCD(("SID %d DID %d\n", fc->sid, fc->did))
302   - fcmd = l->fcmds + i;
303   - dma_unmap_single(fc->dev, fcmd->cmd, 3 * sizeof(logi),
304   - DMA_BIDIRECTIONAL);
305   - fch = &fcmd->fch;
306   - memset(l->logi + 3 * i, 0, 3 * sizeof(logi));
307   - FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT);
308   - FILL_FCHDR_SID(fch, 0);
309   - FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
310   - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
311   - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
312   - fch->param = 0;
313   - l->logi [3 * i].code = LS_FLOGI;
314   - fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi),
315   - DMA_BIDIRECTIONAL);
316   - fcmd->rsp = fcmd->cmd + sizeof(logi);
317   - fcmd->cmdlen = sizeof(logi);
318   - fcmd->rsplen = sizeof(logi);
319   - fcmd->data = (dma_addr_t)NULL;
320   - fcmd->class = FC_CLASS_SIMPLE;
321   - fcmd->proto = TYPE_EXTENDED_LS;
322   - if (fc->hw_enque (fc, fcmd))
323   - printk ("FC: Cannot enque FLOGI packet on %s\n", fc->name);
324   - break;
325   - case FC_STATUS_ERR_OFFLINE:
326   - fc->state = FC_STATE_MAYBEOFFLINE;
327   - FCD (("FC is offline %d\n", l->grace[i]))
328   - break;
329   - default:
330   - printk ("FLOGI failed for %s with status %d\n", fc->name, status);
331   - /* Do some sort of error recovery here */
332   - break;
333   - }
334   -}
335   -
336   -void fcp_register(fc_channel *fc, u8 type, int unregister)
337   -{
338   - int size, i;
339   - int slots = (fc->can_queue * 3) >> 1;
340   -
341   - FCND(("Going to %sregister\n", unregister ? "un" : ""))
342   -
343   - if (type == TYPE_SCSI_FCP) {
344   - if (!unregister) {
345   - fc->scsi_cmd_pool = (fcp_cmd *)
346   - dma_alloc_consistent (fc->dev,
347   - slots * (sizeof (fcp_cmd) + fc->rsp_size),
348   - &fc->dma_scsi_cmd);
349   - fc->scsi_rsp_pool = (char *)(fc->scsi_cmd_pool + slots);
350   - fc->dma_scsi_rsp = fc->dma_scsi_cmd + slots * sizeof (fcp_cmd);
351   - fc->scsi_bitmap_end = (slots + 63) & ~63;
352   - size = fc->scsi_bitmap_end / 8;
353   - fc->scsi_bitmap = kzalloc (size, GFP_KERNEL);
354   - set_bit (0, fc->scsi_bitmap);
355   - for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++)
356   - set_bit (i, fc->scsi_bitmap);
357   - fc->scsi_free = fc->can_queue;
358   - fc->cmd_slots = kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
359   - fc->abort_count = 0;
360   - } else {
361   - fc->scsi_name[0] = 0;
362   - kfree (fc->scsi_bitmap);
363   - kfree (fc->cmd_slots);
364   - FCND(("Unregistering\n"));
365   -#if 0
366   - if (fc->rst_pkt) {
367   - if (fc->rst_pkt->eh_state == SCSI_STATE_UNUSED)
368   - kfree(fc->rst_pkt);
369   - else {
370   - /* Can't happen. Some memory would be lost. */
371   - printk("FC: Reset in progress. Now?!");
372   - }
373   - }
374   -#endif
375   - FCND(("Unregistered\n"));
376   - }
377   - } else
378   - printk ("FC: %segistering unknown type %02x\n", unregister ? "Unr" : "R", type);
379   -}
380   -
381   -static void fcp_scsi_done(struct scsi_cmnd *SCpnt);
382   -
383   -static inline void fcp_scsi_receive(fc_channel *fc, int token, int status, fc_hdr *fch)
384   -{
385   - fcp_cmnd *fcmd;
386   - fcp_rsp *rsp;
387   - int host_status;
388   - struct scsi_cmnd *SCpnt;
389   - int sense_len;
390   - int rsp_status;
391   -
392   - fcmd = fc->cmd_slots[token];
393   - if (!fcmd) return;
394   - rsp = (fcp_rsp *) (fc->scsi_rsp_pool + fc->rsp_size * token);
395   - SCpnt = SC_FCMND(fcmd);
396   -
397   - if (SCpnt->done != fcp_scsi_done)
398   - return;
399   -
400   - rsp_status = rsp->fcp_status;
401   - FCD(("rsp_status %08x status %08x\n", rsp_status, status))
402   - switch (status) {
403   - case FC_STATUS_OK:
404   - host_status=DID_OK;
405   -
406   - if (rsp_status & FCP_STATUS_RESID) {
407   -#ifdef FCDEBUG
408   - FCD(("Resid %d\n", rsp->fcp_resid))
409   - {
410   - fcp_cmd *cmd = fc->scsi_cmd_pool + token;
411   - int i;
412   -
413   - printk ("Command ");
414   - for (i = 0; i < sizeof(fcp_cmd); i+=4)
415   - printk ("%08x ", *(u32 *)(((char *)cmd)+i));
416   - printk ("\nResponse ");
417   - for (i = 0; i < fc->rsp_size; i+=4)
418   - printk ("%08x ", *(u32 *)(((char *)rsp)+i));
419   - printk ("\n");
420   - }
421   -#endif
422   - }
423   -
424   - if (rsp_status & FCP_STATUS_SENSE_LEN) {
425   - sense_len = rsp->fcp_sense_len;
426   - if (sense_len > sizeof(SCpnt->sense_buffer)) sense_len = sizeof(SCpnt->sense_buffer);
427   - memcpy(SCpnt->sense_buffer, ((char *)(rsp+1)), sense_len);
428   - }
429   -
430   - if (fcmd->data)
431   - dma_unmap_sg(fc->dev, scsi_sglist(SCpnt),
432   - scsi_sg_count(SCpnt),
433   - SCpnt->sc_data_direction);
434   - break;
435   - default:
436   - host_status=DID_ERROR; /* FIXME */
437   - FCD(("Wrong FC status %d for token %d\n", status, token))
438   - break;
439   - }
440   -
441   - if (status_byte(rsp_status) == QUEUE_FULL) {
442   - printk ("%s: (%d,%d) Received rsp_status 0x%x\n", fc->name, SCpnt->device->channel, SCpnt->device->id, rsp_status);
443   - }
444   -
445   - SCpnt->result = (host_status << 16) | (rsp_status & 0xff);
446   -#ifdef FCDEBUG
447   - if (host_status || SCpnt->result || rsp_status) printk("FC: host_status %d, packet status %d\n",
448   - host_status, SCpnt->result);
449   -#endif
450   - SCpnt->done = fcmd->done;
451   - fcmd->done=NULL;
452   - clear_bit(token, fc->scsi_bitmap);
453   - fc->scsi_free++;
454   - FCD(("Calling scsi_done with %08x\n", SCpnt->result))
455   - SCpnt->scsi_done(SCpnt);
456   -}
457   -
458   -void fcp_receive_solicited(fc_channel *fc, int proto, int token, int status, fc_hdr *fch)
459   -{
460   - int magic;
461   - FCD(("receive_solicited %d %d %d\n", proto, token, status))
462   - switch (proto) {
463   - case TYPE_SCSI_FCP:
464   - fcp_scsi_receive(fc, token, status, fch); break;
465   - case TYPE_EXTENDED_LS:
466   - case PROTO_REPORT_AL_MAP:
467   - magic = 0;
468   - if (fc->ls)
469   - magic = ((ls *)(fc->ls))->magic;
470   - if (magic == LSMAGIC) {
471   - ls *l = (ls *)fc->ls;
472   - int i = (token >= l->count) ? token - l->count : token;
473   -
474   - /* Let's be sure */
475   - if ((unsigned)i < l->count && l->fcmds[i].fc == fc) {
476   - if (proto == TYPE_EXTENDED_LS)
477   - fcp_login_done(fc, token, status);
478   - else
479   - fcp_report_map_done(fc, token, status);
480   - break;
481   - }
482   - }
483   - FCD(("fc %p fc->ls %p fc->cmd_slots %p\n", fc, fc->ls, fc->cmd_slots))
484   - if (proto == TYPE_EXTENDED_LS && !fc->ls && fc->cmd_slots) {
485   - fcp_cmnd *fcmd;
486   -
487   - fcmd = fc->cmd_slots[token];
488   - if (fcmd && fcmd->ls && ((ls *)(fcmd->ls))->magic == LSEMAGIC) {
489   - lse *l = (lse *)fcmd->ls;
490   -
491   - l->status = status;
492   - up (&l->sem);
493   - }
494   - }
495   - break;
496   - case PROTO_OFFLINE:
497   - if (fc->ls && ((lso *)(fc->ls))->magic == LSOMAGIC) {
498   - lso *l = (lso *)fc->ls;
499   -
500   - if ((unsigned)token < l->count && l->fcmds[token].fc == fc) {
501   - /* Wow, OFFLINE response arrived :) */
502   - FCD(("OFFLINE Response arrived\n"))
503   - fc->state = FC_STATE_OFFLINE;
504   - if (atomic_dec_and_test (&l->todo))
505   - up(&l->sem);
506   - }
507   - }
508   - break;
509   -
510   - default:
511   - break;
512   - }
513   -}
514   -
515   -void fcp_state_change(fc_channel *fc, int state)
516   -{
517   - FCD(("state_change %d %d\n", state, fc->state))
518   - if (state == FC_STATE_ONLINE && fc->state == FC_STATE_MAYBEOFFLINE)
519   - fc->state = FC_STATE_UNINITED;
520   - else if (state == FC_STATE_ONLINE)
521   - printk (KERN_WARNING "%s: state change to ONLINE\n", fc->name);
522   - else
523   - printk (KERN_ERR "%s: state change to OFFLINE\n", fc->name);
524   -}
525   -
526   -int fcp_initialize(fc_channel *fcchain, int count)
527   -{
528   - fc_channel *fc;
529   - fcp_cmnd *fcmd;
530   - int i, retry, ret;
531   - ls *l;
532   -
533   - FCND(("fcp_inititialize %08lx\n", (long)fcp_init))
534   - FCND(("fc_channels %08lx\n", (long)fc_channels))
535   - FCND((" SID %d DID %d\n", fcchain->sid, fcchain->did))
536   - l = kzalloc(sizeof (ls) + count, GFP_KERNEL);
537   - if (!l) {
538   - printk ("FC: Cannot allocate memory for initialization\n");
539   - return -ENOMEM;
540   - }
541   - l->magic = LSMAGIC;
542   - l->count = count;
543   - FCND(("FCP Init for %d channels\n", count))
544   - init_MUTEX_LOCKED(&l->sem);
545   - init_timer(&l->timer);
546   - l->timer.function = fcp_login_timeout;
547   - l->timer.data = (unsigned long)l;
548   - atomic_set (&l->todo, count);
549   - l->logi = kzalloc (count * 3 * sizeof(logi), GFP_KERNEL);
550   - l->fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
551   - if (!l->logi || !l->fcmds) {
552   - kfree (l->logi);
553   - kfree (l->fcmds);
554   - kfree (l);
555   - printk ("FC: Cannot allocate DMA memory for initialization\n");
556   - return -ENOMEM;
557   - }
558   - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
559   - fc->state = FC_STATE_UNINITED;
560   - fc->rst_pkt = NULL; /* kmalloc when first used */
561   - }
562   - /* First try if we are in a AL topology */
563   - FCND(("Initializing REPORT_MAP packets\n"))
564   - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
565   - fcmd = l->fcmds + i;
566   - fc->login = fcmd;
567   - fc->ls = (void *)l;
568   - /* Assumes sizeof(fc_al_posmap) < 3 * sizeof(logi), which is true */
569   - fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi),
570   - DMA_BIDIRECTIONAL);
571   - fcmd->proto = PROTO_REPORT_AL_MAP;
572   - fcmd->token = i;
573   - fcmd->fc = fc;
574   - }
575   - for (retry = 0; retry < 8; retry++) {
576   - int nqueued = 0;
577   - FCND(("Sending REPORT_MAP/FLOGI/PLOGI packets\n"))
578   - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
579   - if (fc->state == FC_STATE_ONLINE || fc->state == FC_STATE_OFFLINE)
580   - continue;
581   - disable_irq(fc->irq);
582   - if (fc->state == FC_STATE_MAYBEOFFLINE) {
583   - if (!l->grace[i]) {
584   - l->grace[i]++;
585   - FCD(("Grace\n"))
586   - } else {
587   - fc->state = FC_STATE_OFFLINE;
588   - enable_irq(fc->irq);
589   - dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
590   - if (atomic_dec_and_test (&l->todo))
591   - goto all_done;
592   - }
593   - }
594   - ret = fc->hw_enque (fc, fc->login);
595   - enable_irq(fc->irq);
596   - if (!ret) {
597   - nqueued++;
598   - continue;
599   - }
600   - if (ret == -ENOSYS && fc->login->proto == PROTO_REPORT_AL_MAP) {
601   - /* Oh yes, this card handles Point-to-Point only, so let's try that. */
602   - fc_hdr *fch;
603   -
604   - FCD(("SID %d DID %d\n", fc->sid, fc->did))
605   - fcmd = l->fcmds + i;
606   - dma_unmap_single(fc->dev, fcmd->cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
607   - fch = &fcmd->fch;
608   - FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT);
609   - FILL_FCHDR_SID(fch, 0);
610   - FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
611   - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
612   - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
613   - fch->param = 0;
614   - l->logi [3 * i].code = LS_FLOGI;
615   - fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
616   - fcmd->rsp = fcmd->cmd + sizeof(logi);
617   - fcmd->cmdlen = sizeof(logi);
618   - fcmd->rsplen = sizeof(logi);
619   - fcmd->data = (dma_addr_t)NULL;
620   - fcmd->class = FC_CLASS_SIMPLE;
621   - fcmd->proto = TYPE_EXTENDED_LS;
622   - } else
623   - printk ("FC: Cannot enque FLOGI/REPORT_MAP packet on %s\n", fc->name);
624   - }
625   -
626   - if (nqueued) {
627   - l->timer.expires = jiffies + 5 * HZ;
628   - add_timer(&l->timer);
629   -
630   - down(&l->sem);
631   - if (!atomic_read(&l->todo)) {
632   - FCND(("All channels answered in time\n"))
633   - break; /* All fc channels have answered us */
634   - }
635   - }
636   - }
637   -all_done:
638   - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
639   - fc->ls = NULL;
640   - switch (fc->state) {
641   - case FC_STATE_ONLINE: break;
642   - case FC_STATE_OFFLINE: break;
643   - default: dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
644   - break;
645   - }
646   - }
647   - del_timer(&l->timer);
648   - kfree (l->logi);
649   - kfree (l->fcmds);
650   - kfree (l);
651   - return 0;
652   -}
653   -
654   -int fcp_forceoffline(fc_channel *fcchain, int count)
655   -{
656   - fc_channel *fc;
657   - fcp_cmnd *fcmd;
658   - int i, ret;
659   - lso l;
660   -
661   - memset (&l, 0, sizeof(lso));
662   - l.count = count;
663   - l.magic = LSOMAGIC;
664   - FCND(("FCP Force Offline for %d channels\n", count))
665   - init_MUTEX_LOCKED(&l.sem);
666   - init_timer(&l.timer);
667   - l.timer.function = fcp_login_timeout;
668   - l.timer.data = (unsigned long)&l;
669   - atomic_set (&l.todo, count);
670   - l.fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
671   - if (!l.fcmds) {
672   - printk ("FC: Cannot allocate memory for forcing offline\n");
673   - return -ENOMEM;
674   - }
675   - FCND(("Initializing OFFLINE packets\n"))
676   - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
677   - fc->state = FC_STATE_UNINITED;
678   - fcmd = l.fcmds + i;
679   - fc->login = fcmd;
680   - fc->ls = (void *)&l;
681   - fcmd->did = fc->did;
682   - fcmd->class = FC_CLASS_OFFLINE;
683   - fcmd->proto = PROTO_OFFLINE;
684   - fcmd->token = i;
685   - fcmd->fc = fc;
686   - disable_irq(fc->irq);
687   - ret = fc->hw_enque (fc, fc->login);
688   - enable_irq(fc->irq);
689   - if (ret) printk ("FC: Cannot enque OFFLINE packet on %s\n", fc->name);
690   - }
691   -
692   - l.timer.expires = jiffies + 5 * HZ;
693   - add_timer(&l.timer);
694   - down(&l.sem);
695   - del_timer(&l.timer);
696   -
697   - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++)
698   - fc->ls = NULL;
699   - kfree (l.fcmds);
700   - return 0;
701   -}
702   -
703   -int fcp_init(fc_channel *fcchain)
704   -{
705   - fc_channel *fc;
706   - int count=0;
707   - int ret;
708   -
709   - for (fc = fcchain; fc; fc = fc->next) {
710   - fc->fcp_register = fcp_register;
711   - count++;
712   - }
713   -
714   - ret = fcp_initialize (fcchain, count);
715   - if (ret)
716   - return ret;
717   -
718   - if (!fc_channels)
719   - fc_channels = fcchain;
720   - else {
721   - for (fc = fc_channels; fc->next; fc = fc->next);
722   - fc->next = fcchain;
723   - }
724   - return ret;
725   -}
726   -
727   -void fcp_release(fc_channel *fcchain, int count) /* count must > 0 */
728   -{
729   - fc_channel *fc;
730   - fc_channel *fcx;
731   -
732   - for (fc = fcchain; --count && fc->next; fc = fc->next);
733   - if (count) {
734   - printk("FC: nothing to release\n");
735   - return;
736   - }
737   -
738   - if (fc_channels == fcchain)
739   - fc_channels = fc->next;
740   - else {
741   - for (fcx = fc_channels; fcx->next != fcchain; fcx = fcx->next);
742   - fcx->next = fc->next;
743   - }
744   - fc->next = NULL;
745   -
746   - /*
747   - * We've just grabbed fcchain out of the fc_channel list
748   - * and zero-terminated it, while destroying the count.
749   - *
750   - * Freeing the fc's is the low level driver's responsibility.
751   - */
752   -}
753   -
754   -
755   -static void fcp_scsi_done(struct scsi_cmnd *SCpnt)
756   -{
757   - if (FCP_CMND(SCpnt)->done)
758   - FCP_CMND(SCpnt)->done(SCpnt);
759   -}
760   -
761   -static int fcp_scsi_queue_it(fc_channel *fc, struct scsi_cmnd *SCpnt,
762   - fcp_cmnd *fcmd, int prepare)
763   -{
764   - long i;
765   - fcp_cmd *cmd;
766   - u32 fcp_cntl;
767   - if (prepare) {
768   - i = find_first_zero_bit (fc->scsi_bitmap, fc->scsi_bitmap_end);
769   - set_bit (i, fc->scsi_bitmap);
770   - fcmd->token = i;
771   - cmd = fc->scsi_cmd_pool + i;
772   -
773   - if (fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd)) {
774   - /* Invalid channel/id/lun and couldn't map it into fcp_addr */
775   - clear_bit (i, fc->scsi_bitmap);
776   - SCpnt->result = (DID_BAD_TARGET << 16);
777   - SCpnt->scsi_done(SCpnt);
778   - return 0;
779   - }
780   - fc->scsi_free--;
781   - fc->cmd_slots[fcmd->token] = fcmd;
782   -
783   - if (SCpnt->device->tagged_supported) {
784   - if (jiffies - fc->ages[SCpnt->device->channel * fc->targets + SCpnt->device->id] > (5 * 60 * HZ)) {
785   - fc->ages[SCpnt->device->channel * fc->targets + SCpnt->device->id] = jiffies;
786   - fcp_cntl = FCP_CNTL_QTYPE_ORDERED;
787   - } else
788   - fcp_cntl = FCP_CNTL_QTYPE_SIMPLE;
789   - } else
790   - fcp_cntl = FCP_CNTL_QTYPE_UNTAGGED;
791   -
792   - if (!scsi_bufflen(SCpnt)) {
793   - cmd->fcp_cntl = fcp_cntl;
794   - fcmd->data = (dma_addr_t)NULL;
795   - } else {
796   - struct scatterlist *sg;
797   - int nents;
798   -
799   - switch (SCpnt->cmnd[0]) {
800   - case WRITE_6:
801   - case WRITE_10:
802   - case WRITE_12:
803   - cmd->fcp_cntl = (FCP_CNTL_WRITE | fcp_cntl); break;
804   - default:
805   - cmd->fcp_cntl = (FCP_CNTL_READ | fcp_cntl); break;
806   - }
807   -
808   - sg = scsi_sglist(SCpnt);
809   - nents = dma_map_sg(fc->dev, sg, scsi_sg_count(SCpnt),
810   - SCpnt->sc_data_direction);
811   - fcmd->data = sg_dma_address(sg);
812   - cmd->fcp_data_len = sg_dma_len(sg);
813   - }
814   - memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len);
815   - memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);
816   - 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)))
817   - }
818   - FCD(("Trying to enque %p\n", fcmd))
819   - if (!fc->scsi_que) {
820   - if (!fc->hw_enque (fc, fcmd)) {
821   - FCD(("hw_enque succeeded for %p\n", fcmd))
822   - return 0;
823   - }
824   - }
825   - FCD(("Putting into que1 %p\n", fcmd))
826   - fcp_scsi_insert_queue (fc, fcmd);
827   - return 0;
828   -}
829   -
830   -int fcp_scsi_queuecommand(struct scsi_cmnd *SCpnt,
831   - void (* done)(struct scsi_cmnd *))
832   -{
833   - fcp_cmnd *fcmd = FCP_CMND(SCpnt);
834   - fc_channel *fc = FC_SCMND(SCpnt);
835   -
836   - FCD(("Entering SCSI queuecommand %p\n", fcmd))
837   - if (SCpnt->done != fcp_scsi_done) {
838   - fcmd->done = SCpnt->done;
839   - SCpnt->done = fcp_scsi_done;
840   - SCpnt->scsi_done = done;
841   - fcmd->proto = TYPE_SCSI_FCP;
842   - if (!fc->scsi_free) {
843   - FCD(("FC: !scsi_free, putting cmd on ML queue\n"))
844   -#if (FCP_SCSI_USE_NEW_EH_CODE == 0)
845   - printk("fcp_scsi_queue_command: queue full, losing cmd, bad\n");
846   -#endif
847   - return 1;
848   - }
849   - return fcp_scsi_queue_it(fc, SCpnt, fcmd, 1);
850   - }
851   - return fcp_scsi_queue_it(fc, SCpnt, fcmd, 0);
852   -}
853   -
854   -void fcp_queue_empty(fc_channel *fc)
855   -{
856   - fcp_cmnd *fcmd;
857   -
858   - FCD(("Queue empty\n"))
859   - while ((fcmd = fc->scsi_que)) {
860   - /* The hw told us we can try again queue some packet */
861   - if (fc->hw_enque (fc, fcmd))
862   - break;
863   - fcp_scsi_remove_queue (fc, fcmd);
864   - }
865   -}
866   -
867   -int fcp_scsi_abort(struct scsi_cmnd *SCpnt)
868   -{
869   - /* Internal bookkeeping only. Lose 1 cmd_slots slot. */
870   - fcp_cmnd *fcmd = FCP_CMND(SCpnt);
871   - fc_channel *fc = FC_SCMND(SCpnt);
872   -
873   - /*
874   - * We react to abort requests by simply forgetting
875   - * about the command and pretending everything's sweet.
876   - * This may or may not be silly. We can't, however,
877   - * immediately reuse the command's cmd_slots slot,
878   - * as its result may arrive later and we cannot
879   - * check whether it is the aborted one, can't we?
880   - *
881   - * Therefore, after the first few aborts are done,
882   - * we tell the scsi error handler to do something clever.
883   - * It will eventually call host reset, refreshing
884   - * cmd_slots for us.
885   - *
886   - * There is a theoretical chance that we sometimes allow
887   - * more than can_queue packets to the jungle this way,
888   - * but the worst outcome possible is a series of
889   - * more aborts and eventually the dev_reset catharsis.
890   - */
891   -
892   - if (++fc->abort_count < (fc->can_queue >> 1)) {
893   - SCpnt->result = DID_ABORT;
894   - fcmd->done(SCpnt);
895   - printk("FC: soft abort\n");
896   - return SUCCESS;
897   - } else {
898   - printk("FC: hard abort refused\n");
899   - return FAILED;
900   - }
901   -}
902   -
903   -#if 0
904   -void fcp_scsi_reset_done(struct scsi_cmnd *SCpnt)
905   -{
906   - fc_channel *fc = FC_SCMND(SCpnt);
907   -
908   - fc->rst_pkt->eh_state = SCSI_STATE_FINISHED;
909   - up(fc->rst_pkt->device->host->eh_action);
910   -}
911   -#endif
912   -
913   -#define FCP_RESET_TIMEOUT (2*HZ)
914   -
915   -int fcp_scsi_dev_reset(struct scsi_cmnd *SCpnt)
916   -{
917   -#if 0 /* broken junk, but if davem wants to compile this driver, let him.. */
918   - unsigned long flags;
919   - fcp_cmd *cmd;
920   - fcp_cmnd *fcmd;
921   - fc_channel *fc = FC_SCMND(SCpnt);
922   - DECLARE_MUTEX_LOCKED(sem);
923   -
924   - if (!fc->rst_pkt) {
925   - fc->rst_pkt = kmalloc(sizeof(SCpnt), GFP_KERNEL);
926   - if (!fc->rst_pkt) return FAILED;
927   -
928   - fcmd = FCP_CMND(fc->rst_pkt);
929   -
930   -
931   - fcmd->token = 0;
932   - cmd = fc->scsi_cmd_pool + 0;
933   - FCD(("Preparing rst packet\n"))
934   - fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd);
935   - fc->rst_pkt->device = SCpnt->device;
936   - fc->rst_pkt->cmd_len = 0;
937   -
938   - fc->cmd_slots[0] = fcmd;
939   -
940   - cmd->fcp_cntl = FCP_CNTL_QTYPE_ORDERED | FCP_CNTL_RESET;
941   - fcmd->data = (dma_addr_t)NULL;
942   - fcmd->proto = TYPE_SCSI_FCP;
943   -
944   - memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len);
945   - memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);
946   - 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)))
947   - } else {
948   - fcmd = FCP_CMND(fc->rst_pkt);
949   - if (fc->rst_pkt->eh_state == SCSI_STATE_QUEUED)
950   - return FAILED; /* or SUCCESS. Only these */
951   - }
952   - fc->rst_pkt->done = NULL;
953   -
954   -
955   - fc->rst_pkt->eh_state = SCSI_STATE_QUEUED;
956   - init_timer(&fc->rst_pkt->eh_timeout);
957   - fc->rst_pkt->eh_timeout.data = (unsigned long) fc->rst_pkt;
958   - fc->rst_pkt->eh_timeout.expires = jiffies + FCP_RESET_TIMEOUT;
959   - fc->rst_pkt->eh_timeout.function = (void (*)(unsigned long))fcp_scsi_reset_done;
960   -
961   - add_timer(&fc->rst_pkt->eh_timeout);
962   -
963   - /*
964   - * Set up the semaphore so we wait for the command to complete.
965   - */
966   -
967   - fc->rst_pkt->device->host->eh_action = &sem;
968   -
969   - fc->rst_pkt->done = fcp_scsi_reset_done;
970   -
971   - spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
972   - fcp_scsi_queue_it(fc, fc->rst_pkt, fcmd, 0);
973   - spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
974   -
975   - down(&sem);
976   -
977   - fc->rst_pkt->device->host->eh_action = NULL;
978   - del_timer(&fc->rst_pkt->eh_timeout);
979   -
980   - /*
981   - * See if timeout. If so, tell the host to forget about it.
982   - * In other words, we don't want a callback any more.
983   - */
984   - if (fc->rst_pkt->eh_state == SCSI_STATE_TIMEOUT ) {
985   - fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
986   - return FAILED;
987   - }
988   - fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
989   -#endif
990   - return SUCCESS;
991   -}
992   -
993   -static int __fcp_scsi_host_reset(struct scsi_cmnd *SCpnt)
994   -{
995   - fc_channel *fc = FC_SCMND(SCpnt);
996   - fcp_cmnd *fcmd = FCP_CMND(SCpnt);
997   - int i;
998   -
999   - printk ("FC: host reset\n");
1000   -
1001   - for (i=0; i < fc->can_queue; i++) {
1002   - if (fc->cmd_slots[i] && SCpnt->result != DID_ABORT) {
1003   - SCpnt->result = DID_RESET;
1004   - fcmd->done(SCpnt);
1005   - fc->cmd_slots[i] = NULL;
1006   - }
1007   - }
1008   - fc->reset(fc);
1009   - fc->abort_count = 0;
1010   - if (fcp_initialize(fc, 1)) return SUCCESS;
1011   - else return FAILED;
1012   -}
1013   -
1014   -int fcp_scsi_host_reset(struct scsi_cmnd *SCpnt)
1015   -{
1016   - unsigned long flags;
1017   - int rc;
1018   -
1019   - spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
1020   - rc = __fcp_scsi_host_reset(SCpnt);
1021   - spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
1022   -
1023   - return rc;
1024   -}
1025   -
1026   -static int fcp_els_queue_it(fc_channel *fc, fcp_cmnd *fcmd)
1027   -{
1028   - long i;
1029   -
1030   - i = find_first_zero_bit (fc->scsi_bitmap, fc->scsi_bitmap_end);
1031   - set_bit (i, fc->scsi_bitmap);
1032   - fcmd->token = i;
1033   - fc->scsi_free--;
1034   - fc->cmd_slots[fcmd->token] = fcmd;
1035   - return fcp_scsi_queue_it(fc, NULL, fcmd, 0);
1036   -}
1037   -
1038   -static int fc_do_els(fc_channel *fc, unsigned int alpa, void *data, int len)
1039   -{
1040   - fcp_cmnd _fcmd, *fcmd;
1041   - fc_hdr *fch;
1042   - lse l;
1043   - int i;
1044   -
1045   - fcmd = &_fcmd;
1046   - memset(fcmd, 0, sizeof(fcp_cmnd));
1047   - FCD(("PLOGI SID %d DID %d\n", fc->sid, alpa))
1048   - fch = &fcmd->fch;
1049   - FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, alpa);
1050   - FILL_FCHDR_SID(fch, fc->sid);
1051   - FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
1052   - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
1053   - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
1054   - fch->param = 0;
1055   - fcmd->cmd = dma_map_single (fc->dev, data, 2 * len, DMA_BIDIRECTIONAL);
1056   - fcmd->rsp = fcmd->cmd + len;
1057   - fcmd->cmdlen = len;
1058   - fcmd->rsplen = len;
1059   - fcmd->data = (dma_addr_t)NULL;
1060   - fcmd->fc = fc;
1061   - fcmd->class = FC_CLASS_SIMPLE;
1062   - fcmd->proto = TYPE_EXTENDED_LS;
1063   -
1064   - memset (&l, 0, sizeof(lse));
1065   - l.magic = LSEMAGIC;
1066   - init_MUTEX_LOCKED(&l.sem);
1067   - l.timer.function = fcp_login_timeout;
1068   - l.timer.data = (unsigned long)&l;
1069   - l.status = FC_STATUS_TIMED_OUT;
1070   - fcmd->ls = (void *)&l;
1071   -
1072   - disable_irq(fc->irq);
1073   - fcp_els_queue_it(fc, fcmd);
1074   - enable_irq(fc->irq);
1075   -
1076   - for (i = 0;;) {
1077   - l.timer.expires = jiffies + 5 * HZ;
1078   - add_timer(&l.timer);
1079   - down(&l.sem);
1080   - del_timer(&l.timer);
1081   - if (l.status != FC_STATUS_TIMED_OUT) break;
1082   - if (++i == 3) break;
1083   - disable_irq(fc->irq);
1084   - fcp_scsi_queue_it(fc, NULL, fcmd, 0);
1085   - enable_irq(fc->irq);
1086   - }
1087   -
1088   - clear_bit(fcmd->token, fc->scsi_bitmap);
1089   - fc->scsi_free++;
1090   - dma_unmap_single (fc->dev, fcmd->cmd, 2 * len, DMA_BIDIRECTIONAL);
1091   - return l.status;
1092   -}
1093   -
1094   -int fc_do_plogi(fc_channel *fc, unsigned char alpa, fc_wwn *node, fc_wwn *nport)
1095   -{
1096   - logi *l;
1097   - int status;
1098   -
1099   - l = kzalloc(2 * sizeof(logi), GFP_KERNEL);
1100   - if (!l) return -ENOMEM;
1101   - l->code = LS_PLOGI;
1102   - memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
1103   - memcpy (&l->node_wwn, &fc->wwn_node, sizeof(fc_wwn));
1104   - memcpy (&l->common, fc->common_svc, sizeof(common_svc_parm));
1105   - memcpy (&l->class1, fc->class_svcs, 3*sizeof(svc_parm));
1106   - status = fc_do_els(fc, alpa, l, sizeof(logi));
1107   - if (status == FC_STATUS_OK) {
1108   - if (l[1].code == LS_ACC) {
1109   -#ifdef FCDEBUG
1110   - u32 *u = (u32 *)&l[1].nport_wwn;
1111   - FCD(("AL-PA %02x: Port WWN %08x%08x Node WWN %08x%08x\n", alpa,
1112   - u[0], u[1], u[2], u[3]))
1113   -#endif
1114   - memcpy(nport, &l[1].nport_wwn, sizeof(fc_wwn));
1115   - memcpy(node, &l[1].node_wwn, sizeof(fc_wwn));
1116   - } else
1117   - status = FC_STATUS_BAD_RSP;
1118   - }
1119   - kfree(l);
1120   - return status;
1121   -}
1122   -
1123   -typedef struct {
1124   - unsigned int code;
1125   - unsigned params[4];
1126   -} prli;
1127   -
1128   -int fc_do_prli(fc_channel *fc, unsigned char alpa)
1129   -{
1130   - prli *p;
1131   - int status;
1132   -
1133   - p = kzalloc(2 * sizeof(prli), GFP_KERNEL);
1134   - if (!p) return -ENOMEM;
1135   - p->code = LS_PRLI;
1136   - p->params[0] = 0x08002000;
1137   - p->params[3] = 0x00000022;
1138   - status = fc_do_els(fc, alpa, p, sizeof(prli));
1139   - if (status == FC_STATUS_OK && p[1].code != LS_PRLI_ACC && p[1].code != LS_ACC)
1140   - status = FC_STATUS_BAD_RSP;
1141   - kfree(p);
1142   - return status;
1143   -}
1144   -
1145   -MODULE_LICENSE("GPL");
drivers/fc4/fc.h
1   -/* fc.h: Definitions for Fibre Channel Physical and Signaling Interface.
2   - *
3   - * Copyright (C) 1996-1997,1999 Jakub Jelinek (jj@ultra.linux.cz)
4   - *
5   - * Sources:
6   - * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
7   - * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
8   - */
9   -
10   -#ifndef __FC_H
11   -#define __FC_H
12   -
13   -/* World Wide Name */
14   -#define NAAID_IEEE 1
15   -#define NAAID_IEEE_EXT 2
16   -#define NAAID_LOCAL 3
17   -#define NAAID_IP 4
18   -#define NAAID_IEEE_REG 5
19   -#define NAAID_IEEE_REG_EXT 6
20   -#define NAAID_CCITT 12
21   -#define NAAID_CCITT_GRP 14
22   -
23   -/* This is NAAID_IEEE_EXT scheme */
24   -typedef struct {
25   - u32 naaid:4;
26   - u32 nportid:12;
27   - u32 hi:16;
28   - u32 lo;
29   -} fc_wwn;
30   -
31   -/* Frame header for FC-PH frames */
32   -
33   -/* r_ctl field */
34   -#define R_CTL_DEVICE_DATA 0x00 /* FC4 Device_Data frame */
35   -#define R_CTL_EXTENDED_SVC 0x20 /* Extended Link_Data frame */
36   -#define R_CTL_FC4_SVC 0x30 /* FC4 Link_Data frame */
37   -#define R_CTL_VIDEO 0x40 /* Video_Data frame */
38   -#define R_CTL_BASIC_SVC 0x80 /* Basic Link_Data frame */
39   -#define R_CTL_LINK_CTL 0xc0 /* Link_Control frame */
40   -/* FC4 Device_Data frames */
41   -#define R_CTL_UNCATEGORIZED 0x00
42   -#define R_CTL_SOLICITED_DATA 0x01
43   -#define R_CTL_UNSOL_CONTROL 0x02
44   -#define R_CTL_SOLICITED_CONTROL 0x03
45   -#define R_CTL_UNSOL_DATA 0x04
46   -#define R_CTL_XFER_RDY 0x05
47   -#define R_CTL_COMMAND 0x06
48   -#define R_CTL_STATUS 0x07
49   -/* Basic Link_Data frames */
50   -#define R_CTL_LS_NOP 0x80
51   -#define R_CTL_LS_ABTS 0x81
52   -#define R_CTL_LS_RMC 0x82
53   -#define R_CTL_LS_BA_ACC 0x84
54   -#define R_CTL_LS_BA_RJT 0x85
55   -/* Extended Link_Data frames */
56   -#define R_CTL_ELS_REQ 0x22
57   -#define R_CTL_ELS_RSP 0x23
58   -/* Link_Control frames */
59   -#define R_CTL_ACK_1 0xc0
60   -#define R_CTL_ACK_N 0xc1
61   -#define R_CTL_P_RJT 0xc2
62   -#define R_CTL_F_RJT 0xc3
63   -#define R_CTL_P_BSY 0xc4
64   -#define R_CTL_F_BSY_DF 0xc5
65   -#define R_CTL_F_BSY_LC 0xc6
66   -#define R_CTL_LCR 0xc7
67   -
68   -/* type field */
69   -#define TYPE_BASIC_LS 0x00
70   -#define TYPE_EXTENDED_LS 0x01
71   -#define TYPE_IS8802 0x04
72   -#define TYPE_IS8802_SNAP 0x05
73   -#define TYPE_SCSI_FCP 0x08
74   -#define TYPE_SCSI_GPP 0x09
75   -#define TYPE_HIPP_FP 0x0a
76   -#define TYPE_IPI3_MASTER 0x11
77   -#define TYPE_IPI3_SLAVE 0x12
78   -#define TYPE_IPI3_PEER 0x13
79   -
80   -/* f_ctl field */
81   -#define F_CTL_FILL_BYTES 0x000003
82   -#define F_CTL_XCHG_REASSEMBLE 0x000004
83   -#define F_CTL_RO_PRESENT 0x000008
84   -#define F_CTL_ABORT_SEQ 0x000030
85   -#define F_CTL_CONTINUE_SEQ 0x0000c0
86   -#define F_CTL_INVALIDATE_XID 0x004000
87   -#define F_CTL_XID_REASSIGNED 0x008000
88   -#define F_CTL_SEQ_INITIATIVE 0x010000
89   -#define F_CTL_CHAINED_SEQ 0x020000
90   -#define F_CTL_END_CONNECT 0x040000
91   -#define F_CTL_END_SEQ 0x080000
92   -#define F_CTL_LAST_SEQ 0x100000
93   -#define F_CTL_FIRST_SEQ 0x200000
94   -#define F_CTL_SEQ_CONTEXT 0x400000
95   -#define F_CTL_XCHG_CONTEXT 0x800000
96   -
97   -typedef struct {
98   - u32 r_ctl:8, did:24;
99   - u32 xxx1:8, sid:24;
100   - u32 type:8, f_ctl:24;
101   - u32 seq_id:8, df_ctl:8, seq_cnt:16;
102   - u16 ox_id, rx_id;
103   - u32 param;
104   -} fc_hdr;
105   -/* The following are ugly macros to make setup of this structure faster */
106   -#define FILL_FCHDR_RCTL_DID(fch, r_ctl, did) *(u32 *)(fch) = ((r_ctl) << 24) | (did);
107   -#define FILL_FCHDR_SID(fch, sid) *((u32 *)(fch)+1) = (sid);
108   -#define FILL_FCHDR_TYPE_FCTL(fch, type, f_ctl) *((u32 *)(fch)+2) = ((type) << 24) | (f_ctl);
109   -#define FILL_FCHDR_SEQ_DF_SEQ(fch, seq_id, df_ctl, seq_cnt) *((u32 *)(fch)+3) = ((seq_id) << 24) | ((df_ctl) << 16) | (seq_cnt);
110   -#define FILL_FCHDR_OXRX(fch, ox_id, rx_id) *((u32 *)(fch)+4) = ((ox_id) << 16) | (rx_id);
111   -
112   -/* Well known addresses */
113   -#define FS_GENERAL_MULTICAST 0xfffff7
114   -#define FS_WELL_KNOWN_MULTICAST 0xfffff8
115   -#define FS_HUNT_GROUP 0xfffff9
116   -#define FS_MANAGEMENT_SERVER 0xfffffa
117   -#define FS_TIME_SERVER 0xfffffb
118   -#define FS_NAME_SERVER 0xfffffc
119   -#define FS_FABRIC_CONTROLLER 0xfffffd
120   -#define FS_FABRIC_F_PORT 0xfffffe
121   -#define FS_BROADCAST 0xffffff
122   -
123   -/* Reject frames */
124   -/* The param field should be cast to this structure */
125   -typedef struct {
126   - u8 action;
127   - u8 reason;
128   - u8 xxx;
129   - u8 vendor_unique;
130   -} rjt_param;
131   -
132   -/* Reject action codes */
133   -#define RJT_RETRY 0x01
134   -#define RJT_NONRETRY 0x02
135   -
136   -/* Reject reason codes */
137   -#define RJT_INVALID_DID 0x01
138   -#define RJT_INVALID_SID 0x02
139   -#define RJT_NPORT_NOT_AVAIL_TEMP 0x03
140   -#define RJT_NPORT_NOT_AVAIL_PERM 0x04
141   -#define RJT_CLASS_NOT_SUPPORTED 0x05
142   -#define RJT_DELIMITER_ERROR 0x06
143   -#define RJT_TYPE_NOT_SUPPORTED 0x07
144   -#define RJT_INVALID_LINK_CONTROL 0x08
145   -#define RJT_INVALID_R_CTL 0x09
146   -#define RJT_INVALID_F_CTL 0x0a
147   -#define RJT_INVALID_OX_ID 0x0b
148   -#define RJT_INVALID_RX_ID 0x0c
149   -#define RJT_INVALID_SEQ_ID 0x0d
150   -#define RJT_INVALID_DF_CTL 0x0e
151   -#define RJT_INVALID_SEQ_CNT 0x0f
152   -#define RJT_INVALID_PARAMETER 0x10
153   -#define RJT_EXCHANGE_ERROR 0x11
154   -#define RJT_PROTOCOL_ERROR 0x12
155   -#define RJT_INCORRECT_LENGTH 0x13
156   -#define RJT_UNEXPECTED_ACK 0x14
157   -#define RJT_UNEXPECTED_LINK_RESP 0x15
158   -#define RJT_LOGIN_REQUIRED 0x16
159   -#define RJT_EXCESSIVE_SEQUENCES 0x17
160   -#define RJT_CANT_ESTABLISH_EXCHANGE 0x18
161   -#define RJT_SECURITY_NOT_SUPPORTED 0x19
162   -#define RJT_FABRIC_NA 0x1a
163   -#define RJT_VENDOR_UNIQUE 0xff
164   -
165   -
166   -#define SP_F_PORT_LOGIN 0x10
167   -
168   -/* Extended SVC commands */
169   -#define LS_RJT 0x01000000
170   -#define LS_ACC 0x02000000
171   -#define LS_PRLI_ACC 0x02100014
172   -#define LS_PLOGI 0x03000000
173   -#define LS_FLOGI 0x04000000
174   -#define LS_LOGO 0x05000000
175   -#define LS_ABTX 0x06000000
176   -#define LS_RCS 0x07000000
177   -#define LS_RES 0x08000000
178   -#define LS_RSS 0x09000000
179   -#define LS_RSI 0x0a000000
180   -#define LS_ESTS 0x0b000000
181   -#define LS_ESTC 0x0c000000
182   -#define LS_ADVC 0x0d000000
183   -#define LS_RTV 0x0e000000
184   -#define LS_RLS 0x0f000000
185   -#define LS_ECHO 0x10000000
186   -#define LS_TEST 0x11000000
187   -#define LS_RRQ 0x12000000
188   -#define LS_IDENT 0x20000000
189   -#define LS_PRLI 0x20100014
190   -#define LS_DISPLAY 0x21000000
191   -#define LS_PRLO 0x21100014
192   -#define LS_PDISC 0x50000000
193   -#define LS_ADISC 0x52000000
194   -
195   -typedef struct {
196   - u8 fcph_hi, fcph_lo;
197   - u16 buf2buf_credit;
198   - u8 common_features;
199   - u8 xxx1;
200   - u16 buf2buf_size;
201   - u8 xxx2;
202   - u8 total_concurrent;
203   - u16 off_by_info;
204   - u32 e_d_tov;
205   -} common_svc_parm;
206   -
207   -typedef struct {
208   - u16 serv_opts;
209   - u16 initiator_ctl;
210   - u16 rcpt_ctl;
211   - u16 recv_size;
212   - u8 xxx1;
213   - u8 concurrent_seqs;
214   - u16 end2end_credit;
215   - u16 open_seqs_per_xchg;
216   - u16 xxx2;
217   -} svc_parm;
218   -
219   -/* Login */
220   -typedef struct {
221   - u32 code;
222   - common_svc_parm common;
223   - fc_wwn nport_wwn;
224   - fc_wwn node_wwn;
225   - svc_parm class1;
226   - svc_parm class2;
227   - svc_parm class3;
228   -} logi;
229   -
230   -#endif /* !(__FC_H) */
drivers/fc4/fc_syms.c
1   -/*
2   - * We should not even be trying to compile this if we are not doing
3   - * a module.
4   - */
5   -#include <linux/module.h>
6   -
7   -#ifdef CONFIG_MODULES
8   -
9   -#include <linux/types.h>
10   -#include <linux/string.h>
11   -#include <linux/kernel.h>
12   -
13   -#include "fcp_impl.h"
14   -
15   -EXPORT_SYMBOL(fcp_init);
16   -EXPORT_SYMBOL(fcp_release);
17   -EXPORT_SYMBOL(fcp_queue_empty);
18   -EXPORT_SYMBOL(fcp_receive_solicited);
19   -EXPORT_SYMBOL(fc_channels);
20   -EXPORT_SYMBOL(fcp_state_change);
21   -EXPORT_SYMBOL(fc_do_plogi);
22   -EXPORT_SYMBOL(fc_do_prli);
23   -
24   -/* SCSI stuff */
25   -EXPORT_SYMBOL(fcp_scsi_queuecommand);
26   -EXPORT_SYMBOL(fcp_scsi_abort);
27   -EXPORT_SYMBOL(fcp_scsi_dev_reset);
28   -EXPORT_SYMBOL(fcp_scsi_host_reset);
29   -
30   -#endif /* CONFIG_MODULES */
drivers/fc4/fcp.h
1   -/* fcp.h: Definitions for Fibre Channel Protocol.
2   - *
3   - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
4   - *
5   - */
6   -
7   -#ifndef __FCP_H
8   -#define __FCP_H
9   -
10   -/* FCP addressing is hierarchical with up to 4 layers, MS first.
11   - Exact meaning of the addresses is up to the vendor */
12   -
13   -/* fcp_cntl field */
14   -#define FCP_CNTL_WRITE 0x00000001 /* Initiator write */
15   -#define FCP_CNTL_READ 0x00000002 /* Initiator read */
16   -#define FCP_CNTL_ABORT_TSK 0x00000200 /* Abort task set */
17   -#define FCP_CNTL_CLR_TASK 0x00000400 /* Clear task set */
18   -#define FCP_CNTL_RESET 0x00002000 /* Reset */
19   -#define FCP_CNTL_CLR_ACA 0x00004000 /* Clear ACA */
20   -#define FCP_CNTL_KILL_TASK 0x00008000 /* Terminate task */
21   -#define FCP_CNTL_QTYPE_MASK 0x00070000 /* Tagged queueing type */
22   -#define FCP_CNTL_QTYPE_SIMPLE 0x00000000
23   -#define FCP_CNTL_QTYPE_HEAD_OF_Q 0x00010000
24   -#define FCP_CNTL_QTYPE_ORDERED 0x00020000
25   -#define FCP_CNTL_QTYPE_ACA_Q_TAG 0x00040000
26   -#define FCP_CNTL_QTYPE_UNTAGGED 0x00050000
27   -
28   -typedef struct {
29   - u16 fcp_addr[4];
30   - u32 fcp_cntl;
31   - u8 fcp_cdb[16];
32   - u32 fcp_data_len;
33   -} fcp_cmd;
34   -
35   -/* fcp_status field */
36   -#define FCP_STATUS_MASK 0x000000ff /* scsi status of command */
37   -#define FCP_STATUS_RSP_LEN 0x00000100 /* response_len != 0 */
38   -#define FCP_STATUS_SENSE_LEN 0x00000200 /* sense_len != 0 */
39   -#define FCP_STATUS_RESID 0x00000400 /* resid != 0 */
40   -
41   -typedef struct {
42   - u32 xxx[2];
43   - u32 fcp_status;
44   - u32 fcp_resid;
45   - u32 fcp_sense_len;
46   - u32 fcp_response_len;
47   - /* u8 fcp_sense[fcp_sense_len]; */
48   - /* u8 fcp_response[fcp_response_len]; */
49   -} fcp_rsp;
50   -
51   -/* fcp errors */
52   -
53   -/* rsp_info_type field */
54   -#define FCP_RSP_SCSI_BUS_ERR 0x01
55   -#define FCP_RSP_SCSI_PORT_ERR 0x02
56   -#define FCP_RSP_CARD_ERR 0x03
57   -
58   -/* isp_status field */
59   -#define FCP_RSP_CMD_COMPLETE 0x0000
60   -#define FCP_RSP_CMD_INCOMPLETE 0x0001
61   -#define FCP_RSP_CMD_DMA_ERR 0x0002
62   -#define FCP_RSP_CMD_TRAN_ERR 0x0003
63   -#define FCP_RSP_CMD_RESET 0x0004
64   -#define FCP_RSP_CMD_ABORTED 0x0005
65   -#define FCP_RSP_CMD_TIMEOUT 0x0006
66   -#define FCP_RSP_CMD_OVERRUN 0x0007
67   -
68   -/* isp_state_flags field */
69   -#define FCP_RSP_ST_GOT_BUS 0x0100
70   -#define FCP_RSP_ST_GOT_TARGET 0x0200
71   -#define FCP_RSP_ST_SENT_CMD 0x0400
72   -#define FCP_RSP_ST_XFRD_DATA 0x0800
73   -#define FCP_RSP_ST_GOT_STATUS 0x1000
74   -#define FCP_RSP_ST_GOT_SENSE 0x2000
75   -
76   -/* isp_stat_flags field */
77   -#define FCP_RSP_STAT_DISC 0x0001
78   -#define FCP_RSP_STAT_SYNC 0x0002
79   -#define FCP_RSP_STAT_PERR 0x0004
80   -#define FCP_RSP_STAT_BUS_RESET 0x0008
81   -#define FCP_RSP_STAT_DEV_RESET 0x0010
82   -#define FCP_RSP_STAT_ABORTED 0x0020
83   -#define FCP_RSP_STAT_TIMEOUT 0x0040
84   -#define FCP_RSP_STAT_NEGOTIATE 0x0080
85   -
86   -typedef struct {
87   - u8 rsp_info_type;
88   - u8 xxx;
89   - u16 isp_status;
90   - u16 isp_state_flags;
91   - u16 isp_stat_flags;
92   -} fcp_scsi_err;
93   -
94   -#endif /* !(__FCP_H) */
drivers/fc4/fcp_impl.h
1   -/* fcp_impl.h: Generic SCSI on top of FC4 - our interface defines.
2   - *
3   - * Copyright (C) 1997-1999 Jakub Jelinek (jj@ultra.linux.cz)
4   - * Copyright (C) 1998 Jirka Hanika (geo@ff.cuni.cz)
5   - */
6   -
7   -#ifndef _FCP_SCSI_H
8   -#define _FCP_SCSI_H
9   -
10   -#include <linux/types.h>
11   -#include "../scsi/scsi.h"
12   -
13   -#include "fc.h"
14   -#include "fcp.h"
15   -#include "fc-al.h"
16   -
17   -#include <asm/io.h>
18   -#ifdef __sparc__
19   -#include <asm/sbus.h>
20   -#endif
21   -
22   -/* 0 or 1 */
23   -#define FCP_SCSI_USE_NEW_EH_CODE 0
24   -
25   -#define FC_CLASS_OUTBOUND 0x01
26   -#define FC_CLASS_INBOUND 0x02
27   -#define FC_CLASS_SIMPLE 0x03
28   -#define FC_CLASS_IO_WRITE 0x04
29   -#define FC_CLASS_IO_READ 0x05
30   -#define FC_CLASS_UNSOLICITED 0x06
31   -#define FC_CLASS_OFFLINE 0x08
32   -
33   -#define PROTO_OFFLINE 0x02
34   -#define PROTO_REPORT_AL_MAP 0x03
35   -#define PROTO_FORCE_LIP 0x06
36   -
37   -struct _fc_channel;
38   -
39   -typedef struct fcp_cmnd {
40   - struct fcp_cmnd *next;
41   - struct fcp_cmnd *prev;
42   - void (*done)(struct scsi_cmnd *);
43   - unsigned short proto;
44   - unsigned short token;
45   - unsigned int did;
46   - /* FCP SCSI stuff */
47   - dma_addr_t data;
48   - /* From now on this cannot be touched for proto == TYPE_SCSI_FCP */
49   - fc_hdr fch;
50   - dma_addr_t cmd;
51   - dma_addr_t rsp;
52   - int cmdlen;
53   - int rsplen;
54   - int class;
55   - int datalen;
56   - /* This is just used as a verification during login */
57   - struct _fc_channel *fc;
58   - void *ls;
59   -} fcp_cmnd;
60   -
61   -typedef struct {
62   - unsigned int len;
63   - unsigned char list[0];
64   -} fcp_posmap;
65   -
66   -typedef struct _fc_channel {
67   - struct _fc_channel *next;
68   - int irq;
69   - int state;
70   - int sid;
71   - int did;
72   - char name[16];
73   - void (*fcp_register)(struct _fc_channel *, u8, int);
74   - void (*reset)(struct _fc_channel *);
75   - int (*hw_enque)(struct _fc_channel *, fcp_cmnd *);
76   - fc_wwn wwn_node;
77   - fc_wwn wwn_nport;
78   - fc_wwn wwn_dest;
79   - common_svc_parm *common_svc;
80   - svc_parm *class_svcs;
81   -#ifdef __sparc__
82   - struct sbus_dev *dev;
83   -#else
84   - struct pci_dev *dev;
85   -#endif
86   - struct module *module;
87   - /* FCP SCSI stuff */
88   - short can_queue;
89   - short abort_count;
90   - int rsp_size;
91   - fcp_cmd *scsi_cmd_pool;
92   - char *scsi_rsp_pool;
93   - dma_addr_t dma_scsi_cmd, dma_scsi_rsp;
94   - unsigned long *scsi_bitmap;
95   - long scsi_bitmap_end;
96   - int scsi_free;
97   - int (*encode_addr)(struct scsi_cmnd *, u16 *, struct _fc_channel *, fcp_cmnd *);
98   - fcp_cmnd *scsi_que;
99   - char scsi_name[4];
100   - fcp_cmnd **cmd_slots;
101   - int channels;
102   - int targets;
103   - long *ages;
104   - struct scsi_cmnd *rst_pkt;
105   - fcp_posmap *posmap;
106   - /* LOGIN stuff */
107   - fcp_cmnd *login;
108   - void *ls;
109   -} fc_channel;
110   -
111   -extern fc_channel *fc_channels;
112   -
113   -#define FC_STATE_UNINITED 0
114   -#define FC_STATE_ONLINE 1
115   -#define FC_STATE_OFFLINE 2
116   -#define FC_STATE_RESETING 3
117   -#define FC_STATE_FPORT_OK 4
118   -#define FC_STATE_MAYBEOFFLINE 5
119   -
120   -#define FC_STATUS_OK 0
121   -#define FC_STATUS_P_RJT 2
122   -#define FC_STATUS_F_RJT 3
123   -#define FC_STATUS_P_BSY 4
124   -#define FC_STATUS_F_BSY 5
125   -#define FC_STATUS_ERR_OFFLINE 0x11
126   -#define FC_STATUS_TIMEOUT 0x12
127   -#define FC_STATUS_ERR_OVERRUN 0x13
128   -#define FC_STATUS_POINTTOPOINT 0x15
129   -#define FC_STATUS_AL 0x16
130   -#define FC_STATUS_UNKNOWN_CQ_TYPE 0x20
131   -#define FC_STATUS_BAD_SEG_CNT 0x21
132   -#define FC_STATUS_MAX_XCHG_EXCEEDED 0x22
133   -#define FC_STATUS_BAD_XID 0x23
134   -#define FC_STATUS_XCHG_BUSY 0x24
135   -#define FC_STATUS_BAD_POOL_ID 0x25
136   -#define FC_STATUS_INSUFFICIENT_CQES 0x26
137   -#define FC_STATUS_ALLOC_FAIL 0x27
138   -#define FC_STATUS_BAD_SID 0x28
139   -#define FC_STATUS_NO_SEQ_INIT 0x29
140   -#define FC_STATUS_TIMED_OUT -1
141   -#define FC_STATUS_BAD_RSP -2
142   -
143   -void fcp_queue_empty(fc_channel *);
144   -int fcp_init(fc_channel *);
145   -void fcp_release(fc_channel *fc_chain, int count);
146   -void fcp_receive_solicited(fc_channel *, int, int, int, fc_hdr *);
147   -void fcp_state_change(fc_channel *, int);
148   -int fc_do_plogi(fc_channel *, unsigned char, fc_wwn *, fc_wwn *);
149   -int fc_do_prli(fc_channel *, unsigned char);
150   -
151   -#define for_each_fc_channel(fc) \
152   - for (fc = fc_channels; fc; fc = fc->next)
153   -
154   -#define for_each_online_fc_channel(fc) \
155   - for_each_fc_channel(fc) \
156   - if (fc->state == FC_STATE_ONLINE)
157   -
158   -int fcp_scsi_queuecommand(struct scsi_cmnd *,
159   - void (* done) (struct scsi_cmnd *));
160   -int fcp_scsi_abort(struct scsi_cmnd *);
161   -int fcp_scsi_dev_reset(struct scsi_cmnd *);
162   -int fcp_scsi_host_reset(struct scsi_cmnd *);
163   -
164   -#endif /* !(_FCP_SCSI_H) */
drivers/fc4/soc.c
1   -/* soc.c: Sparc SUNW,soc (Serial Optical Channel) Fibre Channel Sbus adapter support.
2   - *
3   - * Copyright (C) 1996,1997,1999 Jakub Jelinek (jj@ultra.linux.cz)
4   - * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz)
5   - *
6   - * Sources:
7   - * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
8   - * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
9   - *
10   - * Supported hardware:
11   - * Tested on SOC sbus card bought with SS1000 in Linux running on SS5 and Ultra1.
12   - * For SOC sbus cards, you have to make sure your FCode is 1.52 or later.
13   - * If you have older FCode, you should try to upgrade or get SOC microcode from Sun
14   - * (the microcode is present in Solaris soc driver as well). In that case you need
15   - * to #define HAVE_SOC_UCODE and format the microcode into soc_asm.c. For the exact
16   - * format mail me and I will tell you. I cannot offer you the actual microcode though,
17   - * unless Sun confirms they don't mind.
18   - */
19   -
20   -static char *version =
21   - "soc.c:v1.3 9/Feb/99 Jakub Jelinek (jj@ultra.linux.cz), Jirka Hanika (geo@ff.cuni.cz)\n";
22   -
23   -#include <linux/module.h>
24   -#include <linux/kernel.h>
25   -#include <linux/types.h>
26   -#include <linux/fcntl.h>
27   -#include <linux/interrupt.h>
28   -#include <linux/ptrace.h>
29   -#include <linux/ioport.h>
30   -#include <linux/in.h>
31   -#include <linux/slab.h>
32   -#include <linux/string.h>
33   -#include <linux/init.h>
34   -#include <linux/bitops.h>
35   -#include <asm/io.h>
36   -#include <asm/dma.h>
37   -#include <linux/errno.h>
38   -#include <asm/byteorder.h>
39   -
40   -#include <asm/openprom.h>
41   -#include <asm/oplib.h>
42   -#include <asm/pgtable.h>
43   -#include <asm/irq.h>
44   -
45   -/* #define SOCDEBUG */
46   -/* #define HAVE_SOC_UCODE */
47   -
48   -#include "fcp_impl.h"
49   -#include "soc.h"
50   -#ifdef HAVE_SOC_UCODE
51   -#include "soc_asm.h"
52   -#endif
53   -
54   -#define soc_printk printk ("soc%d: ", s->soc_no); printk
55   -
56   -#ifdef SOCDEBUG
57   -#define SOD(x) soc_printk x;
58   -#else
59   -#define SOD(x)
60   -#endif
61   -
62   -#define for_each_soc(s) for (s = socs; s; s = s->next)
63   -struct soc *socs = NULL;
64   -
65   -static inline void soc_disable(struct soc *s)
66   -{
67   - sbus_writel(0, s->regs + IMASK);
68   - sbus_writel(SOC_CMD_SOFT_RESET, s->regs + CMD);
69   -}
70   -
71   -static inline void soc_enable(struct soc *s)
72   -{
73   - SOD(("enable %08x\n", s->cfg))
74   - sbus_writel(0, s->regs + SAE);
75   - sbus_writel(s->cfg, s->regs + CFG);
76   - sbus_writel(SOC_CMD_RSP_QALL, s->regs + CMD);
77   - SOC_SETIMASK(s, SOC_IMASK_RSP_QALL | SOC_IMASK_SAE);
78   - SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMAK)));
79   -}
80   -
81   -static void soc_reset(fc_channel *fc)
82   -{
83   - soc_port *port = (soc_port *)fc;
84   - struct soc *s = port->s;
85   -
86   - /* FIXME */
87   - soc_disable(s);
88   - s->req[0].seqno = 1;
89   - s->req[1].seqno = 1;
90   - s->rsp[0].seqno = 1;
91   - s->rsp[1].seqno = 1;
92   - s->req[0].in = 0;
93   - s->req[1].in = 0;
94   - s->rsp[0].in = 0;
95   - s->rsp[1].in = 0;
96   - s->req[0].out = 0;
97   - s->req[1].out = 0;
98   - s->rsp[0].out = 0;
99   - s->rsp[1].out = 0;
100   -
101   - /* FIXME */
102   - soc_enable(s);
103   -}
104   -
105   -static inline void soc_solicited (struct soc *s)
106   -{
107   - fc_hdr fchdr;
108   - soc_rsp __iomem *hwrsp;
109   - soc_cq_rsp *sw_cq;
110   - int token;
111   - int status;
112   - fc_channel *fc;
113   -
114   - sw_cq = &s->rsp[SOC_SOLICITED_RSP_Q];
115   -
116   - if (sw_cq->pool == NULL)
117   - sw_cq->pool = (soc_req __iomem *)
118   - (s->xram + xram_get_32low ((xram_p)&sw_cq->hw_cq->address));
119   - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
120   - SOD (("soc_solicited, %d pkts arrived\n", (sw_cq->in-sw_cq->out) & sw_cq->last))
121   - for (;;) {
122   - hwrsp = (soc_rsp __iomem *)sw_cq->pool + sw_cq->out;
123   - token = xram_get_32low ((xram_p)&hwrsp->shdr.token);
124   - status = xram_get_32low ((xram_p)&hwrsp->status);
125   - fc = (fc_channel *)(&s->port[(token >> 11) & 1]);
126   -
127   - if (status == SOC_OK) {
128   - fcp_receive_solicited(fc, token >> 12,
129   - token & ((1 << 11) - 1),
130   - FC_STATUS_OK, NULL);
131   - } else {
132   - xram_copy_from(&fchdr, (xram_p)&hwrsp->fchdr, sizeof(fchdr));
133   - /* We have intentionally defined FC_STATUS_* constants
134   - * to match SOC_* constants, otherwise we'd have to
135   - * translate status.
136   - */
137   - fcp_receive_solicited(fc, token >> 12,
138   - token & ((1 << 11) - 1),
139   - status, &fchdr);
140   - }
141   -
142   - if (++sw_cq->out > sw_cq->last) {
143   - sw_cq->seqno++;
144   - sw_cq->out = 0;
145   - }
146   -
147   - if (sw_cq->out == sw_cq->in) {
148   - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
149   - if (sw_cq->out == sw_cq->in) {
150   - /* Tell the hardware about it */
151   - sbus_writel((sw_cq->out << 24) |
152   - (SOC_CMD_RSP_QALL &
153   - ~(SOC_CMD_RSP_Q0 << SOC_SOLICITED_RSP_Q)),
154   - s->regs + CMD);
155   -
156   - /* Read it, so that we're sure it has been updated */
157   - sbus_readl(s->regs + CMD);
158   - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
159   - if (sw_cq->out == sw_cq->in)
160   - break;
161   - }
162   - }
163   - }
164   -}
165   -
166   -static inline void soc_request (struct soc *s, u32 cmd)
167   -{
168   - SOC_SETIMASK(s, s->imask & ~(cmd & SOC_CMD_REQ_QALL));
169   - SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK)));
170   -
171   - SOD(("Queues available %08x OUT %X %X\n", cmd,
172   - xram_get_8((xram_p)&s->req[0].hw_cq->out),
173   - xram_get_8((xram_p)&s->req[0].hw_cq->out)))
174   - if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) {
175   - fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port]));
176   - if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out))
177   - fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
178   - } else {
179   - fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
180   - }
181   - if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE)
182   - s->curr_port ^= 1;
183   -}
184   -
185   -static inline void soc_unsolicited (struct soc *s)
186   -{
187   - soc_rsp __iomem *hwrsp, *hwrspc;
188   - soc_cq_rsp *sw_cq;
189   - int count;
190   - int status;
191   - int flags;
192   - fc_channel *fc;
193   -
194   - sw_cq = &s->rsp[SOC_UNSOLICITED_RSP_Q];
195   - if (sw_cq->pool == NULL)
196   - sw_cq->pool = (soc_req __iomem *)
197   - (s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address)));
198   -
199   - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
200   - SOD (("soc_unsolicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last))
201   - while (sw_cq->in != sw_cq->out) {
202   - /* ...real work per entry here... */
203   - hwrsp = (soc_rsp __iomem *)sw_cq->pool + sw_cq->out;
204   -
205   - hwrspc = NULL;
206   - flags = xram_get_16 ((xram_p)&hwrsp->shdr.flags);
207   - count = xram_get_8 ((xram_p)&hwrsp->count);
208   - fc = (fc_channel *)&s->port[flags & SOC_PORT_B];
209   - SOD(("FC %08lx fcp_state_change %08lx\n",
210   - (long)fc, (long)fc->fcp_state_change))
211   -
212   - if (count != 1) {
213   - /* Ugh, continuation entries */
214   - u8 in;
215   -
216   - if (count != 2) {
217   - printk("%s: Too many continuations entries %d\n",
218   - fc->name, count);
219   - goto update_out;
220   - }
221   -
222   - in = sw_cq->in;
223   - if (in < sw_cq->out) in += sw_cq->last + 1;
224   - if (in < sw_cq->out + 2) {
225   - /* Ask the hardware if they haven't arrived yet. */
226   - sbus_writel((sw_cq->out << 24) |
227   - (SOC_CMD_RSP_QALL &
228   - ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)),
229   - s->regs + CMD);
230   -
231   - /* Read it, so that we're sure it has been updated */
232   - sbus_readl(s->regs + CMD);
233   - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
234   - in = sw_cq->in;
235   - if (in < sw_cq->out)
236   - in += sw_cq->last + 1;
237   - if (in < sw_cq->out + 2) /* Nothing came, let us wait */
238   - return;
239   - }
240   - if (sw_cq->out == sw_cq->last)
241   - hwrspc = (soc_rsp __iomem *)sw_cq->pool;
242   - else
243   - hwrspc = hwrsp + 1;
244   - }
245   -
246   - switch (flags & ~SOC_PORT_B) {
247   - case SOC_STATUS:
248   - status = xram_get_32low ((xram_p)&hwrsp->status);
249   - switch (status) {
250   - case SOC_ONLINE:
251   - SOD(("State change to ONLINE\n"));
252   - fcp_state_change(fc, FC_STATE_ONLINE);
253   - break;
254   - case SOC_OFFLINE:
255   - SOD(("State change to OFFLINE\n"));
256   - fcp_state_change(fc, FC_STATE_OFFLINE);
257   - break;
258   - default:
259   - printk ("%s: Unknown STATUS no %d\n",
260   - fc->name, status);
261   - break;
262   - }
263   - break;
264   - case (SOC_UNSOLICITED|SOC_FC_HDR):
265   - {
266   - int r_ctl = xram_get_8 ((xram_p)&hwrsp->fchdr);
267   - unsigned len;
268   - char buf[64];
269   -
270   - if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) {
271   - len = xram_get_32 ((xram_p)&hwrsp->shdr.bytecnt);
272   - if (len < 4 || !hwrspc) {
273   - printk ("%s: Invalid R_CTL %02x "
274   - "continuation entries\n",
275   - fc->name, r_ctl);
276   - } else {
277   - if (len > 60)
278   - len = 60;
279   - xram_copy_from (buf, (xram_p)hwrspc,
280   - (len + 3) & ~3);
281   - if (*(u32 *)buf == LS_DISPLAY) {
282   - int i;
283   -
284   - for (i = 4; i < len; i++)
285   - if (buf[i] == '\n')
286   - buf[i] = ' ';
287   - buf[len] = 0;
288   - printk ("%s message: %s\n",
289   - fc->name, buf + 4);
290   - } else {
291   - printk ("%s: Unknown LS_CMD "
292   - "%02x\n", fc->name,
293   - buf[0]);
294   - }
295   - }
296   - } else {
297   - printk ("%s: Unsolicited R_CTL %02x "
298   - "not handled\n", fc->name, r_ctl);
299   - }
300   - }
301   - break;
302   - default:
303   - printk ("%s: Unexpected flags %08x\n", fc->name, flags);
304   - break;
305   - };
306   -update_out:
307   - if (++sw_cq->out > sw_cq->last) {
308   - sw_cq->seqno++;
309   - sw_cq->out = 0;
310   - }
311   -
312   - if (hwrspc) {
313   - if (++sw_cq->out > sw_cq->last) {
314   - sw_cq->seqno++;
315   - sw_cq->out = 0;
316   - }
317   - }
318   -
319   - if (sw_cq->out == sw_cq->in) {
320   - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
321   - if (sw_cq->out == sw_cq->in) {
322   - /* Tell the hardware about it */
323   - sbus_writel((sw_cq->out << 24) |
324   - (SOC_CMD_RSP_QALL &
325   - ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)),
326   - s->regs + CMD);
327   -
328   - /* Read it, so that we're sure it has been updated */
329   - sbus_readl(s->regs + CMD);
330   - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
331   - }
332   - }
333   - }
334   -}
335   -
336   -static irqreturn_t soc_intr(int irq, void *dev_id)
337   -{
338   - u32 cmd;
339   - unsigned long flags;
340   - register struct soc *s = (struct soc *)dev_id;
341   -
342   - spin_lock_irqsave(&s->lock, flags);
343   - cmd = sbus_readl(s->regs + CMD);
344   - for (; (cmd = SOC_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) {
345   - if (cmd & SOC_CMD_RSP_Q1) soc_unsolicited (s);
346   - if (cmd & SOC_CMD_RSP_Q0) soc_solicited (s);
347   - if (cmd & SOC_CMD_REQ_QALL) soc_request (s, cmd);
348   - }
349   - spin_unlock_irqrestore(&s->lock, flags);
350   -
351   - return IRQ_HANDLED;
352   -}
353   -
354   -#define TOKEN(proto, port, token) (((proto)<<12)|(token)|(port))
355   -
356   -static int soc_hw_enque (fc_channel *fc, fcp_cmnd *fcmd)
357   -{
358   - soc_port *port = (soc_port *)fc;
359   - struct soc *s = port->s;
360   - int qno;
361   - soc_cq_req *sw_cq;
362   - int cq_next_in;
363   - soc_req *request;
364   - fc_hdr *fch;
365   - int i;
366   -
367   - if (fcmd->proto == TYPE_SCSI_FCP)
368   - qno = 1;
369   - else
370   - qno = 0;
371   - SOD(("Putting a FCP packet type %d into hw queue %d\n", fcmd->proto, qno))
372   - if (s->imask & (SOC_IMASK_REQ_Q0 << qno)) {
373   - SOD(("EIO %08x\n", s->imask))
374   - return -EIO;
375   - }
376   - sw_cq = s->req + qno;
377   - cq_next_in = (sw_cq->in + 1) & sw_cq->last;
378   -
379   - if (cq_next_in == sw_cq->out &&
380   - cq_next_in == (sw_cq->out = xram_get_8((xram_p)&sw_cq->hw_cq->out))) {
381   - SOD(("%d IN %d OUT %d LAST %d\n", qno, sw_cq->in, sw_cq->out, sw_cq->last))
382   - SOC_SETIMASK(s, s->imask | (SOC_IMASK_REQ_Q0 << qno));
383   - SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK)));
384   - /* If queue is full, just say NO */
385   - return -EBUSY;
386   - }
387   -
388   - request = sw_cq->pool + sw_cq->in;
389   - fch = &request->fchdr;
390   -
391   - switch (fcmd->proto) {
392   - case TYPE_SCSI_FCP:
393   - request->shdr.token = TOKEN(TYPE_SCSI_FCP, port->mask, fcmd->token);
394   - request->data[0].base = fc->dma_scsi_cmd + fcmd->token * sizeof(fcp_cmd);
395   - request->data[0].count = sizeof(fcp_cmd);
396   - request->data[1].base = fc->dma_scsi_rsp + fcmd->token * fc->rsp_size;
397   - request->data[1].count = fc->rsp_size;
398   - if (fcmd->data) {
399   - request->shdr.segcnt = 3;
400   - i = fc->scsi_cmd_pool[fcmd->token].fcp_data_len;
401   - request->shdr.bytecnt = i;
402   - request->data[2].base = fcmd->data;
403   - request->data[2].count = i;
404   - request->type =
405   - (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ?
406   - SOC_CQTYPE_IO_WRITE : SOC_CQTYPE_IO_READ;
407   - } else {
408   - request->shdr.segcnt = 2;
409   - request->shdr.bytecnt = 0;
410   - request->data[2].base = 0;
411   - request->data[2].count = 0;
412   - request->type = SOC_CQTYPE_SIMPLE;
413   - }
414   - FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did);
415   - FILL_FCHDR_SID(fch, fc->sid);
416   - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP,
417   - F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
418   - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
419   - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
420   - fch->param = 0;
421   - request->shdr.flags = port->flags;
422   - request->shdr.class = 2;
423   - break;
424   -
425   - case PROTO_OFFLINE:
426   - memset (request, 0, sizeof(*request));
427   - request->shdr.token = TOKEN(PROTO_OFFLINE, port->mask, fcmd->token);
428   - request->type = SOC_CQTYPE_OFFLINE;
429   - FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did);
430   - FILL_FCHDR_SID(fch, fc->sid);
431   - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP,
432   - F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
433   - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
434   - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
435   - request->shdr.flags = port->flags;
436   - break;
437   -
438   - case PROTO_REPORT_AL_MAP:
439   - /* SOC only supports Point-to-Point topology, no FC-AL, sorry... */
440   - return -ENOSYS;
441   -
442   - default:
443   - request->shdr.token = TOKEN(fcmd->proto, port->mask, fcmd->token);
444   - request->shdr.class = 2;
445   - request->shdr.flags = port->flags;
446   - memcpy (fch, &fcmd->fch, sizeof(fc_hdr));
447   - request->data[0].count = fcmd->cmdlen;
448   - request->data[1].count = fcmd->rsplen;
449   - request->type = fcmd->class;
450   - switch (fcmd->class) {
451   - case FC_CLASS_OUTBOUND:
452   - request->data[0].base = fcmd->cmd;
453   - request->data[0].count = fcmd->cmdlen;
454   - request->type = SOC_CQTYPE_OUTBOUND;
455   - request->shdr.bytecnt = fcmd->cmdlen;
456   - request->shdr.segcnt = 1;
457   - break;
458   - case FC_CLASS_INBOUND:
459   - request->data[0].base = fcmd->rsp;
460   - request->data[0].count = fcmd->rsplen;
461   - request->type = SOC_CQTYPE_INBOUND;
462   - request->shdr.bytecnt = 0;
463   - request->shdr.segcnt = 1;
464   - break;
465   - case FC_CLASS_SIMPLE:
466   - request->data[0].base = fcmd->cmd;
467   - request->data[1].base = fcmd->rsp;
468   - request->data[0].count = fcmd->cmdlen;
469   - request->data[1].count = fcmd->rsplen;
470   - request->type = SOC_CQTYPE_SIMPLE;
471   - request->shdr.bytecnt = fcmd->cmdlen;
472   - request->shdr.segcnt = 2;
473   - break;
474   - case FC_CLASS_IO_READ:
475   - case FC_CLASS_IO_WRITE:
476   - request->data[0].base = fcmd->cmd;
477   - request->data[1].base = fcmd->rsp;
478   - request->data[0].count = fcmd->cmdlen;
479   - request->data[1].count = fcmd->rsplen;
480   - request->type =
481   - (fcmd->class == FC_CLASS_IO_READ) ?
482   - SOC_CQTYPE_IO_READ : SOC_CQTYPE_IO_WRITE;
483   - if (fcmd->data) {
484   - request->data[2].base = fcmd->data;
485   - request->data[2].count = fcmd->datalen;
486   - request->shdr.bytecnt = fcmd->datalen;
487   - request->shdr.segcnt = 3;
488   - } else {
489   - request->shdr.bytecnt = 0;
490   - request->shdr.segcnt = 2;
491   - }
492   - break;
493   - };
494   - break;
495   - };
496   -
497   - request->count = 1;
498   - request->flags = 0;
499   - request->seqno = sw_cq->seqno;
500   -
501   - /* And now tell the SOC about it */
502   -
503   - if (++sw_cq->in > sw_cq->last) {
504   - sw_cq->in = 0;
505   - sw_cq->seqno++;
506   - }
507   -
508   - SOD(("Putting %08x into cmd\n",
509   - SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno)))
510   -
511   - sbus_writel(SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno),
512   - s->regs + CMD);
513   -
514   - /* Read so that command is completed. */
515   - sbus_readl(s->regs + CMD);
516   -
517   - return 0;
518   -}
519   -
520   -static inline void soc_download_fw(struct soc *s)
521   -{
522   -#ifdef HAVE_SOC_UCODE
523   - xram_copy_to (s->xram, soc_ucode, sizeof(soc_ucode));
524   - xram_bzero (s->xram + sizeof(soc_ucode), 32768 - sizeof(soc_ucode));
525   -#endif
526   -}
527   -
528   -/* Check for what the best SBUS burst we can use happens
529   - * to be on this machine.
530   - */
531   -static inline void soc_init_bursts(struct soc *s, struct sbus_dev *sdev)
532   -{
533   - int bsizes, bsizes_more;
534   -
535   - bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff);
536   - bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff);
537   - bsizes &= bsizes_more;
538   - if ((bsizes & 0x7f) == 0x7f)
539   - s->cfg = SOC_CFG_BURST_64;
540   - else if ((bsizes & 0x3f) == 0x3f)
541   - s->cfg = SOC_CFG_BURST_32;
542   - else if ((bsizes & 0x1f) == 0x1f)
543   - s->cfg = SOC_CFG_BURST_16;
544   - else
545   - s->cfg = SOC_CFG_BURST_4;
546   -}
547   -
548   -static inline void soc_init(struct sbus_dev *sdev, int no)
549   -{
550   - unsigned char tmp[60];
551   - int propl;
552   - struct soc *s;
553   - static int version_printed = 0;
554   - soc_hw_cq cq[8];
555   - int size, i;
556   - int irq;
557   -
558   - s = kzalloc (sizeof (struct soc), GFP_KERNEL);
559   - if (s == NULL)
560   - return;
561   - spin_lock_init(&s->lock);
562   - s->soc_no = no;
563   -
564   - SOD(("socs %08lx soc_intr %08lx soc_hw_enque %08x\n",
565   - (long)socs, (long)soc_intr, (long)soc_hw_enque))
566   - if (version_printed++ == 0)
567   - printk (version);
568   -
569   - s->port[0].fc.module = THIS_MODULE;
570   - s->port[1].fc.module = THIS_MODULE;
571   -
572   - s->next = socs;
573   - socs = s;
574   - s->port[0].fc.dev = sdev;
575   - s->port[1].fc.dev = sdev;
576   - s->port[0].s = s;
577   - s->port[1].s = s;
578   -
579   - s->port[0].fc.next = &s->port[1].fc;
580   -
581   - /* World Wide Name of SOC */
582   - propl = prom_getproperty (sdev->prom_node, "soc-wwn", tmp, sizeof(tmp));
583   - if (propl != sizeof (fc_wwn)) {
584   - s->wwn.naaid = NAAID_IEEE;
585   - s->wwn.lo = 0x12345678;
586   - } else
587   - memcpy (&s->wwn, tmp, sizeof (fc_wwn));
588   -
589   - propl = prom_getproperty (sdev->prom_node, "port-wwns", tmp, sizeof(tmp));
590   - if (propl != 2 * sizeof (fc_wwn)) {
591   - s->port[0].fc.wwn_nport.naaid = NAAID_IEEE_EXT;
592   - s->port[0].fc.wwn_nport.hi = s->wwn.hi;
593   - s->port[0].fc.wwn_nport.lo = s->wwn.lo;
594   - s->port[1].fc.wwn_nport.naaid = NAAID_IEEE_EXT;
595   - s->port[1].fc.wwn_nport.nportid = 1;
596   - s->port[1].fc.wwn_nport.hi = s->wwn.hi;
597   - s->port[1].fc.wwn_nport.lo = s->wwn.lo;
598   - } else {
599   - memcpy (&s->port[0].fc.wwn_nport, tmp, sizeof (fc_wwn));
600   - memcpy (&s->port[1].fc.wwn_nport, tmp + sizeof (fc_wwn), sizeof (fc_wwn));
601   - }
602   - memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
603   - memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
604   - SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n",
605   - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
606   - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
607   - *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo))
608   -
609   - s->port[0].fc.sid = 1;
610   - s->port[1].fc.sid = 17;
611   - s->port[0].fc.did = 2;
612   - s->port[1].fc.did = 18;
613   -
614   - s->port[0].fc.reset = soc_reset;
615   - s->port[1].fc.reset = soc_reset;
616   -
617   - if (sdev->num_registers == 1) {
618   - /* Probably SunFire onboard SOC */
619   - s->xram = sbus_ioremap(&sdev->resource[0], 0,
620   - 0x10000UL, "soc xram");
621   - s->regs = sbus_ioremap(&sdev->resource[0], 0x10000UL,
622   - 0x10UL, "soc regs");
623   - } else {
624   - /* Probably SOC sbus card */
625   - s->xram = sbus_ioremap(&sdev->resource[1], 0,
626   - sdev->reg_addrs[1].reg_size, "soc xram");
627   - s->regs = sbus_ioremap(&sdev->resource[2], 0,
628   - sdev->reg_addrs[2].reg_size, "soc regs");
629   - }
630   -
631   - soc_init_bursts(s, sdev);
632   -
633   - SOD(("Disabling SOC\n"))
634   -
635   - soc_disable (s);
636   -
637   - irq = sdev->irqs[0];
638   -
639   - if (request_irq (irq, soc_intr, IRQF_SHARED, "SOC", (void *)s)) {
640   - soc_printk ("Cannot order irq %d to go\n", irq);
641   - socs = s->next;
642   - return;
643   - }
644   -
645   - SOD(("SOC uses IRQ %d\n", irq))
646   -
647   - s->port[0].fc.irq = irq;
648   - s->port[1].fc.irq = irq;
649   -
650   - sprintf (s->port[0].fc.name, "soc%d port A", no);
651   - sprintf (s->port[1].fc.name, "soc%d port B", no);
652   - s->port[0].flags = SOC_FC_HDR | SOC_PORT_A;
653   - s->port[1].flags = SOC_FC_HDR | SOC_PORT_B;
654   - s->port[1].mask = (1 << 11);
655   -
656   - s->port[0].fc.hw_enque = soc_hw_enque;
657   - s->port[1].fc.hw_enque = soc_hw_enque;
658   -
659   - soc_download_fw (s);
660   -
661   - SOD(("Downloaded firmware\n"))
662   -
663   - /* Now setup xram circular queues */
664   - memset (cq, 0, sizeof(cq));
665   -
666   - size = (SOC_CQ_REQ0_SIZE + SOC_CQ_REQ1_SIZE) * sizeof(soc_req);
667   - s->req_cpu = sbus_alloc_consistent(sdev, size, &s->req_dvma);
668   - s->req[0].pool = s->req_cpu;
669   - cq[0].address = s->req_dvma;
670   - s->req[1].pool = s->req[0].pool + SOC_CQ_REQ0_SIZE;
671   -
672   - s->req[0].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_REQ_OFFSET);
673   - s->req[1].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq));
674   - s->rsp[0].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_RSP_OFFSET);
675   - s->rsp[1].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq));
676   -
677   - cq[1].address = cq[0].address + (SOC_CQ_REQ0_SIZE * sizeof(soc_req));
678   - cq[4].address = 1;
679   - cq[5].address = 1;
680   - cq[0].last = SOC_CQ_REQ0_SIZE - 1;
681   - cq[1].last = SOC_CQ_REQ1_SIZE - 1;
682   - cq[4].last = SOC_CQ_RSP0_SIZE - 1;
683   - cq[5].last = SOC_CQ_RSP1_SIZE - 1;
684   - for (i = 0; i < 8; i++)
685   - cq[i].seqno = 1;
686   -
687   - s->req[0].last = SOC_CQ_REQ0_SIZE - 1;
688   - s->req[1].last = SOC_CQ_REQ1_SIZE - 1;
689   - s->rsp[0].last = SOC_CQ_RSP0_SIZE - 1;
690   - s->rsp[1].last = SOC_CQ_RSP1_SIZE - 1;
691   -
692   - s->req[0].seqno = 1;
693   - s->req[1].seqno = 1;
694   - s->rsp[0].seqno = 1;
695   - s->rsp[1].seqno = 1;
696   -
697   - xram_copy_to (s->xram + SOC_CQ_REQ_OFFSET, cq, sizeof(cq));
698   -
699   - /* Make our sw copy of SOC service parameters */
700   - xram_copy_from (s->serv_params, s->xram + 0x140, sizeof (s->serv_params));
701   -
702   - s->port[0].fc.common_svc = (common_svc_parm *)s->serv_params;
703   - s->port[0].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
704   - s->port[1].fc.common_svc = (common_svc_parm *)&s->serv_params;
705   - s->port[1].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
706   -
707   - soc_enable (s);
708   -
709   - SOD(("Enabled SOC\n"))
710   -}
711   -
712   -static int __init soc_probe(void)
713   -{
714   - struct sbus_bus *sbus;
715   - struct sbus_dev *sdev = NULL;
716   - struct soc *s;
717   - int cards = 0;
718   -
719   - for_each_sbus(sbus) {
720   - for_each_sbusdev(sdev, sbus) {
721   - if(!strcmp(sdev->prom_name, "SUNW,soc")) {
722   - soc_init(sdev, cards);
723   - cards++;
724   - }
725   - }
726   - }
727   - if (!cards) return -EIO;
728   -
729   - for_each_soc(s)
730   - if (s->next)
731   - s->port[1].fc.next = &s->next->port[0].fc;
732   - fcp_init (&socs->port[0].fc);
733   - return 0;
734   -}
735   -
736   -static void __exit soc_cleanup(void)
737   -{
738   - struct soc *s;
739   - int irq;
740   - struct sbus_dev *sdev;
741   -
742   - for_each_soc(s) {
743   - irq = s->port[0].fc.irq;
744   - free_irq (irq, s);
745   -
746   - fcp_release(&(s->port[0].fc), 2);
747   -
748   - sdev = s->port[0].fc.dev;
749   - if (sdev->num_registers == 1) {
750   - sbus_iounmap(s->xram, 0x10000UL);
751   - sbus_iounmap(s->regs, 0x10UL);
752   - } else {
753   - sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size);
754   - sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size);
755   - }
756   - sbus_free_consistent(sdev,
757   - (SOC_CQ_REQ0_SIZE+SOC_CQ_REQ1_SIZE)*sizeof(soc_req),
758   - s->req_cpu, s->req_dvma);
759   - }
760   -}
761   -
762   -module_init(soc_probe);
763   -module_exit(soc_cleanup);
764   -MODULE_LICENSE("GPL");
drivers/fc4/soc.h
1   -/* soc.h: Definitions for Sparc SUNW,soc Fibre Channel Sbus driver.
2   - *
3   - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
4   - */
5   -
6   -#ifndef __SOC_H
7   -#define __SOC_H
8   -
9   -#include "fc.h"
10   -#include "fcp.h"
11   -#include "fcp_impl.h"
12   -
13   -/* Hardware register offsets and constants first {{{ */
14   -#define CFG 0x00UL /* Config Register */
15   -#define SAE 0x04UL /* Slave Access Error Register */
16   -#define CMD 0x08UL /* Command and Status Register */
17   -#define IMASK 0x0cUL /* Interrupt Mask Register */
18   -
19   -/* Config Register */
20   -#define SOC_CFG_EXT_RAM_BANK_MASK 0x07000000
21   -#define SOC_CFG_EEPROM_BANK_MASK 0x00030000
22   -#define SOC_CFG_BURST64_MASK 0x00000700
23   -#define SOC_CFG_SBUS_PARITY_TEST 0x00000020
24   -#define SOC_CFG_SBUS_PARITY_CHECK 0x00000010
25   -#define SOC_CFG_SBUS_ENHANCED 0x00000008
26   -#define SOC_CFG_BURST_MASK 0x00000007
27   -/* Bursts */
28   -#define SOC_CFG_BURST_4 0x00000000
29   -#define SOC_CFG_BURST_16 0x00000004
30   -#define SOC_CFG_BURST_32 0x00000005
31   -#define SOC_CFG_BURST_64 0x00000006
32   -
33   -/* Slave Access Error Register */
34   -#define SOC_SAE_ALIGNMENT 0x00000004
35   -#define SOC_SAE_UNSUPPORTED 0x00000002
36   -#define SOC_SAE_PARITY 0x00000001
37   -
38   -/* Command & Status Register */
39   -#define SOC_CMD_RSP_QALL 0x000f0000
40   -#define SOC_CMD_RSP_Q0 0x00010000
41   -#define SOC_CMD_RSP_Q1 0x00020000
42   -#define SOC_CMD_RSP_Q2 0x00040000
43   -#define SOC_CMD_RSP_Q3 0x00080000
44   -#define SOC_CMD_REQ_QALL 0x00000f00
45   -#define SOC_CMD_REQ_Q0 0x00000100
46   -#define SOC_CMD_REQ_Q1 0x00000200
47   -#define SOC_CMD_REQ_Q2 0x00000400
48   -#define SOC_CMD_REQ_Q3 0x00000800
49   -#define SOC_CMD_SAE 0x00000080
50   -#define SOC_CMD_INTR_PENDING 0x00000008
51   -#define SOC_CMD_NON_QUEUED 0x00000004
52   -#define SOC_CMD_IDLE 0x00000002
53   -#define SOC_CMD_SOFT_RESET 0x00000001
54   -
55   -/* Interrupt Mask Register */
56   -#define SOC_IMASK_RSP_QALL 0x000f0000
57   -#define SOC_IMASK_RSP_Q0 0x00010000
58   -#define SOC_IMASK_RSP_Q1 0x00020000
59   -#define SOC_IMASK_RSP_Q2 0x00040000
60   -#define SOC_IMASK_RSP_Q3 0x00080000
61   -#define SOC_IMASK_REQ_QALL 0x00000f00
62   -#define SOC_IMASK_REQ_Q0 0x00000100
63   -#define SOC_IMASK_REQ_Q1 0x00000200
64   -#define SOC_IMASK_REQ_Q2 0x00000400
65   -#define SOC_IMASK_REQ_Q3 0x00000800
66   -#define SOC_IMASK_SAE 0x00000080
67   -#define SOC_IMASK_NON_QUEUED 0x00000004
68   -
69   -#define SOC_INTR(s, cmd) \
70   - (((cmd & SOC_CMD_RSP_QALL) | ((~cmd) & SOC_CMD_REQ_QALL)) \
71   - & s->imask)
72   -
73   -#define SOC_SETIMASK(s, i) \
74   -do { (s)->imask = (i); \
75   - sbus_writel((i), (s)->regs + IMASK); \
76   -} while(0)
77   -
78   -/* XRAM
79   - *
80   - * This is a 64KB register area. It accepts only halfword access.
81   - * That's why here are the following inline functions...
82   - */
83   -
84   -typedef void __iomem *xram_p;
85   -
86   -/* Get 32bit number from XRAM */
87   -static inline u32 xram_get_32(xram_p x)
88   -{
89   - return ((sbus_readw(x + 0x00UL) << 16) |
90   - (sbus_readw(x + 0x02UL)));
91   -}
92   -
93   -/* Like the above, but when we don't care about the high 16 bits */
94   -static inline u32 xram_get_32low(xram_p x)
95   -{
96   - return (u32) sbus_readw(x + 0x02UL);
97   -}
98   -
99   -static inline u16 xram_get_16(xram_p x)
100   -{
101   - return sbus_readw(x);
102   -}
103   -
104   -static inline u8 xram_get_8(xram_p x)
105   -{
106   - if ((unsigned long)x & 0x1UL) {
107   - x = x - 1;
108   - return (u8) sbus_readw(x);
109   - } else {
110   - return (u8) (sbus_readw(x) >> 8);
111   - }
112   -}
113   -
114   -static inline void xram_copy_from(void *p, xram_p x, int len)
115   -{
116   - for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
117   - u32 val, *p32 = p;
118   -
119   - val = ((sbus_readw(x + 0x00UL) << 16) |
120   - (sbus_readw(x + 0x02UL)));
121   - *p32++ = val;
122   - p = p32;
123   - }
124   -}
125   -
126   -static inline void xram_copy_to(xram_p x, void *p, int len)
127   -{
128   - for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
129   - u32 tmp, *p32 = p;
130   -
131   - tmp = *p32++;
132   - p = p32;
133   - sbus_writew(tmp >> 16, x + 0x00UL);
134   - sbus_writew(tmp, x + 0x02UL);
135   - }
136   -}
137   -
138   -static inline void xram_bzero(xram_p x, int len)
139   -{
140   - for (len >>= 1; len > 0; len--, x += sizeof(u16))
141   - sbus_writew(0, x);
142   -}
143   -
144   -/* Circular Queue */
145   -
146   -#define SOC_CQ_REQ_OFFSET (0x100 * sizeof(u16))
147   -#define SOC_CQ_RSP_OFFSET (0x110 * sizeof(u16))
148   -
149   -typedef struct {
150   - u32 address;
151   - u8 in;
152   - u8 out;
153   - u8 last;
154   - u8 seqno;
155   -} soc_hw_cq;
156   -
157   -#define SOC_PORT_A 0x0000 /* From/To Port A */
158   -#define SOC_PORT_B 0x0001 /* From/To Port A */
159   -#define SOC_FC_HDR 0x0002 /* Contains FC Header */
160   -#define SOC_NORSP 0x0004 /* Don't generate response nor interrupt */
161   -#define SOC_NOINT 0x0008 /* Generate response but not interrupt */
162   -#define SOC_XFERRDY 0x0010 /* Generate XFERRDY */
163   -#define SOC_IGNOREPARAM 0x0020 /* Ignore PARAM field in the FC header */
164   -#define SOC_COMPLETE 0x0040 /* Command completed */
165   -#define SOC_UNSOLICITED 0x0080 /* For request this is the packet to establish unsolicited pools, */
166   - /* for rsp this is unsolicited packet */
167   -#define SOC_STATUS 0x0100 /* State change (on/off line) */
168   -
169   -typedef struct {
170   - u32 token;
171   - u16 flags;
172   - u8 class;
173   - u8 segcnt;
174   - u32 bytecnt;
175   -} soc_hdr;
176   -
177   -typedef struct {
178   - u32 base;
179   - u32 count;
180   -} soc_data;
181   -
182   -#define SOC_CQTYPE_OUTBOUND 0x01
183   -#define SOC_CQTYPE_INBOUND 0x02
184   -#define SOC_CQTYPE_SIMPLE 0x03
185   -#define SOC_CQTYPE_IO_WRITE 0x04
186   -#define SOC_CQTYPE_IO_READ 0x05
187   -#define SOC_CQTYPE_UNSOLICITED 0x06
188   -#define SOC_CQTYPE_DIAG 0x07
189   -#define SOC_CQTYPE_OFFLINE 0x08
190   -#define SOC_CQTYPE_RESPONSE 0x10
191   -#define SOC_CQTYPE_INLINE 0x20
192   -
193   -#define SOC_CQFLAGS_CONT 0x01
194   -#define SOC_CQFLAGS_FULL 0x02
195   -#define SOC_CQFLAGS_BADHDR 0x04
196   -#define SOC_CQFLAGS_BADPKT 0x08
197   -
198   -typedef struct {
199   - soc_hdr shdr;
200   - soc_data data[3];
201   - fc_hdr fchdr;
202   - u8 count;
203   - u8 type;
204   - u8 flags;
205   - u8 seqno;
206   -} soc_req;
207   -
208   -#define SOC_OK 0
209   -#define SOC_P_RJT 2
210   -#define SOC_F_RJT 3
211   -#define SOC_P_BSY 4
212   -#define SOC_F_BSY 5
213   -#define SOC_ONLINE 0x10
214   -#define SOC_OFFLINE 0x11
215   -#define SOC_TIMEOUT 0x12
216   -#define SOC_OVERRUN 0x13
217   -#define SOC_UNKOWN_CQ_TYPE 0x20
218   -#define SOC_BAD_SEG_CNT 0x21
219   -#define SOC_MAX_XCHG_EXCEEDED 0x22
220   -#define SOC_BAD_XID 0x23
221   -#define SOC_XCHG_BUSY 0x24
222   -#define SOC_BAD_POOL_ID 0x25
223   -#define SOC_INSUFFICIENT_CQES 0x26
224   -#define SOC_ALLOC_FAIL 0x27
225   -#define SOC_BAD_SID 0x28
226   -#define SOC_NO_SEG_INIT 0x29
227   -
228   -typedef struct {
229   - soc_hdr shdr;
230   - u32 status;
231   - soc_data data;
232   - u8 xxx1[12];
233   - fc_hdr fchdr;
234   - u8 count;
235   - u8 type;
236   - u8 flags;
237   - u8 seqno;
238   -} soc_rsp;
239   -
240   -/* }}} */
241   -
242   -/* Now our software structures and constants we use to drive the beast {{{ */
243   -
244   -#define SOC_CQ_REQ0_SIZE 4
245   -#define SOC_CQ_REQ1_SIZE 64
246   -#define SOC_CQ_RSP0_SIZE 8
247   -#define SOC_CQ_RSP1_SIZE 4
248   -
249   -#define SOC_SOLICITED_RSP_Q 0
250   -#define SOC_UNSOLICITED_RSP_Q 1
251   -
252   -struct soc;
253   -
254   -typedef struct {
255   - /* This must come first */
256   - fc_channel fc;
257   - struct soc *s;
258   - u16 flags;
259   - u16 mask;
260   -} soc_port;
261   -
262   -typedef struct {
263   - soc_hw_cq __iomem *hw_cq; /* Related XRAM cq */
264   - soc_req __iomem *pool;
265   - u8 in;
266   - u8 out;
267   - u8 last;
268   - u8 seqno;
269   -} soc_cq_rsp;
270   -
271   -typedef struct {
272   - soc_hw_cq __iomem *hw_cq; /* Related XRAM cq */
273   - soc_req *pool;
274   - u8 in;
275   - u8 out;
276   - u8 last;
277   - u8 seqno;
278   -} soc_cq_req;
279   -
280   -struct soc {
281   - spinlock_t lock;
282   - soc_port port[2]; /* Every SOC has one or two FC ports */
283   - soc_cq_req req[2]; /* Request CQs */
284   - soc_cq_rsp rsp[2]; /* Response CQs */
285   - int soc_no;
286   - void __iomem *regs;
287   - xram_p xram;
288   - fc_wwn wwn;
289   - u32 imask; /* Our copy of regs->imask */
290   - u32 cfg; /* Our copy of regs->cfg */
291   - char serv_params[80];
292   - struct soc *next;
293   - int curr_port; /* Which port will have priority to fcp_queue_empty */
294   -
295   - soc_req *req_cpu;
296   - u32 req_dvma;
297   -};
298   -
299   -/* }}} */
300   -
301   -#endif /* !(__SOC_H) */
drivers/fc4/socal.c
1   -/* socal.c: Sparc SUNW,socal (SOC+) Fibre Channel Sbus adapter support.
2   - *
3   - * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
4   - *
5   - * Sources:
6   - * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
7   - * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
8   - * SOC+ Programming Guide 0.1
9   - * Fibre Channel Arbitrated Loop (FC-AL), dpANS rev. 4.5, 1995
10   - *
11   - * Supported hardware:
12   - * On-board SOC+ adapters of Ultra Enterprise servers and sun4d.
13   - */
14   -
15   -static char *version =
16   - "socal.c: SOC+ driver v1.1 9/Feb/99 Jakub Jelinek (jj@ultra.linux.cz)\n";
17   -
18   -#include <linux/module.h>
19   -#include <linux/kernel.h>
20   -#include <linux/types.h>
21   -#include <linux/fcntl.h>
22   -#include <linux/interrupt.h>
23   -#include <linux/ptrace.h>
24   -#include <linux/ioport.h>
25   -#include <linux/in.h>
26   -#include <linux/slab.h>
27   -#include <linux/string.h>
28   -#include <linux/init.h>
29   -#include <linux/bitops.h>
30   -#include <asm/system.h>
31   -#include <asm/io.h>
32   -#include <asm/dma.h>
33   -#include <linux/errno.h>
34   -#include <asm/byteorder.h>
35   -
36   -#include <asm/openprom.h>
37   -#include <asm/oplib.h>
38   -#include <asm/pgtable.h>
39   -#include <asm/irq.h>
40   -
41   -/* #define SOCALDEBUG */
42   -/* #define HAVE_SOCAL_UCODE */
43   -/* #define USE_64BIT_MODE */
44   -
45   -#include "fcp_impl.h"
46   -#include "socal.h"
47   -#ifdef HAVE_SOCAL_UCODE
48   -#include "socal_asm.h"
49   -#endif
50   -
51   -#define socal_printk printk ("socal%d: ", s->socal_no); printk
52   -
53   -#ifdef SOCALDEBUG
54   -#define SOD(x) socal_printk x;
55   -#else
56   -#define SOD(x)
57   -#endif
58   -
59   -#define for_each_socal(s) for (s = socals; s; s = s->next)
60   -struct socal *socals = NULL;
61   -
62   -static void socal_copy_from_xram(void *d, void __iomem *xram, long size)
63   -{
64   - u32 *dp = (u32 *) d;
65   - while (size) {
66   - *dp++ = sbus_readl(xram);
67   - xram += sizeof(u32);
68   - size -= sizeof(u32);
69   - }
70   -}
71   -
72   -static void socal_copy_to_xram(void __iomem *xram, void *s, long size)
73   -{
74   - u32 *sp = (u32 *) s;
75   - while (size) {
76   - u32 val = *sp++;
77   - sbus_writel(val, xram);
78   - xram += sizeof(u32);
79   - size -= sizeof(u32);
80   - }
81   -}
82   -
83   -#ifdef HAVE_SOCAL_UCODE
84   -static void socal_bzero(unsigned long xram, int size)
85   -{
86   - while (size) {
87   - sbus_writel(0, xram);
88   - xram += sizeof(u32);
89   - size -= sizeof(u32);
90   - }
91   -}
92   -#endif
93   -
94   -static inline void socal_disable(struct socal *s)
95   -{
96   - sbus_writel(0, s->regs + IMASK);
97   - sbus_writel(SOCAL_CMD_SOFT_RESET, s->regs + CMD);
98   -}
99   -
100   -static inline void socal_enable(struct socal *s)
101   -{
102   - SOD(("enable %08x\n", s->cfg))
103   - sbus_writel(0, s->regs + SAE);
104   - sbus_writel(s->cfg, s->regs + CFG);
105   - sbus_writel(SOCAL_CMD_RSP_QALL, s->regs + CMD);
106   - SOCAL_SETIMASK(s, SOCAL_IMASK_RSP_QALL | SOCAL_IMASK_SAE);
107   - SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
108   -}
109   -
110   -static void socal_reset(fc_channel *fc)
111   -{
112   - socal_port *port = (socal_port *)fc;
113   - struct socal *s = port->s;
114   -
115   - /* FIXME */
116   - socal_disable(s);
117   - s->req[0].seqno = 1;
118   - s->req[1].seqno = 1;
119   - s->rsp[0].seqno = 1;
120   - s->rsp[1].seqno = 1;
121   - s->req[0].in = 0;
122   - s->req[1].in = 0;
123   - s->rsp[0].in = 0;
124   - s->rsp[1].in = 0;
125   - s->req[0].out = 0;
126   - s->req[1].out = 0;
127   - s->rsp[0].out = 0;
128   - s->rsp[1].out = 0;
129   -
130   - /* FIXME */
131   - socal_enable(s);
132   -}
133   -
134   -static inline void socal_solicited(struct socal *s, unsigned long qno)
135   -{
136   - socal_rsp *hwrsp;
137   - socal_cq *sw_cq;
138   - int token;
139   - int status;
140   - fc_channel *fc;
141   -
142   - sw_cq = &s->rsp[qno];
143   -
144   - /* Finally an improvement against old SOC :) */
145   - sw_cq->in = sbus_readb(s->regs + RESP + qno);
146   - SOD (("socal_solicited, %d packets arrived\n",
147   - (sw_cq->in - sw_cq->out) & sw_cq->last))
148   - for (;;) {
149   - hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out;
150   - SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out))
151   -
152   -#if defined(SOCALDEBUG) && 0
153   - {
154   - u32 *u = (u32 *)hwrsp;
155   - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
156   - u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
157   - u += 8;
158   - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
159   - u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
160   - u = (u32 *)s->xram;
161   - while (u < ((u32 *)s->regs)) {
162   - if (sbus_readl(&u[0]) == 0x00003000 ||
163   - sbus_readl(&u[0]) == 0x00003801) {
164   - SOD(("Found at %04lx\n",
165   - (unsigned long)u - (unsigned long)s->xram))
166   - SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
167   - sbus_readl(&u[0]), sbus_readl(&u[1]),
168   - sbus_readl(&u[2]), sbus_readl(&u[3]),
169   - sbus_readl(&u[4]), sbus_readl(&u[5]),
170   - sbus_readl(&u[6]), sbus_readl(&u[7])))
171   - u += 8;
172   - SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
173   - sbus_readl(&u[0]), sbus_readl(&u[1]),
174   - sbus_readl(&u[2]), sbus_readl(&u[3]),
175   - sbus_readl(&u[4]), sbus_readl(&u[5]),
176   - sbus_readl(&u[6]), sbus_readl(&u[7])))
177   - u -= 8;
178   - }
179   - u++;
180   - }
181   - }
182   -#endif
183   -
184   - token = hwrsp->shdr.token;
185   - status = hwrsp->status;
186   - fc = (fc_channel *)(&s->port[(token >> 11) & 1]);
187   -
188   - SOD(("Solicited token %08x status %08x\n", token, status))
189   - if (status == SOCAL_OK) {
190   - fcp_receive_solicited(fc, token >> 12,
191   - token & ((1 << 11) - 1),
192   - FC_STATUS_OK, NULL);
193   - } else {
194   - /* We have intentionally defined FC_STATUS_* constants
195   - * to match SOCAL_* constants, otherwise we'd have to
196   - * translate status.
197   - */
198   - fcp_receive_solicited(fc, token >> 12,
199   - token & ((1 << 11) - 1), status, &hwrsp->fchdr);
200   - }
201   -
202   - if (++sw_cq->out > sw_cq->last) {
203   - sw_cq->seqno++;
204   - sw_cq->out = 0;
205   - }
206   -
207   - if (sw_cq->out == sw_cq->in) {
208   - sw_cq->in = sbus_readb(s->regs + RESP + qno);
209   - if (sw_cq->out == sw_cq->in) {
210   - /* Tell the hardware about it */
211   - sbus_writel((sw_cq->out << 24) |
212   - (SOCAL_CMD_RSP_QALL &
213   - ~(SOCAL_CMD_RSP_Q0 << qno)),
214   - s->regs + CMD);
215   -
216   - /* Read it, so that we're sure it has been updated */
217   - sbus_readl(s->regs + CMD);
218   - sw_cq->in = sbus_readb(s->regs + RESP + qno);
219   - if (sw_cq->out == sw_cq->in)
220   - break;
221   - }
222   - }
223   - }
224   -}
225   -
226   -static inline void socal_request (struct socal *s, u32 cmd)
227   -{
228   - SOCAL_SETIMASK(s, s->imask & ~(cmd & SOCAL_CMD_REQ_QALL));
229   - SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
230   -
231   - SOD(("Queues available %08x OUT %X\n", cmd, s->regs->reqpr[0]))
232   - if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) {
233   - fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port]));
234   - if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out))
235   - fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
236   - } else {
237   - fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
238   - }
239   - if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE)
240   - s->curr_port ^= 1;
241   -}
242   -
243   -static inline void socal_unsolicited (struct socal *s, unsigned long qno)
244   -{
245   - socal_rsp *hwrsp, *hwrspc;
246   - socal_cq *sw_cq;
247   - int count;
248   - int status;
249   - int flags;
250   - fc_channel *fc;
251   -
252   - sw_cq = &s->rsp[qno];
253   -
254   - sw_cq->in = sbus_readb(s->regs + RESP + qno);
255   - SOD (("socal_unsolicited, %d packets arrived, in %d\n",
256   - (sw_cq->in - sw_cq->out) & sw_cq->last, sw_cq->in))
257   - while (sw_cq->in != sw_cq->out) {
258   - /* ...real work per entry here... */
259   - hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out;
260   - SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out))
261   -
262   -#if defined(SOCALDEBUG) && 0
263   - {
264   - u32 *u = (u32 *)hwrsp;
265   - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
266   - u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
267   - u += 8;
268   - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
269   - u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
270   - }
271   -#endif
272   -
273   - hwrspc = NULL;
274   - flags = hwrsp->shdr.flags;
275   - count = hwrsp->count;
276   - fc = (fc_channel *)&s->port[flags & SOCAL_PORT_B];
277   - SOD(("FC %08lx\n", (long)fc))
278   -
279   - if (count != 1) {
280   - /* Ugh, continuation entries */
281   - u8 in;
282   -
283   - if (count != 2) {
284   - printk("%s: Too many continuations entries %d\n",
285   - fc->name, count);
286   - goto update_out;
287   - }
288   -
289   - in = sw_cq->in;
290   - if (in < sw_cq->out)
291   - in += sw_cq->last + 1;
292   - if (in < sw_cq->out + 2) {
293   - /* Ask the hardware if they haven't arrived yet. */
294   - sbus_writel((sw_cq->out << 24) |
295   - (SOCAL_CMD_RSP_QALL &
296   - ~(SOCAL_CMD_RSP_Q0 << qno)),
297   - s->regs + CMD);
298   -
299   - /* Read it, so that we're sure it has been updated */
300   - sbus_readl(s->regs + CMD);
301   - sw_cq->in = sbus_readb(s->regs + RESP + qno);
302   - in = sw_cq->in;
303   - if (in < sw_cq->out)
304   - in += sw_cq->last + 1;
305   - if (in < sw_cq->out + 2) /* Nothing came, let us wait */
306   - return;
307   - }
308   - if (sw_cq->out == sw_cq->last)
309   - hwrspc = (socal_rsp *)sw_cq->pool;
310   - else
311   - hwrspc = hwrsp + 1;
312   - }
313   -
314   - switch (flags & ~SOCAL_PORT_B) {
315   - case SOCAL_STATUS:
316   - status = hwrsp->status;
317   - switch (status) {
318   - case SOCAL_ONLINE:
319   - SOD(("State change to ONLINE\n"));
320   - fcp_state_change(fc, FC_STATE_ONLINE);
321   - break;
322   - case SOCAL_ONLINE_LOOP:
323   - SOD(("State change to ONLINE_LOOP\n"));
324   - fcp_state_change(fc, FC_STATE_ONLINE);
325   - break;
326   - case SOCAL_OFFLINE:
327   - SOD(("State change to OFFLINE\n"));
328   - fcp_state_change(fc, FC_STATE_OFFLINE);
329   - break;
330   - default:
331   - printk ("%s: Unknown STATUS no %d\n",
332   - fc->name, status);
333   - break;
334   - };
335   -
336   - break;
337   - case (SOCAL_UNSOLICITED|SOCAL_FC_HDR):
338   - {
339   - int r_ctl = *((u8 *)&hwrsp->fchdr);
340   - unsigned len;
341   -
342   - if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) {
343   - len = hwrsp->shdr.bytecnt;
344   - if (len < 4 || !hwrspc) {
345   - printk ("%s: Invalid R_CTL %02x "
346   - "continuation entries\n",
347   - fc->name, r_ctl);
348   - } else {
349   - if (len > 60)
350   - len = 60;
351   - if (*(u32 *)hwrspc == LS_DISPLAY) {
352   - int i;
353   -
354   - for (i = 4; i < len; i++)
355   - if (((u8 *)hwrspc)[i] == '\n')
356   - ((u8 *)hwrspc)[i] = ' ';
357   - ((u8 *)hwrspc)[len] = 0;
358   - printk ("%s message: %s\n",
359   - fc->name, ((u8 *)hwrspc) + 4);
360   - } else {
361   - printk ("%s: Unknown LS_CMD "
362   - "%08x\n", fc->name,
363   - *(u32 *)hwrspc);
364   - }
365   - }
366   - } else {
367   - printk ("%s: Unsolicited R_CTL %02x "
368   - "not handled\n", fc->name, r_ctl);
369   - }
370   - }
371   - break;
372   - default:
373   - printk ("%s: Unexpected flags %08x\n", fc->name, flags);
374   - break;
375   - };
376   -update_out:
377   - if (++sw_cq->out > sw_cq->last) {
378   - sw_cq->seqno++;
379   - sw_cq->out = 0;
380   - }
381   -
382   - if (hwrspc) {
383   - if (++sw_cq->out > sw_cq->last) {
384   - sw_cq->seqno++;
385   - sw_cq->out = 0;
386   - }
387   - }
388   -
389   - if (sw_cq->out == sw_cq->in) {
390   - sw_cq->in = sbus_readb(s->regs + RESP + qno);
391   - if (sw_cq->out == sw_cq->in) {
392   - /* Tell the hardware about it */
393   - sbus_writel((sw_cq->out << 24) |
394   - (SOCAL_CMD_RSP_QALL &
395   - ~(SOCAL_CMD_RSP_Q0 << qno)),
396   - s->regs + CMD);
397   -
398   - /* Read it, so that we're sure it has been updated */
399   - sbus_readl(s->regs + CMD);
400   - sw_cq->in = sbus_readb(s->regs + RESP + qno);
401   - }
402   - }
403   - }
404   -}
405   -
406   -static irqreturn_t socal_intr(int irq, void *dev_id)
407   -{
408   - u32 cmd;
409   - unsigned long flags;
410   - register struct socal *s = (struct socal *)dev_id;
411   -
412   - spin_lock_irqsave(&s->lock, flags);
413   - cmd = sbus_readl(s->regs + CMD);
414   - for (; (cmd = SOCAL_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) {
415   -#ifdef SOCALDEBUG
416   - static int cnt = 0;
417   - if (cnt++ < 50)
418   - printk("soc_intr %08x\n", cmd);
419   -#endif
420   - if (cmd & SOCAL_CMD_RSP_Q2)
421   - socal_unsolicited (s, SOCAL_UNSOLICITED_RSP_Q);
422   - if (cmd & SOCAL_CMD_RSP_Q1)
423   - socal_unsolicited (s, SOCAL_SOLICITED_BAD_RSP_Q);
424   - if (cmd & SOCAL_CMD_RSP_Q0)
425   - socal_solicited (s, SOCAL_SOLICITED_RSP_Q);
426   - if (cmd & SOCAL_CMD_REQ_QALL)
427   - socal_request (s, cmd);
428   - }
429   - spin_unlock_irqrestore(&s->lock, flags);
430   -
431   - return IRQ_HANDLED;
432   -}
433   -
434   -#define TOKEN(proto, port, token) (((proto)<<12)|(token)|(port))
435   -
436   -static int socal_hw_enque (fc_channel *fc, fcp_cmnd *fcmd)
437   -{
438   - socal_port *port = (socal_port *)fc;
439   - struct socal *s = port->s;
440   - unsigned long qno;
441   - socal_cq *sw_cq;
442   - int cq_next_in;
443   - socal_req *request;
444   - fc_hdr *fch;
445   - int i;
446   -
447   - if (fcmd->proto == TYPE_SCSI_FCP)
448   - qno = 1;
449   - else
450   - qno = 0;
451   - SOD(("Putting a FCP packet type %d into hw queue %d\n", fcmd->proto, qno))
452   - if (s->imask & (SOCAL_IMASK_REQ_Q0 << qno)) {
453   - SOD(("EIO %08x\n", s->imask))
454   - return -EIO;
455   - }
456   - sw_cq = s->req + qno;
457   - cq_next_in = (sw_cq->in + 1) & sw_cq->last;
458   -
459   - if (cq_next_in == sw_cq->out &&
460   - cq_next_in == (sw_cq->out = sbus_readb(s->regs + REQP + qno))) {
461   - SOD(("%d IN %d OUT %d LAST %d\n",
462   - qno, sw_cq->in,
463   - sw_cq->out, sw_cq->last))
464   - SOCAL_SETIMASK(s, s->imask | (SOCAL_IMASK_REQ_Q0 << qno));
465   - SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
466   -
467   - /* If queue is full, just say NO. */
468   - return -EBUSY;
469   - }
470   -
471   - request = sw_cq->pool + sw_cq->in;
472   - fch = &request->fchdr;
473   -
474   - switch (fcmd->proto) {
475   - case TYPE_SCSI_FCP:
476   - request->shdr.token = TOKEN(TYPE_SCSI_FCP, port->mask, fcmd->token);
477   - request->data[0].base = fc->dma_scsi_cmd + fcmd->token * sizeof(fcp_cmd);
478   - request->data[0].count = sizeof(fcp_cmd);
479   - request->data[1].base = fc->dma_scsi_rsp + fcmd->token * fc->rsp_size;
480   - request->data[1].count = fc->rsp_size;
481   - if (fcmd->data) {
482   - request->shdr.segcnt = 3;
483   - i = fc->scsi_cmd_pool[fcmd->token].fcp_data_len;
484   - request->shdr.bytecnt = i;
485   - request->data[2].base = fcmd->data;
486   - request->data[2].count = i;
487   - request->type = (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ?
488   - SOCAL_CQTYPE_IO_WRITE : SOCAL_CQTYPE_IO_READ;
489   - } else {
490   - request->shdr.segcnt = 2;
491   - request->shdr.bytecnt = 0;
492   - request->data[2].base = 0;
493   - request->data[2].count = 0;
494   - request->type = SOCAL_CQTYPE_SIMPLE;
495   - }
496   - FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fcmd->did);
497   - FILL_FCHDR_SID(fch, fc->sid);
498   - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
499   - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
500   - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
501   - fch->param = 0;
502   - request->shdr.flags = port->flags;
503   - request->shdr.class = fc->posmap ? 3 : 2;
504   - break;
505   -
506   - case PROTO_OFFLINE:
507   - memset (request, 0, sizeof(*request));
508   - request->shdr.token = TOKEN(PROTO_OFFLINE, port->mask, fcmd->token);
509   - request->type = SOCAL_CQTYPE_OFFLINE;
510   - FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fcmd->did);
511   - FILL_FCHDR_SID(fch, fc->sid);
512   - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
513   - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
514   - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
515   - request->shdr.flags = port->flags;
516   - break;
517   -
518   - case PROTO_REPORT_AL_MAP:
519   - memset (request, 0, sizeof(*request));
520   - request->shdr.token = TOKEN(PROTO_REPORT_AL_MAP, port->mask, fcmd->token);
521   - request->type = SOCAL_CQTYPE_REPORT_MAP;
522   - request->shdr.flags = port->flags;
523   - request->shdr.segcnt = 1;
524   - request->shdr.bytecnt = sizeof(fc_al_posmap);
525   - request->data[0].base = fcmd->cmd;
526   - request->data[0].count = sizeof(fc_al_posmap);
527   - break;
528   -
529   - default:
530   - request->shdr.token = TOKEN(fcmd->proto, port->mask, fcmd->token);
531   - request->shdr.class = fc->posmap ? 3 : 2;
532   - request->shdr.flags = port->flags;
533   - memcpy (fch, &fcmd->fch, sizeof(fc_hdr));
534   - request->data[0].count = fcmd->cmdlen;
535   - request->data[1].count = fcmd->rsplen;
536   - request->type = fcmd->class;
537   - switch (fcmd->class) {
538   - case FC_CLASS_OUTBOUND:
539   - request->data[0].base = fcmd->cmd;
540   - request->data[0].count = fcmd->cmdlen;
541   - request->type = SOCAL_CQTYPE_OUTBOUND;
542   - request->shdr.bytecnt = fcmd->cmdlen;
543   - request->shdr.segcnt = 1;
544   - break;
545   - case FC_CLASS_INBOUND:
546   - request->data[0].base = fcmd->rsp;
547   - request->data[0].count = fcmd->rsplen;
548   - request->type = SOCAL_CQTYPE_INBOUND;
549   - request->shdr.bytecnt = 0;
550   - request->shdr.segcnt = 1;
551   - break;
552   - case FC_CLASS_SIMPLE:
553   - request->data[0].base = fcmd->cmd;
554   - request->data[1].base = fcmd->rsp;
555   - request->data[0].count = fcmd->cmdlen;
556   - request->data[1].count = fcmd->rsplen;
557   - request->type = SOCAL_CQTYPE_SIMPLE;
558   - request->shdr.bytecnt = fcmd->cmdlen;
559   - request->shdr.segcnt = 2;
560   - break;
561   - case FC_CLASS_IO_READ:
562   - case FC_CLASS_IO_WRITE:
563   - request->data[0].base = fcmd->cmd;
564   - request->data[1].base = fcmd->rsp;
565   - request->data[0].count = fcmd->cmdlen;
566   - request->data[1].count = fcmd->rsplen;
567   - request->type = (fcmd->class == FC_CLASS_IO_READ) ? SOCAL_CQTYPE_IO_READ : SOCAL_CQTYPE_IO_WRITE;
568   - if (fcmd->data) {
569   - request->data[2].base = fcmd->data;
570   - request->data[2].count = fcmd->datalen;
571   - request->shdr.bytecnt = fcmd->datalen;
572   - request->shdr.segcnt = 3;
573   - } else {
574   - request->shdr.bytecnt = 0;
575   - request->shdr.segcnt = 2;
576   - }
577   - break;
578   - }
579   - break;
580   - }
581   -
582   - request->count = 1;
583   - request->flags = 0;
584   - request->seqno = sw_cq->seqno;
585   -
586   - SOD(("queueing token %08x\n", request->shdr.token))
587   -
588   - /* And now tell the SOCAL about it */
589   -
590   - if (++sw_cq->in > sw_cq->last) {
591   - sw_cq->in = 0;
592   - sw_cq->seqno++;
593   - }
594   -
595   - SOD(("Putting %08x into cmd\n", SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno)))
596   -
597   - sbus_writel(SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno),
598   - s->regs + CMD);
599   -
600   - /* Read so that command is completed */
601   - sbus_readl(s->regs + CMD);
602   -
603   - return 0;
604   -}
605   -
606   -static inline void socal_download_fw(struct socal *s)
607   -{
608   -#ifdef HAVE_SOCAL_UCODE
609   - SOD(("Loading %ld bytes from %p to %p\n", sizeof(socal_ucode), socal_ucode, s->xram))
610   - socal_copy_to_xram(s->xram, socal_ucode, sizeof(socal_ucode));
611   - SOD(("Clearing the rest of memory\n"))
612   - socal_bzero (s->xram + sizeof(socal_ucode), 65536 - sizeof(socal_ucode));
613   - SOD(("Done\n"))
614   -#endif
615   -}
616   -
617   -/* Check for what the best SBUS burst we can use happens
618   - * to be on this machine.
619   - */
620   -static inline void socal_init_bursts(struct socal *s, struct sbus_dev *sdev)
621   -{
622   - int bsizes, bsizes_more;
623   - u32 cfg;
624   -
625   - bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff);
626   - bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff);
627   - bsizes &= bsizes_more;
628   -#ifdef USE_64BIT_MODE
629   -#ifdef __sparc_v9__
630   - mmu_set_sbus64(sdev, bsizes >> 16);
631   -#endif
632   -#endif
633   - if ((bsizes & 0x7f) == 0x7f)
634   - cfg = SOCAL_CFG_BURST_64;
635   - else if ((bsizes & 0x3f) == 0x3f)
636   - cfg = SOCAL_CFG_BURST_32;
637   - else if ((bsizes & 0x1f) == 0x1f)
638   - cfg = SOCAL_CFG_BURST_16;
639   - else
640   - cfg = SOCAL_CFG_BURST_4;
641   -#ifdef USE_64BIT_MODE
642   -#ifdef __sparc_v9__
643   - /* What is BURST_128? -jj */
644   - if ((bsizes & 0x780000) == 0x780000)
645   - cfg |= (SOCAL_CFG_BURST_64 << 8) | SOCAL_CFG_SBUS_ENHANCED;
646   - else if ((bsizes & 0x380000) == 0x380000)
647   - cfg |= (SOCAL_CFG_BURST_32 << 8) | SOCAL_CFG_SBUS_ENHANCED;
648   - else if ((bsizes & 0x180000) == 0x180000)
649   - cfg |= (SOCAL_CFG_BURST_16 << 8) | SOCAL_CFG_SBUS_ENHANCED;
650   - else
651   - cfg |= (SOCAL_CFG_BURST_8 << 8) | SOCAL_CFG_SBUS_ENHANCED;
652   -#endif
653   -#endif
654   - s->cfg = cfg;
655   -}
656   -
657   -static inline void socal_init(struct sbus_dev *sdev, int no)
658   -{
659   - unsigned char tmp[60];
660   - int propl;
661   - struct socal *s;
662   - static unsigned version_printed = 0;
663   - socal_hw_cq cq[8];
664   - int size, i;
665   - int irq, node;
666   -
667   - s = kzalloc (sizeof (struct socal), GFP_KERNEL);
668   - if (!s) return;
669   - spin_lock_init(&s->lock);
670   - s->socal_no = no;
671   -
672   - SOD(("socals %08lx socal_intr %08lx socal_hw_enque %08lx\n",
673   - (long)socals, (long)socal_intr, (long)socal_hw_enque))
674   - if (version_printed++ == 0)
675   - printk (version);
676   -
677   - s->port[0].fc.module = THIS_MODULE;
678   - s->port[1].fc.module = THIS_MODULE;
679   -
680   - s->next = socals;
681   - socals = s;
682   - s->port[0].fc.dev = sdev;
683   - s->port[1].fc.dev = sdev;
684   - s->port[0].s = s;
685   - s->port[1].s = s;
686   -
687   - s->port[0].fc.next = &s->port[1].fc;
688   -
689   - /* World Wide Name of SOCAL */
690   - propl = prom_getproperty (sdev->prom_node, "wwn", tmp, sizeof(tmp));
691   - if (propl != sizeof (fc_wwn)) {
692   - s->wwn.naaid = NAAID_IEEE_REG;
693   - s->wwn.nportid = 0x123;
694   - s->wwn.hi = 0x1234;
695   - s->wwn.lo = 0x12345678;
696   - } else
697   - memcpy (&s->wwn, tmp, sizeof (fc_wwn));
698   -
699   - memcpy (&s->port[0].fc.wwn_nport, &s->wwn, sizeof (fc_wwn));
700   - s->port[0].fc.wwn_nport.lo++;
701   - memcpy (&s->port[1].fc.wwn_nport, &s->wwn, sizeof (fc_wwn));
702   - s->port[1].fc.wwn_nport.lo+=2;
703   -
704   - node = prom_getchild (sdev->prom_node);
705   - while (node && (node = prom_searchsiblings (node, "sf"))) {
706   - int port;
707   -
708   - port = prom_getintdefault(node, "port#", -1);
709   - switch (port) {
710   - case 0:
711   - case 1:
712   - if (prom_getproplen(node, "port-wwn") == sizeof (fc_wwn))
713   - prom_getproperty (node, "port-wwn",
714   - (char *)&s->port[port].fc.wwn_nport,
715   - sizeof (fc_wwn));
716   - break;
717   - default:
718   - break;
719   - };
720   -
721   - node = prom_getsibling(node);
722   - }
723   -
724   - memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
725   - memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
726   - SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n",
727   - *(u32 *)&s->port[0].fc.wwn_node, s->port[0].fc.wwn_node.lo,
728   - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
729   - *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo))
730   -
731   - s->port[0].fc.sid = 1;
732   - s->port[1].fc.sid = 17;
733   - s->port[0].fc.did = 2;
734   - s->port[1].fc.did = 18;
735   -
736   - s->port[0].fc.reset = socal_reset;
737   - s->port[1].fc.reset = socal_reset;
738   -
739   - if (sdev->num_registers == 1) {
740   - s->eeprom = sbus_ioremap(&sdev->resource[0], 0,
741   - sdev->reg_addrs[0].reg_size, "socal xram");
742   - if (sdev->reg_addrs[0].reg_size > 0x20000)
743   - s->xram = s->eeprom + 0x10000UL;
744   - else
745   - s->xram = s->eeprom;
746   - s->regs = (s->xram + 0x10000UL);
747   - } else {
748   - /* E.g. starfire presents 3 registers for SOCAL */
749   - s->xram = sbus_ioremap(&sdev->resource[1], 0,
750   - sdev->reg_addrs[1].reg_size, "socal xram");
751   - s->regs = sbus_ioremap(&sdev->resource[2], 0,
752   - sdev->reg_addrs[2].reg_size, "socal regs");
753   - }
754   -
755   - socal_init_bursts(s, sdev);
756   -
757   - SOD(("Disabling SOCAL\n"))
758   -
759   - socal_disable (s);
760   -
761   - irq = sdev->irqs[0];
762   -
763   - if (request_irq (irq, socal_intr, IRQF_SHARED, "SOCAL", (void *)s)) {
764   - socal_printk ("Cannot order irq %d to go\n", irq);
765   - socals = s->next;
766   - return;
767   - }
768   -
769   - SOD(("SOCAL uses IRQ %d\n", irq))
770   -
771   - s->port[0].fc.irq = irq;
772   - s->port[1].fc.irq = irq;
773   -
774   - sprintf (s->port[0].fc.name, "socal%d port A", no);
775   - sprintf (s->port[1].fc.name, "socal%d port B", no);
776   - s->port[0].flags = SOCAL_FC_HDR | SOCAL_PORT_A;
777   - s->port[1].flags = SOCAL_FC_HDR | SOCAL_PORT_B;
778   - s->port[1].mask = (1 << 11);
779   -
780   - s->port[0].fc.hw_enque = socal_hw_enque;
781   - s->port[1].fc.hw_enque = socal_hw_enque;
782   -
783   - socal_download_fw (s);
784   -
785   - SOD(("Downloaded firmware\n"))
786   -
787   - /* Now setup xram circular queues */
788   - memset (cq, 0, sizeof(cq));
789   -
790   - size = (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE +
791   - SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE +
792   - SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req);
793   - s->req_cpu = sbus_alloc_consistent(sdev, size, &s->req_dvma);
794   - s->req[0].pool = s->req_cpu;
795   - cq[0].address = s->req_dvma;
796   - s->req[1].pool = s->req[0].pool + SOCAL_CQ_REQ0_SIZE;
797   - s->rsp[0].pool = s->req[1].pool + SOCAL_CQ_REQ1_SIZE;
798   - s->rsp[1].pool = s->rsp[0].pool + SOCAL_CQ_RSP0_SIZE;
799   - s->rsp[2].pool = s->rsp[1].pool + SOCAL_CQ_RSP1_SIZE;
800   -
801   - s->req[0].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_REQ_OFFSET);
802   - s->req[1].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_REQ_OFFSET + sizeof(socal_hw_cq));
803   - s->rsp[0].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET);
804   - s->rsp[1].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET + sizeof(socal_hw_cq));
805   - s->rsp[2].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET + 2 * sizeof(socal_hw_cq));
806   -
807   - cq[1].address = cq[0].address + (SOCAL_CQ_REQ0_SIZE * sizeof(socal_req));
808   - cq[4].address = cq[1].address + (SOCAL_CQ_REQ1_SIZE * sizeof(socal_req));
809   - cq[5].address = cq[4].address + (SOCAL_CQ_RSP0_SIZE * sizeof(socal_req));
810   - cq[6].address = cq[5].address + (SOCAL_CQ_RSP1_SIZE * sizeof(socal_req));
811   -
812   - cq[0].last = SOCAL_CQ_REQ0_SIZE - 1;
813   - cq[1].last = SOCAL_CQ_REQ1_SIZE - 1;
814   - cq[4].last = SOCAL_CQ_RSP0_SIZE - 1;
815   - cq[5].last = SOCAL_CQ_RSP1_SIZE - 1;
816   - cq[6].last = SOCAL_CQ_RSP2_SIZE - 1;
817   - for (i = 0; i < 8; i++)
818   - cq[i].seqno = 1;
819   -
820   - s->req[0].last = SOCAL_CQ_REQ0_SIZE - 1;
821   - s->req[1].last = SOCAL_CQ_REQ1_SIZE - 1;
822   - s->rsp[0].last = SOCAL_CQ_RSP0_SIZE - 1;
823   - s->rsp[1].last = SOCAL_CQ_RSP1_SIZE - 1;
824   - s->rsp[2].last = SOCAL_CQ_RSP2_SIZE - 1;
825   -
826   - s->req[0].seqno = 1;
827   - s->req[1].seqno = 1;
828   - s->rsp[0].seqno = 1;
829   - s->rsp[1].seqno = 1;
830   - s->rsp[2].seqno = 1;
831   -
832   - socal_copy_to_xram(s->xram + SOCAL_CQ_REQ_OFFSET, cq, sizeof(cq));
833   -
834   - SOD(("Setting up params\n"))
835   -
836   - /* Make our sw copy of SOCAL service parameters */
837   - socal_copy_from_xram(s->serv_params, s->xram + 0x280, sizeof (s->serv_params));
838   -
839   - s->port[0].fc.common_svc = (common_svc_parm *)s->serv_params;
840   - s->port[0].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
841   - s->port[1].fc.common_svc = (common_svc_parm *)&s->serv_params;
842   - s->port[1].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
843   -
844   - socal_enable (s);
845   -
846   - SOD(("Enabled SOCAL\n"))
847   -}
848   -
849   -static int __init socal_probe(void)
850   -{
851   - struct sbus_bus *sbus;
852   - struct sbus_dev *sdev = NULL;
853   - struct socal *s;
854   - int cards = 0;
855   -
856   - for_each_sbus(sbus) {
857   - for_each_sbusdev(sdev, sbus) {
858   - if(!strcmp(sdev->prom_name, "SUNW,socal")) {
859   - socal_init(sdev, cards);
860   - cards++;
861   - }
862   - }
863   - }
864   - if (!cards)
865   - return -EIO;
866   -
867   - for_each_socal(s)
868   - if (s->next)
869   - s->port[1].fc.next = &s->next->port[0].fc;
870   -
871   - fcp_init (&socals->port[0].fc);
872   - return 0;
873   -}
874   -
875   -static void __exit socal_cleanup(void)
876   -{
877   - struct socal *s;
878   - int irq;
879   - struct sbus_dev *sdev;
880   -
881   - for_each_socal(s) {
882   - irq = s->port[0].fc.irq;
883   - free_irq (irq, s);
884   -
885   - fcp_release(&(s->port[0].fc), 2);
886   -
887   - sdev = s->port[0].fc.dev;
888   - if (sdev->num_registers == 1) {
889   - sbus_iounmap(s->eeprom, sdev->reg_addrs[0].reg_size);
890   - } else {
891   - sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size);
892   - sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size);
893   - }
894   - sbus_free_consistent(sdev,
895   - (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE +
896   - SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE +
897   - SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req),
898   - s->req_cpu, s->req_dvma);
899   - }
900   -}
901   -
902   -module_init(socal_probe);
903   -module_exit(socal_cleanup);
904   -MODULE_LICENSE("GPL");
drivers/fc4/socal.h
1   -/* socal.h: Definitions for Sparc SUNW,socal (SOC+) Fibre Channel Sbus driver.
2   - *
3   - * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
4   - */
5   -
6   -#ifndef __SOCAL_H
7   -#define __SOCAL_H
8   -
9   -#include "fc.h"
10   -#include "fcp.h"
11   -#include "fcp_impl.h"
12   -
13   -/* Hardware register offsets and constants first {{{ */
14   -#define CFG 0x00UL
15   -#define SAE 0x04UL
16   -#define CMD 0x08UL
17   -#define IMASK 0x0cUL
18   -#define REQP 0x10UL
19   -#define RESP 0x14UL
20   -
21   -/* Config Register */
22   -#define SOCAL_CFG_EXT_RAM_BANK_MASK 0x07000000
23   -#define SOCAL_CFG_EEPROM_BANK_MASK 0x00030000
24   -#define SOCAL_CFG_BURST64_MASK 0x00000700
25   -#define SOCAL_CFG_SBUS_PARITY_TEST 0x00000020
26   -#define SOCAL_CFG_SBUS_PARITY_CHECK 0x00000010
27   -#define SOCAL_CFG_SBUS_ENHANCED 0x00000008
28   -#define SOCAL_CFG_BURST_MASK 0x00000007
29   -/* Bursts */
30   -#define SOCAL_CFG_BURST_4 0x00000000
31   -#define SOCAL_CFG_BURST_8 0x00000003
32   -#define SOCAL_CFG_BURST_16 0x00000004
33   -#define SOCAL_CFG_BURST_32 0x00000005
34   -#define SOCAL_CFG_BURST_64 0x00000006
35   -#define SOCAL_CFG_BURST_128 0x00000007
36   -
37   -/* Slave Access Error Register */
38   -#define SOCAL_SAE_ALIGNMENT 0x00000004
39   -#define SOCAL_SAE_UNSUPPORTED 0x00000002
40   -#define SOCAL_SAE_PARITY 0x00000001
41   -
42   -/* Command & Status Register */
43   -#define SOCAL_CMD_RSP_QALL 0x000f0000
44   -#define SOCAL_CMD_RSP_Q0 0x00010000
45   -#define SOCAL_CMD_RSP_Q1 0x00020000
46   -#define SOCAL_CMD_RSP_Q2 0x00040000
47   -#define SOCAL_CMD_RSP_Q3 0x00080000
48   -#define SOCAL_CMD_REQ_QALL 0x00000f00
49   -#define SOCAL_CMD_REQ_Q0 0x00000100
50   -#define SOCAL_CMD_REQ_Q1 0x00000200
51   -#define SOCAL_CMD_REQ_Q2 0x00000400
52   -#define SOCAL_CMD_REQ_Q3 0x00000800
53   -#define SOCAL_CMD_SAE 0x00000080
54   -#define SOCAL_CMD_INTR_PENDING 0x00000008
55   -#define SOCAL_CMD_NON_QUEUED 0x00000004
56   -#define SOCAL_CMD_IDLE 0x00000002
57   -#define SOCAL_CMD_SOFT_RESET 0x00000001
58   -
59   -/* Interrupt Mask Register */
60   -#define SOCAL_IMASK_RSP_QALL 0x000f0000
61   -#define SOCAL_IMASK_RSP_Q0 0x00010000
62   -#define SOCAL_IMASK_RSP_Q1 0x00020000
63   -#define SOCAL_IMASK_RSP_Q2 0x00040000
64   -#define SOCAL_IMASK_RSP_Q3 0x00080000
65   -#define SOCAL_IMASK_REQ_QALL 0x00000f00
66   -#define SOCAL_IMASK_REQ_Q0 0x00000100
67   -#define SOCAL_IMASK_REQ_Q1 0x00000200
68   -#define SOCAL_IMASK_REQ_Q2 0x00000400
69   -#define SOCAL_IMASK_REQ_Q3 0x00000800
70   -#define SOCAL_IMASK_SAE 0x00000080
71   -#define SOCAL_IMASK_NON_QUEUED 0x00000004
72   -
73   -#define SOCAL_INTR(s, cmd) \
74   - (((cmd & SOCAL_CMD_RSP_QALL) | ((~cmd) & SOCAL_CMD_REQ_QALL)) \
75   - & s->imask)
76   -
77   -#define SOCAL_SETIMASK(s, i) \
78   -do { (s)->imask = (i); \
79   - sbus_writel((i), (s)->regs + IMASK); \
80   -} while (0)
81   -
82   -#define SOCAL_MAX_EXCHANGES 1024
83   -
84   -/* XRAM
85   - *
86   - * This is a 64KB register area.
87   - * From the documentation, it seems like it is finally able to cope
88   - * at least with 1,2,4 byte accesses for read and 2,4 byte accesses for write.
89   - */
90   -
91   -/* Circular Queue */
92   -
93   -#define SOCAL_CQ_REQ_OFFSET 0x200
94   -#define SOCAL_CQ_RSP_OFFSET 0x220
95   -
96   -typedef struct {
97   - u32 address;
98   - u8 in;
99   - u8 out;
100   - u8 last;
101   - u8 seqno;
102   -} socal_hw_cq;
103   -
104   -#define SOCAL_PORT_A 0x0000 /* From/To Port A */
105   -#define SOCAL_PORT_B 0x0001 /* From/To Port A */
106   -#define SOCAL_FC_HDR 0x0002 /* Contains FC Header */
107   -#define SOCAL_NORSP 0x0004 /* Don't generate response nor interrupt */
108   -#define SOCAL_NOINT 0x0008 /* Generate response but not interrupt */
109   -#define SOCAL_XFERRDY 0x0010 /* Generate XFERRDY */
110   -#define SOCAL_IGNOREPARAM 0x0020 /* Ignore PARAM field in the FC header */
111   -#define SOCAL_COMPLETE 0x0040 /* Command completed */
112   -#define SOCAL_UNSOLICITED 0x0080 /* For request this is the packet to establish unsolicited pools, */
113   - /* for rsp this is unsolicited packet */
114   -#define SOCAL_STATUS 0x0100 /* State change (on/off line) */
115   -#define SOCAL_RSP_HDR 0x0200 /* Return frame header in any case */
116   -
117   -typedef struct {
118   - u32 token;
119   - u16 flags;
120   - u8 class;
121   - u8 segcnt;
122   - u32 bytecnt;
123   -} socal_hdr;
124   -
125   -typedef struct {
126   - u32 base;
127   - u32 count;
128   -} socal_data;
129   -
130   -#define SOCAL_CQTYPE_NOP 0x00
131   -#define SOCAL_CQTYPE_OUTBOUND 0x01
132   -#define SOCAL_CQTYPE_INBOUND 0x02
133   -#define SOCAL_CQTYPE_SIMPLE 0x03
134   -#define SOCAL_CQTYPE_IO_WRITE 0x04
135   -#define SOCAL_CQTYPE_IO_READ 0x05
136   -#define SOCAL_CQTYPE_UNSOLICITED 0x06
137   -#define SOCAL_CQTYPE_BYPASS_DEV 0x06
138   -#define SOCAL_CQTYPE_DIAG 0x07
139   -#define SOCAL_CQTYPE_OFFLINE 0x08
140   -#define SOCAL_CQTYPE_ADD_POOL 0x09
141   -#define SOCAL_CQTYPE_DELETE_POOL 0x0a
142   -#define SOCAL_CQTYPE_ADD_BUFFER 0x0b
143   -#define SOCAL_CQTYPE_ADD_POOL_BUFFER 0x0c
144   -#define SOCAL_CQTYPE_REQUEST_ABORT 0x0d
145   -#define SOCAL_CQTYPE_REQUEST_LIP 0x0e
146   -#define SOCAL_CQTYPE_REPORT_MAP 0x0f
147   -#define SOCAL_CQTYPE_RESPONSE 0x10
148   -#define SOCAL_CQTYPE_INLINE 0x20
149   -
150   -#define SOCAL_CQFLAGS_CONT 0x01
151   -#define SOCAL_CQFLAGS_FULL 0x02
152   -#define SOCAL_CQFLAGS_BADHDR 0x04
153   -#define SOCAL_CQFLAGS_BADPKT 0x08
154   -
155   -typedef struct {
156   - socal_hdr shdr;
157   - socal_data data[3];
158   - fc_hdr fchdr;
159   - u8 count;
160   - u8 type;
161   - u8 flags;
162   - u8 seqno;
163   -} socal_req;
164   -
165   -#define SOCAL_OK 0
166   -#define SOCAL_P_RJT 2
167   -#define SOCAL_F_RJT 3
168   -#define SOCAL_P_BSY 4
169   -#define SOCAL_F_BSY 5
170   -#define SOCAL_ONLINE 0x10
171   -#define SOCAL_OFFLINE 0x11
172   -#define SOCAL_TIMEOUT 0x12
173   -#define SOCAL_OVERRUN 0x13
174   -#define SOCAL_ONLINE_LOOP 0x14
175   -#define SOCAL_OLD_PORT 0x15
176   -#define SOCAL_AL_PORT 0x16
177   -#define SOCAL_UNKOWN_CQ_TYPE 0x20
178   -#define SOCAL_BAD_SEG_CNT 0x21
179   -#define SOCAL_MAX_XCHG_EXCEEDED 0x22
180   -#define SOCAL_BAD_XID 0x23
181   -#define SOCAL_XCHG_BUSY 0x24
182   -#define SOCAL_BAD_POOL_ID 0x25
183   -#define SOCAL_INSUFFICIENT_CQES 0x26
184   -#define SOCAL_ALLOC_FAIL 0x27
185   -#define SOCAL_BAD_SID 0x28
186   -#define SOCAL_NO_SEG_INIT 0x29
187   -#define SOCAL_BAD_DID 0x2a
188   -#define SOCAL_ABORTED 0x30
189   -#define SOCAL_ABORT_FAILED 0x31
190   -
191   -typedef struct {
192   - socal_hdr shdr;
193   - u32 status;
194   - socal_data data;
195   - u8 xxx1[10];
196   - u16 ncmds;
197   - fc_hdr fchdr;
198   - u8 count;
199   - u8 type;
200   - u8 flags;
201   - u8 seqno;
202   -} socal_rsp;
203   -
204   -typedef struct {
205   - socal_hdr shdr;
206   - u8 xxx1[48];
207   - u8 count;
208   - u8 type;
209   - u8 flags;
210   - u8 seqno;
211   -} socal_cmdonly;
212   -
213   -#define SOCAL_DIAG_NOP 0x00
214   -#define SOCAL_DIAG_INT_LOOP 0x01
215   -#define SOCAL_DIAG_EXT_LOOP 0x02
216   -#define SOCAL_DIAG_REM_LOOP 0x03
217   -#define SOCAL_DIAG_XRAM_TEST 0x04
218   -#define SOCAL_DIAG_SOC_TEST 0x05
219   -#define SOCAL_DIAG_HCB_TEST 0x06
220   -#define SOCAL_DIAG_SOCLB_TEST 0x07
221   -#define SOCAL_DIAG_SRDSLB_TEST 0x08
222   -#define SOCAL_DIAG_EXTOE_TEST 0x09
223   -
224   -typedef struct {
225   - socal_hdr shdr;
226   - u32 cmd;
227   - u8 xxx1[44];
228   - u8 count;
229   - u8 type;
230   - u8 flags;
231   - u8 seqno;
232   -} socal_diag_req;
233   -
234   -#define SOCAL_POOL_MASK_RCTL 0x800000
235   -#define SOCAL_POOL_MASK_DID 0x700000
236   -#define SOCAL_POOL_MASK_SID 0x070000
237   -#define SOCAL_POOL_MASK_TYPE 0x008000
238   -#define SOCAL_POOL_MASK_F_CTL 0x007000
239   -#define SOCAL_POOL_MASK_SEQ_ID 0x000800
240   -#define SOCAL_POOL_MASK_D_CTL 0x000400
241   -#define SOCAL_POOL_MASK_SEQ_CNT 0x000300
242   -#define SOCAL_POOL_MASK_OX_ID 0x0000f0
243   -#define SOCAL_POOL_MASK_PARAM 0x00000f
244   -
245   -typedef struct {
246   - socal_hdr shdr;
247   - u32 pool_id;
248   - u32 header_mask;
249   - u32 buf_size;
250   - u32 entries;
251   - u8 xxx1[8];
252   - fc_hdr fchdr;
253   - u8 count;
254   - u8 type;
255   - u8 flags;
256   - u8 seqno;
257   -} socal_pool_req;
258   -
259   -/* }}} */
260   -
261   -/* Now our software structures and constants we use to drive the beast {{{ */
262   -
263   -#define SOCAL_CQ_REQ0_SIZE 4
264   -#define SOCAL_CQ_REQ1_SIZE 256
265   -#define SOCAL_CQ_RSP0_SIZE 8
266   -#define SOCAL_CQ_RSP1_SIZE 4
267   -#define SOCAL_CQ_RSP2_SIZE 4
268   -
269   -#define SOCAL_SOLICITED_RSP_Q 0
270   -#define SOCAL_SOLICITED_BAD_RSP_Q 1
271   -#define SOCAL_UNSOLICITED_RSP_Q 2
272   -
273   -struct socal;
274   -
275   -typedef struct {
276   - /* This must come first */
277   - fc_channel fc;
278   - struct socal *s;
279   - u16 flags;
280   - u16 mask;
281   -} socal_port;
282   -
283   -typedef struct {
284   - socal_hw_cq __iomem *hw_cq; /* Related XRAM cq */
285   - socal_req *pool;
286   - u8 in;
287   - u8 out;
288   - u8 last;
289   - u8 seqno;
290   -} socal_cq;
291   -
292   -struct socal {
293   - spinlock_t lock;
294   - socal_port port[2]; /* Every SOCAL has one or two FC ports */
295   - socal_cq req[4]; /* Request CQs */
296   - socal_cq rsp[4]; /* Response CQs */
297   - int socal_no;
298   - void __iomem *regs;
299   - void __iomem *xram;
300   - void __iomem *eeprom;
301   - fc_wwn wwn;
302   - u32 imask; /* Our copy of regs->imask */
303   - u32 cfg; /* Our copy of regs->cfg */
304   - char serv_params[80];
305   - struct socal *next;
306   - int curr_port; /* Which port will have priority to fcp_queue_empty */
307   -
308   - socal_req * req_cpu;
309   - u32 req_dvma;
310   -};
311   -
312   -/* }}} */
313   -
314   -#endif /* !(__SOCAL_H) */
drivers/scsi/Makefile
... ... @@ -115,7 +115,6 @@
115 115 obj-$(CONFIG_BLK_DEV_IDESCSI) += ide-scsi.o
116 116 obj-$(CONFIG_SCSI_MESH) += mesh.o
117 117 obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o
118   -obj-$(CONFIG_SCSI_PLUTO) += pluto.o
119 118 obj-$(CONFIG_SCSI_DECNCR) += NCR53C9x.o dec_esp.o
120 119 obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
121 120 obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o
... ... @@ -123,7 +122,6 @@
123 122 obj-$(CONFIG_SCSI_IMM) += imm.o
124 123 obj-$(CONFIG_JAZZ_ESP) += esp_scsi.o jazz_esp.o
125 124 obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o
126   -obj-$(CONFIG_SCSI_FCAL) += fcal.o
127 125 obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o
128 126 obj-$(CONFIG_SCSI_SNI_53C710) += 53c700.o sni_53c710.o
129 127 obj-$(CONFIG_SCSI_NSP32) += nsp32.o
drivers/scsi/fcal.c
1   -/* 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/blkdev.h>
13   -#include <linux/proc_fs.h>
14   -#include <linux/stat.h>
15   -#include <linux/init.h>
16   -#ifdef CONFIG_KMOD
17   -#include <linux/kmod.h>
18   -#endif
19   -
20   -#include <asm/irq.h>
21   -
22   -#include "scsi.h"
23   -#include <scsi/scsi_host.h>
24   -#include "../fc4/fcp_impl.h"
25   -#include "fcal.h"
26   -
27   -#include <linux/module.h>
28   -
29   -/* #define FCAL_DEBUG */
30   -
31   -#define fcal_printk printk ("FCAL %s: ", fc->name); printk
32   -
33   -#ifdef FCAL_DEBUG
34   -#define FCALD(x) fcal_printk x;
35   -#define FCALND(x) printk ("FCAL: "); printk x;
36   -#else
37   -#define FCALD(x)
38   -#define FCALND(x)
39   -#endif
40   -
41   -static unsigned char alpa2target[] = {
42   -0x7e, 0x7d, 0x7c, 0xff, 0x7b, 0xff, 0xff, 0xff, 0x7a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79,
43   -0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x77, 0x76, 0xff, 0xff, 0x75, 0xff, 0x74, 0x73, 0x72,
44   -0xff, 0xff, 0xff, 0x71, 0xff, 0x70, 0x6f, 0x6e, 0xff, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0xff,
45   -0xff, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0xff, 0xff, 0x61, 0x60, 0xff, 0x5f, 0xff, 0xff, 0xff,
46   -0xff, 0xff, 0xff, 0x5e, 0xff, 0x5d, 0x5c, 0x5b, 0xff, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0xff,
47   -0xff, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0xff, 0xff, 0x4e, 0x4d, 0xff, 0x4c, 0xff, 0xff, 0xff,
48   -0xff, 0xff, 0xff, 0x4b, 0xff, 0x4a, 0x49, 0x48, 0xff, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0xff,
49   -0xff, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0xff, 0xff, 0x3b, 0x3a, 0xff, 0x39, 0xff, 0xff, 0xff,
50   -0x38, 0x37, 0x36, 0xff, 0x35, 0xff, 0xff, 0xff, 0x34, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33,
51   -0x32, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0x30, 0xff, 0xff, 0x2f, 0xff, 0x2e, 0x2d, 0x2c,
52   -0xff, 0xff, 0xff, 0x2b, 0xff, 0x2a, 0x29, 0x28, 0xff, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0xff,
53   -0xff, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0xff, 0xff, 0x1b, 0x1a, 0xff, 0x19, 0xff, 0xff, 0xff,
54   -0xff, 0xff, 0xff, 0x18, 0xff, 0x17, 0x16, 0x15, 0xff, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0xff,
55   -0xff, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0xff, 0xff, 0x08, 0x07, 0xff, 0x06, 0xff, 0xff, 0xff,
56   -0x05, 0x04, 0x03, 0xff, 0x02, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
57   -};
58   -
59   -static unsigned char target2alpa[] = {
60   -0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
61   -0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
62   -0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
63   -0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
64   -0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
65   -0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
66   -0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
67   -0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
68   -};
69   -
70   -static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
71   -
72   -int fcal_slave_configure(struct scsi_device *device)
73   -{
74   - int depth_to_use;
75   -
76   - if (device->tagged_supported)
77   - depth_to_use = /* 254 */ 8;
78   - else
79   - depth_to_use = 2;
80   -
81   - scsi_adjust_queue_depth(device,
82   - (device->tagged_supported ?
83   - MSG_SIMPLE_TAG : 0),
84   - depth_to_use);
85   -
86   - return 0;
87   -}
88   -
89   -/* Detect all FC Arbitrated Loops attached to the machine.
90   - fc4 module has done all the work for us... */
91   -int __init fcal_detect(struct scsi_host_template *tpnt)
92   -{
93   - int nfcals = 0;
94   - fc_channel *fc;
95   - int fcalcount;
96   - int i;
97   -
98   - tpnt->proc_name = "fcal";
99   - fcalcount = 0;
100   - for_each_online_fc_channel(fc)
101   - if (fc->posmap)
102   - fcalcount++;
103   - FCALND(("%d channels online\n", fcalcount))
104   - if (!fcalcount) {
105   -#if defined(MODULE) && defined(CONFIG_FC4_SOCAL_MODULE) && defined(CONFIG_KMOD)
106   - request_module("socal");
107   -
108   - for_each_online_fc_channel(fc)
109   - if (fc->posmap)
110   - fcalcount++;
111   - if (!fcalcount)
112   -#endif
113   - return 0;
114   - }
115   - for_each_online_fc_channel(fc) {
116   - struct Scsi_Host *host;
117   - long *ages;
118   - struct fcal *fcal;
119   -
120   - if (!fc->posmap) continue;
121   -
122   - /* Strange, this is already registered to some other SCSI host, then it cannot be fcal */
123   - if (fc->scsi_name[0]) continue;
124   - memcpy (fc->scsi_name, "FCAL", 4);
125   -
126   - fc->can_queue = FCAL_CAN_QUEUE;
127   - fc->rsp_size = 64;
128   - fc->encode_addr = fcal_encode_addr;
129   -
130   - ages = kmalloc (128 * sizeof(long), GFP_KERNEL);
131   - if (!ages) continue;
132   -
133   - host = scsi_register (tpnt, sizeof (struct fcal));
134   - if (!host)
135   - {
136   - kfree(ages);
137   - continue;
138   - }
139   -
140   - if (!try_module_get(fc->module)) {
141   - kfree(ages);
142   - scsi_unregister(host);
143   - continue;
144   - }
145   -
146   - nfcals++;
147   -
148   - fcal = (struct fcal *)host->hostdata;
149   -
150   - fc->fcp_register(fc, TYPE_SCSI_FCP, 0);
151   -
152   - for (i = 0; i < fc->posmap->len; i++) {
153   - int status, target, alpa;
154   -
155   - alpa = fc->posmap->list[i];
156   - FCALD(("Sending PLOGI to %02x\n", alpa))
157   - target = alpa2target[alpa];
158   - status = fc_do_plogi(fc, alpa, fcal->node_wwn + target,
159   - fcal->nport_wwn + target);
160   - FCALD(("PLOGI returned with status %d\n", status))
161   - if (status != FC_STATUS_OK)
162   - continue;
163   - FCALD(("Sending PRLI to %02x\n", alpa))
164   - status = fc_do_prli(fc, alpa);
165   - FCALD(("PRLI returned with status %d\n", status))
166   - if (status == FC_STATUS_OK)
167   - fcal->map[target] = 1;
168   - }
169   -
170   - host->max_id = 127;
171   - host->irq = fc->irq;
172   -#ifdef __sparc_v9__
173   - host->unchecked_isa_dma = 1;
174   -#endif
175   -
176   - fc->channels = 1;
177   - fc->targets = 127;
178   - fc->ages = ages;
179   - memset (ages, 0, 128 * sizeof(long));
180   -
181   - fcal->fc = fc;
182   -
183   - FCALD(("Found FCAL\n"))
184   - }
185   - if (nfcals)
186   -#ifdef __sparc__
187   - printk ("FCAL: Total of %d Sun Enterprise Network Array (A5000 or EX500) channels found\n", nfcals);
188   -#else
189   - printk ("FCAL: Total of %d Fibre Channel Arbitrated Loops found\n", nfcals);
190   -#endif
191   - return nfcals;
192   -}
193   -
194   -int fcal_release(struct Scsi_Host *host)
195   -{
196   - struct fcal *fcal = (struct fcal *)host->hostdata;
197   - fc_channel *fc = fcal->fc;
198   -
199   - module_put(fc->module);
200   -
201   - fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
202   - FCALND((" releasing fcal.\n"));
203   - kfree (fc->ages);
204   - FCALND(("released fcal!\n"));
205   - return 0;
206   -}
207   -
208   -#undef SPRINTF
209   -#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
210   -
211   -int fcal_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout)
212   -{
213   - struct fcal *fcal;
214   - fc_channel *fc;
215   - char *pos = buffer;
216   - int i, j;
217   -
218   - if (inout) return length;
219   -
220   - fcal = (struct fcal *)host->hostdata;
221   - fc = fcal->fc;
222   -
223   -#ifdef __sparc__
224   - SPRINTF ("Sun Enterprise Network Array (A5000 or E?500) on %s PROM node %x\n", fc->name, fc->dev->prom_node);
225   -#else
226   - SPRINTF ("Fibre Channel Arbitrated Loop on %s\n", fc->name);
227   -#endif
228   - SPRINTF ("Initiator AL-PA: %02x\n", fc->sid);
229   -
230   - SPRINTF ("\nAttached devices:\n");
231   -
232   - for (i = 0; i < fc->posmap->len; i++) {
233   - unsigned char alpa = fc->posmap->list[i];
234   - unsigned char target;
235   - u32 *u1, *u2;
236   -
237   - target = alpa2target[alpa];
238   - u1 = (u32 *)&fcal->nport_wwn[target];
239   - u2 = (u32 *)&fcal->node_wwn[target];
240   - if (!u1[0] && !u1[1]) {
241   - SPRINTF (" [AL-PA: %02x] Not responded to PLOGI\n", alpa);
242   - } else if (!fcal->map[target]) {
243   - SPRINTF (" [AL-PA: %02x, Port WWN: %08x%08x, Node WWN: %08x%08x] Not responded to PRLI\n",
244   - alpa, u1[0], u1[1], u2[0], u2[1]);
245   - } else {
246   - struct scsi_device *scd;
247   - shost_for_each_device(scd, host)
248   - if (scd->id == target) {
249   - SPRINTF (" [AL-PA: %02x, Id: %02d, Port WWN: %08x%08x, Node WWN: %08x%08x] ",
250   - alpa, target, u1[0], u1[1], u2[0], u2[1]);
251   - SPRINTF ("%s ", scsi_device_type(scd->type));
252   -
253   - for (j = 0; (j < 8) && (scd->vendor[j] >= 0x20); j++)
254   - SPRINTF ("%c", scd->vendor[j]);
255   - SPRINTF (" ");
256   -
257   - for (j = 0; (j < 16) && (scd->model[j] >= 0x20); j++)
258   - SPRINTF ("%c", scd->model[j]);
259   -
260   - SPRINTF ("\n");
261   - }
262   - }
263   - }
264   - SPRINTF ("\n");
265   -
266   - *start = buffer + offset;
267   -
268   - if ((pos - buffer) < offset)
269   - return 0;
270   - else if (pos - buffer - offset < length)
271   - return pos - buffer - offset;
272   - else
273   - return length;
274   -}
275   -
276   -/*
277   - For FC-AL, we use a simple addressing: we have just one channel 0,
278   - and all AL-PAs are mapped to targets 0..0x7e
279   - */
280   -static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd)
281   -{
282   - struct fcal *f;
283   -
284   - /* 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] */
285   - if (SCpnt->cmnd[1] & 0xe0) return -EINVAL;
286   - /* FC-PLDA tells us... */
287   - memset(addr, 0, 8);
288   - f = (struct fcal *)SCpnt->device->host->hostdata;
289   - if (!f->map[SCpnt->device->id])
290   - return -EINVAL;
291   - /* Now, determine DID: It will be Native Identifier, so we zero upper
292   - 2 bytes of the 3 byte DID, lowest byte will be AL-PA */
293   - fcmd->did = target2alpa[SCpnt->device->id];
294   - FCALD(("trying DID %06x\n", fcmd->did))
295   - return 0;
296   -}
297   -
298   -static struct scsi_host_template driver_template = {
299   - .name = "Fibre Channel Arbitrated Loop",
300   - .detect = fcal_detect,
301   - .release = fcal_release,
302   - .proc_info = fcal_proc_info,
303   - .queuecommand = fcp_scsi_queuecommand,
304   - .slave_configure = fcal_slave_configure,
305   - .can_queue = FCAL_CAN_QUEUE,
306   - .this_id = -1,
307   - .sg_tablesize = 1,
308   - .cmd_per_lun = 1,
309   - .use_clustering = ENABLE_CLUSTERING,
310   - .eh_abort_handler = fcp_scsi_abort,
311   - .eh_device_reset_handler = fcp_scsi_dev_reset,
312   - .eh_host_reset_handler = fcp_scsi_host_reset,
313   -};
314   -#include "scsi_module.c"
315   -
316   -MODULE_LICENSE("GPL");
drivers/scsi/fcal.h
1   -/* fcal.h: Generic Fibre Channel Arbitrated Loop SCSI host adapter driver definitions.
2   - *
3   - * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
4   - */
5   -
6   -#ifndef _FCAL_H
7   -#define _FCAL_H
8   -
9   -#include "../fc4/fcp_impl.h"
10   -
11   -struct fcal {
12   - /* fc must be first */
13   - fc_channel *fc;
14   - unsigned char map[128];
15   - fc_wwn nport_wwn[128];
16   - fc_wwn node_wwn[128];
17   -};
18   -
19   -/* Arbitrary constant. Cannot be too large, as fc4 layer has limitations
20   - for a particular channel */
21   -#define FCAL_CAN_QUEUE 512
22   -
23   -int fcal_detect(struct scsi_host_template *);
24   -int fcal_release(struct Scsi_Host *);
25   -int fcal_slave_configure(struct scsi_device *);
26   -
27   -#endif /* !(_FCAL_H) */
drivers/scsi/pluto.c
1   -/* pluto.c: SparcSTORAGE Array SCSI host adapter driver.
2   - *
3   - * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
4   - *
5   - */
6   -
7   -#include <linux/completion.h>
8   -#include <linux/kernel.h>
9   -#include <linux/delay.h>
10   -#include <linux/types.h>
11   -#include <linux/string.h>
12   -#include <linux/slab.h>
13   -#include <linux/blkdev.h>
14   -#include <linux/proc_fs.h>
15   -#include <linux/stat.h>
16   -#include <linux/init.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 <scsi/scsi_host.h>
25   -#include "../fc4/fcp_impl.h"
26   -#include "pluto.h"
27   -
28   -#include <linux/module.h>
29   -
30   -#define RQ_SCSI_BUSY 0xffff
31   -#define RQ_SCSI_DONE 0xfffe
32   -
33   -/* #define PLUTO_DEBUG */
34   -
35   -#define pluto_printk printk ("PLUTO %s: ", fc->name); printk
36   -
37   -#ifdef PLUTO_DEBUG
38   -#define PLD(x) pluto_printk x;
39   -#define PLND(x) printk ("PLUTO: "); printk x;
40   -#else
41   -#define PLD(x)
42   -#define PLND(x)
43   -#endif
44   -
45   -static struct ctrl_inquiry {
46   - struct Scsi_Host host;
47   - struct pluto pluto;
48   - Scsi_Cmnd cmd;
49   - char inquiry[256];
50   - fc_channel *fc;
51   -} *fcs __initdata;
52   -static int fcscount __initdata = 0;
53   -static atomic_t fcss __initdata = ATOMIC_INIT(0);
54   -static DECLARE_COMPLETION(fc_detect_complete);
55   -
56   -static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
57   -
58   -static void __init pluto_detect_done(Scsi_Cmnd *SCpnt)
59   -{
60   - /* Do nothing */
61   -}
62   -
63   -static void __init pluto_detect_scsi_done(Scsi_Cmnd *SCpnt)
64   -{
65   - PLND(("Detect done %08lx\n", (long)SCpnt))
66   - if (atomic_dec_and_test (&fcss))
67   - complete(&fc_detect_complete);
68   -}
69   -
70   -int pluto_slave_configure(struct scsi_device *device)
71   -{
72   - int depth_to_use;
73   -
74   - if (device->tagged_supported)
75   - depth_to_use = /* 254 */ 8;
76   - else
77   - depth_to_use = 2;
78   -
79   - scsi_adjust_queue_depth(device,
80   - (device->tagged_supported ?
81   - MSG_SIMPLE_TAG : 0),
82   - depth_to_use);
83   -
84   - return 0;
85   -}
86   -
87   -/* Detect all SSAs attached to the machine.
88   - To be fast, do it on all online FC channels at the same time. */
89   -int __init pluto_detect(struct scsi_host_template *tpnt)
90   -{
91   - int i, retry, nplutos;
92   - fc_channel *fc;
93   - struct scsi_device dev;
94   -
95   - tpnt->proc_name = "pluto";
96   - fcscount = 0;
97   - for_each_online_fc_channel(fc) {
98   - if (!fc->posmap)
99   - fcscount++;
100   - }
101   - PLND(("%d channels online\n", fcscount))
102   - if (!fcscount) {
103   -#if defined(MODULE) && defined(CONFIG_FC4_SOC_MODULE) && defined(CONFIG_KMOD)
104   - request_module("soc");
105   -
106   - for_each_online_fc_channel(fc) {
107   - if (!fc->posmap)
108   - fcscount++;
109   - }
110   - if (!fcscount)
111   -#endif
112   - return 0;
113   - }
114   - fcs = kcalloc(fcscount, sizeof (struct ctrl_inquiry), GFP_DMA);
115   - if (!fcs) {
116   - printk ("PLUTO: Not enough memory to probe\n");
117   - return 0;
118   - }
119   -
120   - memset (&dev, 0, sizeof(dev));
121   - atomic_set (&fcss, fcscount);
122   -
123   - i = 0;
124   - for_each_online_fc_channel(fc) {
125   - Scsi_Cmnd *SCpnt;
126   - struct Scsi_Host *host;
127   - struct pluto *pluto;
128   -
129   - if (i == fcscount) break;
130   - if (fc->posmap) continue;
131   -
132   - PLD(("trying to find SSA\n"))
133   -
134   - /* If this is already registered to some other SCSI host, then it cannot be pluto */
135   - if (fc->scsi_name[0]) continue;
136   - memcpy (fc->scsi_name, "SSA", 4);
137   -
138   - fcs[i].fc = fc;
139   -
140   - fc->can_queue = PLUTO_CAN_QUEUE;
141   - fc->rsp_size = 64;
142   - fc->encode_addr = pluto_encode_addr;
143   -
144   - fc->fcp_register(fc, TYPE_SCSI_FCP, 0);
145   -
146   - SCpnt = &(fcs[i].cmd);
147   - host = &(fcs[i].host);
148   - pluto = (struct pluto *)host->hostdata;
149   -
150   - pluto->fc = fc;
151   -
152   - SCpnt->cmnd[0] = INQUIRY;
153   - SCpnt->cmnd[4] = 255;
154   -
155   - /* FC layer requires this, so that SCpnt->device->tagged_supported is initially 0 */
156   - SCpnt->device = &dev;
157   - dev.host = host;
158   -
159   - SCpnt->cmd_len = COMMAND_SIZE(INQUIRY);
160   -
161   - SCpnt->request->cmd_flags &= ~REQ_STARTED;
162   -
163   - SCpnt->request_bufflen = 256;
164   - SCpnt->request_buffer = fcs[i].inquiry;
165   - PLD(("set up %d %08lx\n", i, (long)SCpnt))
166   - i++;
167   - }
168   -
169   - for (retry = 0; retry < 5; retry++) {
170   - for (i = 0; i < fcscount; i++) {
171   - if (!fcs[i].fc) break;
172   - if (!(fcs[i].cmd.request->cmd_flags & REQ_STARTED)) {
173   - fcs[i].cmd.request->cmd_flags |= REQ_STARTED;
174   - disable_irq(fcs[i].fc->irq);
175   - PLND(("queuecommand %d %d\n", retry, i))
176   - fcp_scsi_queuecommand (&(fcs[i].cmd),
177   - pluto_detect_scsi_done);
178   - enable_irq(fcs[i].fc->irq);
179   - }
180   - }
181   -
182   - wait_for_completion_timeout(&fc_detect_complete, 10 * HZ);
183   - PLND(("Woken up\n"))
184   - if (!atomic_read(&fcss))
185   - break; /* All fc channels have answered us */
186   - }
187   -
188   - PLND(("Finished search\n"))
189   - for (i = 0, nplutos = 0; i < fcscount; i++) {
190   - Scsi_Cmnd *SCpnt;
191   -
192   - if (!(fc = fcs[i].fc)) break;
193   -
194   - SCpnt = &(fcs[i].cmd);
195   -
196   - /* Let FC mid-level free allocated resources */
197   - pluto_detect_scsi_done(SCpnt);
198   -
199   - if (!SCpnt->result) {
200   - struct pluto_inquiry *inq;
201   - struct pluto *pluto;
202   - struct Scsi_Host *host;
203   -
204   - inq = (struct pluto_inquiry *)fcs[i].inquiry;
205   -
206   - if ((inq->dtype & 0x1f) == TYPE_PROCESSOR &&
207   - !strncmp (inq->vendor_id, "SUN", 3) &&
208   - !strncmp (inq->product_id, "SSA", 3)) {
209   - char *p;
210   - long *ages;
211   -
212   - ages = kcalloc((inq->channels + 1) * inq->targets, sizeof(long), GFP_KERNEL);
213   - if (!ages) continue;
214   -
215   - host = scsi_register (tpnt, sizeof (struct pluto));
216   - if(!host)
217   - {
218   - kfree(ages);
219   - continue;
220   - }
221   -
222   - if (!try_module_get(fc->module)) {
223   - kfree(ages);
224   - scsi_unregister(host);
225   - continue;
226   - }
227   -
228   - nplutos++;
229   -
230   - pluto = (struct pluto *)host->hostdata;
231   -
232   - host->max_id = inq->targets;
233   - host->max_channel = inq->channels;
234   - host->irq = fc->irq;
235   -
236   - fc->channels = inq->channels + 1;
237   - fc->targets = inq->targets;
238   - fc->ages = ages;
239   -
240   - pluto->fc = fc;
241   - memcpy (pluto->rev_str, inq->revision, 4);
242   - pluto->rev_str[4] = 0;
243   - p = strchr (pluto->rev_str, ' ');
244   - if (p) *p = 0;
245   - memcpy (pluto->fw_rev_str, inq->fw_revision, 4);
246   - pluto->fw_rev_str[4] = 0;
247   - p = strchr (pluto->fw_rev_str, ' ');
248   - if (p) *p = 0;
249   - memcpy (pluto->serial_str, inq->serial, 12);
250   - pluto->serial_str[12] = 0;
251   - p = strchr (pluto->serial_str, ' ');
252   - if (p) *p = 0;
253   -
254   - PLD(("Found SSA rev %s fw rev %s serial %s %dx%d\n", pluto->rev_str, pluto->fw_rev_str, pluto->serial_str, host->max_channel, host->max_id))
255   - } else
256   - fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
257   - } else
258   - fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
259   - }
260   - kfree(fcs);
261   - if (nplutos)
262   - printk ("PLUTO: Total of %d SparcSTORAGE Arrays found\n", nplutos);
263   - return nplutos;
264   -}
265   -
266   -int pluto_release(struct Scsi_Host *host)
267   -{
268   - struct pluto *pluto = (struct pluto *)host->hostdata;
269   - fc_channel *fc = pluto->fc;
270   -
271   - module_put(fc->module);
272   -
273   - fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
274   - PLND((" releasing pluto.\n"));
275   - kfree (fc->ages);
276   - PLND(("released pluto!\n"));
277   - return 0;
278   -}
279   -
280   -const char *pluto_info(struct Scsi_Host *host)
281   -{
282   - static char buf[128], *p;
283   - struct pluto *pluto = (struct pluto *) host->hostdata;
284   -
285   - sprintf(buf, "SUN SparcSTORAGE Array %s fw %s serial %s %dx%d on %s",
286   - pluto->rev_str, pluto->fw_rev_str, pluto->serial_str,
287   - host->max_channel, host->max_id, pluto->fc->name);
288   -#ifdef __sparc__
289   - p = strchr(buf, 0);
290   - sprintf(p, " PROM node %x", pluto->fc->dev->prom_node);
291   -#endif
292   - return buf;
293   -}
294   -
295   -/* SSA uses this FC4S addressing:
296   - switch (addr[0])
297   - {
298   - case 0: CONTROLLER - All of addr[1]..addr[3] has to be 0
299   - case 1: SINGLE DISK - addr[1] channel, addr[2] id, addr[3] 0
300   - case 2: DISK GROUP - ???
301   - }
302   -
303   - So that SCSI mid-layer can access to these, we reserve
304   - channel 0 id 0 lun 0 for CONTROLLER
305   - and channels 1 .. max_channel are normal single disks.
306   - */
307   -static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd)
308   -{
309   - PLND(("encode addr %d %d %d\n", SCpnt->device->channel, SCpnt->device->id, SCpnt->cmnd[1] & 0xe0))
310   - /* We don't support LUNs - neither does SSA :) */
311   - if (SCpnt->cmnd[1] & 0xe0)
312   - return -EINVAL;
313   - if (!SCpnt->device->channel) {
314   - if (SCpnt->device->id)
315   - return -EINVAL;
316   - memset (addr, 0, 4 * sizeof(u16));
317   - } else {
318   - addr[0] = 1;
319   - addr[1] = SCpnt->device->channel - 1;
320   - addr[2] = SCpnt->device->id;
321   - addr[3] = 0;
322   - }
323   - /* We're Point-to-Point, so target it to the default DID */
324   - fcmd->did = fc->did;
325   - PLND(("trying %04x%04x%04x%04x\n", addr[0], addr[1], addr[2], addr[3]))
326   - return 0;
327   -}
328   -
329   -static struct scsi_host_template driver_template = {
330   - .name = "Sparc Storage Array 100/200",
331   - .detect = pluto_detect,
332   - .release = pluto_release,
333   - .info = pluto_info,
334   - .queuecommand = fcp_scsi_queuecommand,
335   - .slave_configure = pluto_slave_configure,
336   - .can_queue = PLUTO_CAN_QUEUE,
337   - .this_id = -1,
338   - .sg_tablesize = 1,
339   - .cmd_per_lun = 1,
340   - .use_clustering = ENABLE_CLUSTERING,
341   - .eh_abort_handler = fcp_scsi_abort,
342   - .eh_device_reset_handler = fcp_scsi_dev_reset,
343   - .eh_host_reset_handler = fcp_scsi_host_reset,
344   -};
345   -
346   -#include "scsi_module.c"
347   -
348   -MODULE_LICENSE("GPL");
drivers/scsi/pluto.h
1   -/* pluto.h: SparcSTORAGE Array SCSI host adapter driver definitions.
2   - *
3   - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
4   - */
5   -
6   -#ifndef _PLUTO_H
7   -#define _PLUTO_H
8   -
9   -#include "../fc4/fcp_impl.h"
10   -
11   -struct pluto {
12   - /* This must be first */
13   - fc_channel *fc;
14   - char rev_str[5];
15   - char fw_rev_str[5];
16   - char serial_str[13];
17   -};
18   -
19   -struct pluto_inquiry {
20   - u8 dtype;
21   - u8 removable:1, qualifier:7;
22   - u8 iso:2, ecma:3, ansi:3;
23   - u8 aenc:1, trmiop:1, :2, rdf:4;
24   - u8 len;
25   - u8 xxx1;
26   - u8 xxx2;
27   - u8 reladdr:1, wbus32:1, wbus16:1, sync:1, linked:1, :1, cmdque:1, softreset:1;
28   - u8 vendor_id[8];
29   - u8 product_id[16];
30   - u8 revision[4];
31   - u8 fw_revision[4];
32   - u8 serial[12];
33   - u8 xxx3[2];
34   - u8 channels;
35   - u8 targets;
36   -};
37   -
38   -/* This is the max number of outstanding SCSI commands per pluto */
39   -#define PLUTO_CAN_QUEUE 254
40   -
41   -int pluto_detect(struct scsi_host_template *);
42   -int pluto_release(struct Scsi_Host *);
43   -const char * pluto_info(struct Scsi_Host *);
44   -int pluto_slave_configure(struct scsi_device *);
45   -
46   -#endif /* !(_PLUTO_H) */