xref: /OK3568_Linux_fs/kernel/Documentation/scsi/libsas.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun=========
4*4882a593SmuzhiyunSAS Layer
5*4882a593Smuzhiyun=========
6*4882a593Smuzhiyun
7*4882a593SmuzhiyunThe SAS Layer is a management infrastructure which manages
8*4882a593SmuzhiyunSAS LLDDs.  It sits between SCSI Core and SAS LLDDs.  The
9*4882a593Smuzhiyunlayout is as follows: while SCSI Core is concerned with
10*4882a593SmuzhiyunSAM/SPC issues, and a SAS LLDD+sequencer is concerned with
11*4882a593Smuzhiyunphy/OOB/link management, the SAS layer is concerned with:
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun      * SAS Phy/Port/HA event management (LLDD generates,
14*4882a593Smuzhiyun        SAS Layer processes),
15*4882a593Smuzhiyun      * SAS Port management (creation/destruction),
16*4882a593Smuzhiyun      * SAS Domain discovery and revalidation,
17*4882a593Smuzhiyun      * SAS Domain device management,
18*4882a593Smuzhiyun      * SCSI Host registration/unregistration,
19*4882a593Smuzhiyun      * Device registration with SCSI Core (SAS) or libata
20*4882a593Smuzhiyun        (SATA), and
21*4882a593Smuzhiyun      * Expander management and exporting expander control
22*4882a593Smuzhiyun        to user space.
23*4882a593Smuzhiyun
24*4882a593SmuzhiyunA SAS LLDD is a PCI device driver.  It is concerned with
25*4882a593Smuzhiyunphy/OOB management, and vendor specific tasks and generates
26*4882a593Smuzhiyunevents to the SAS layer.
27*4882a593Smuzhiyun
28*4882a593SmuzhiyunThe SAS Layer does most SAS tasks as outlined in the SAS 1.1
29*4882a593Smuzhiyunspec.
30*4882a593Smuzhiyun
31*4882a593SmuzhiyunThe sas_ha_struct describes the SAS LLDD to the SAS layer.
32*4882a593SmuzhiyunMost of it is used by the SAS Layer but a few fields need to
33*4882a593Smuzhiyunbe initialized by the LLDDs.
34*4882a593Smuzhiyun
35*4882a593SmuzhiyunAfter initializing your hardware, from the probe() function
36*4882a593Smuzhiyunyou call sas_register_ha(). It will register your LLDD with
37*4882a593Smuzhiyunthe SCSI subsystem, creating a SCSI host and it will
38*4882a593Smuzhiyunregister your SAS driver with the sysfs SAS tree it creates.
39*4882a593SmuzhiyunIt will then return.  Then you enable your phys to actually
40*4882a593Smuzhiyunstart OOB (at which point your driver will start calling the
41*4882a593Smuzhiyunnotify_* event callbacks).
42*4882a593Smuzhiyun
43*4882a593SmuzhiyunStructure descriptions
44*4882a593Smuzhiyun======================
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun``struct sas_phy``
47*4882a593Smuzhiyun------------------
48*4882a593Smuzhiyun
49*4882a593SmuzhiyunNormally this is statically embedded to your driver's
50*4882a593Smuzhiyunphy structure::
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun    struct my_phy {
53*4882a593Smuzhiyun	    blah;
54*4882a593Smuzhiyun	    struct sas_phy sas_phy;
55*4882a593Smuzhiyun	    bleh;
56*4882a593Smuzhiyun    };
57*4882a593Smuzhiyun
58*4882a593SmuzhiyunAnd then all the phys are an array of my_phy in your HA
59*4882a593Smuzhiyunstruct (shown below).
60*4882a593Smuzhiyun
61*4882a593SmuzhiyunThen as you go along and initialize your phys you also
62*4882a593Smuzhiyuninitialize the sas_phy struct, along with your own
63*4882a593Smuzhiyunphy structure.
64*4882a593Smuzhiyun
65*4882a593SmuzhiyunIn general, the phys are managed by the LLDD and the ports
66*4882a593Smuzhiyunare managed by the SAS layer.  So the phys are initialized
67*4882a593Smuzhiyunand updated by the LLDD and the ports are initialized and
68*4882a593Smuzhiyunupdated by the SAS layer.
69*4882a593Smuzhiyun
70*4882a593SmuzhiyunThere is a scheme where the LLDD can RW certain fields,
71*4882a593Smuzhiyunand the SAS layer can only read such ones, and vice versa.
72*4882a593SmuzhiyunThe idea is to avoid unnecessary locking.
73*4882a593Smuzhiyun
74*4882a593Smuzhiyunenabled
75*4882a593Smuzhiyun    - must be set (0/1)
76*4882a593Smuzhiyun
77*4882a593Smuzhiyunid
78*4882a593Smuzhiyun    - must be set [0,MAX_PHYS)]
79*4882a593Smuzhiyun
80*4882a593Smuzhiyunclass, proto, type, role, oob_mode, linkrate
81*4882a593Smuzhiyun    - must be set
82*4882a593Smuzhiyun
83*4882a593Smuzhiyunoob_mode
84*4882a593Smuzhiyun    - you set this when OOB has finished and then notify
85*4882a593Smuzhiyun      the SAS Layer.
86*4882a593Smuzhiyun
87*4882a593Smuzhiyunsas_addr
88*4882a593Smuzhiyun    - this normally points to an array holding the sas
89*4882a593Smuzhiyun      address of the phy, possibly somewhere in your my_phy
90*4882a593Smuzhiyun      struct.
91*4882a593Smuzhiyun
92*4882a593Smuzhiyunattached_sas_addr
93*4882a593Smuzhiyun    - set this when you (LLDD) receive an
94*4882a593Smuzhiyun      IDENTIFY frame or a FIS frame, _before_ notifying the SAS
95*4882a593Smuzhiyun      layer.  The idea is that sometimes the LLDD may want to fake
96*4882a593Smuzhiyun      or provide a different SAS address on that phy/port and this
97*4882a593Smuzhiyun      allows it to do this.  At best you should copy the sas
98*4882a593Smuzhiyun      address from the IDENTIFY frame or maybe generate a SAS
99*4882a593Smuzhiyun      address for SATA directly attached devices.  The Discover
100*4882a593Smuzhiyun      process may later change this.
101*4882a593Smuzhiyun
102*4882a593Smuzhiyunframe_rcvd
103*4882a593Smuzhiyun    - this is where you copy the IDENTIFY/FIS frame
104*4882a593Smuzhiyun      when you get it; you lock, copy, set frame_rcvd_size and
105*4882a593Smuzhiyun      unlock the lock, and then call the event.  It is a pointer
106*4882a593Smuzhiyun      since there's no way to know your hw frame size _exactly_,
107*4882a593Smuzhiyun      so you define the actual array in your phy struct and let
108*4882a593Smuzhiyun      this pointer point to it.  You copy the frame from your
109*4882a593Smuzhiyun      DMAable memory to that area holding the lock.
110*4882a593Smuzhiyun
111*4882a593Smuzhiyunsas_prim
112*4882a593Smuzhiyun    - this is where primitives go when they're
113*4882a593Smuzhiyun      received.  See sas.h. Grab the lock, set the primitive,
114*4882a593Smuzhiyun      release the lock, notify.
115*4882a593Smuzhiyun
116*4882a593Smuzhiyunport
117*4882a593Smuzhiyun    - this points to the sas_port if the phy belongs
118*4882a593Smuzhiyun      to a port -- the LLDD only reads this. It points to the
119*4882a593Smuzhiyun      sas_port this phy is part of.  Set by the SAS Layer.
120*4882a593Smuzhiyun
121*4882a593Smuzhiyunha
122*4882a593Smuzhiyun    - may be set; the SAS layer sets it anyway.
123*4882a593Smuzhiyun
124*4882a593Smuzhiyunlldd_phy
125*4882a593Smuzhiyun    - you should set this to point to your phy so you
126*4882a593Smuzhiyun      can find your way around faster when the SAS layer calls one
127*4882a593Smuzhiyun      of your callbacks and passes you a phy.  If the sas_phy is
128*4882a593Smuzhiyun      embedded you can also use container_of -- whatever you
129*4882a593Smuzhiyun      prefer.
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun``struct sas_port``
133*4882a593Smuzhiyun-------------------
134*4882a593Smuzhiyun
135*4882a593SmuzhiyunThe LLDD doesn't set any fields of this struct -- it only
136*4882a593Smuzhiyunreads them.  They should be self explanatory.
137*4882a593Smuzhiyun
138*4882a593Smuzhiyunphy_mask is 32 bit, this should be enough for now, as I
139*4882a593Smuzhiyunhaven't heard of a HA having more than 8 phys.
140*4882a593Smuzhiyun
141*4882a593Smuzhiyunlldd_port
142*4882a593Smuzhiyun    - I haven't found use for that -- maybe other
143*4882a593Smuzhiyun      LLDD who wish to have internal port representation can make
144*4882a593Smuzhiyun      use of this.
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun``struct sas_ha_struct``
147*4882a593Smuzhiyun------------------------
148*4882a593Smuzhiyun
149*4882a593SmuzhiyunIt normally is statically declared in your own LLDD
150*4882a593Smuzhiyunstructure describing your adapter::
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun    struct my_sas_ha {
153*4882a593Smuzhiyun	blah;
154*4882a593Smuzhiyun	struct sas_ha_struct sas_ha;
155*4882a593Smuzhiyun	struct my_phy phys[MAX_PHYS];
156*4882a593Smuzhiyun	struct sas_port sas_ports[MAX_PHYS]; /* (1) */
157*4882a593Smuzhiyun	bleh;
158*4882a593Smuzhiyun    };
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun    (1) If your LLDD doesn't have its own port representation.
161*4882a593Smuzhiyun
162*4882a593SmuzhiyunWhat needs to be initialized (sample function given below).
163*4882a593Smuzhiyun
164*4882a593Smuzhiyunpcidev
165*4882a593Smuzhiyun^^^^^^
166*4882a593Smuzhiyun
167*4882a593Smuzhiyunsas_addr
168*4882a593Smuzhiyun       - since the SAS layer doesn't want to mess with
169*4882a593Smuzhiyun	 memory allocation, etc, this points to statically
170*4882a593Smuzhiyun	 allocated array somewhere (say in your host adapter
171*4882a593Smuzhiyun	 structure) and holds the SAS address of the host
172*4882a593Smuzhiyun	 adapter as given by you or the manufacturer, etc.
173*4882a593Smuzhiyun
174*4882a593Smuzhiyunsas_port
175*4882a593Smuzhiyun^^^^^^^^
176*4882a593Smuzhiyun
177*4882a593Smuzhiyunsas_phy
178*4882a593Smuzhiyun      - an array of pointers to structures. (see
179*4882a593Smuzhiyun	note above on sas_addr).
180*4882a593Smuzhiyun	These must be set.  See more notes below.
181*4882a593Smuzhiyun
182*4882a593Smuzhiyunnum_phys
183*4882a593Smuzhiyun       - the number of phys present in the sas_phy array,
184*4882a593Smuzhiyun	 and the number of ports present in the sas_port
185*4882a593Smuzhiyun	 array.  There can be a maximum num_phys ports (one per
186*4882a593Smuzhiyun	 port) so we drop the num_ports, and only use
187*4882a593Smuzhiyun	 num_phys.
188*4882a593Smuzhiyun
189*4882a593SmuzhiyunThe event interface::
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun	/* LLDD calls these to notify the class of an event. */
192*4882a593Smuzhiyun	void sas_notify_port_event(struct sas_phy *, enum port_event);
193*4882a593Smuzhiyun	void sas_notify_phy_event(struct sas_phy *, enum phy_event);
194*4882a593Smuzhiyun	void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, gfp_t);
195*4882a593Smuzhiyun	void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t);
196*4882a593Smuzhiyun
197*4882a593SmuzhiyunThe port notification::
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun	/* The class calls these to notify the LLDD of an event. */
200*4882a593Smuzhiyun	void (*lldd_port_formed)(struct sas_phy *);
201*4882a593Smuzhiyun	void (*lldd_port_deformed)(struct sas_phy *);
202*4882a593Smuzhiyun
203*4882a593SmuzhiyunIf the LLDD wants notification when a port has been formed
204*4882a593Smuzhiyunor deformed it sets those to a function satisfying the type.
205*4882a593Smuzhiyun
206*4882a593SmuzhiyunA SAS LLDD should also implement at least one of the Task
207*4882a593SmuzhiyunManagement Functions (TMFs) described in SAM::
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun	/* Task Management Functions. Must be called from process context. */
210*4882a593Smuzhiyun	int (*lldd_abort_task)(struct sas_task *);
211*4882a593Smuzhiyun	int (*lldd_abort_task_set)(struct domain_device *, u8 *lun);
212*4882a593Smuzhiyun	int (*lldd_clear_aca)(struct domain_device *, u8 *lun);
213*4882a593Smuzhiyun	int (*lldd_clear_task_set)(struct domain_device *, u8 *lun);
214*4882a593Smuzhiyun	int (*lldd_I_T_nexus_reset)(struct domain_device *);
215*4882a593Smuzhiyun	int (*lldd_lu_reset)(struct domain_device *, u8 *lun);
216*4882a593Smuzhiyun	int (*lldd_query_task)(struct sas_task *);
217*4882a593Smuzhiyun
218*4882a593SmuzhiyunFor more information please read SAM from T10.org.
219*4882a593Smuzhiyun
220*4882a593SmuzhiyunPort and Adapter management::
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun	/* Port and Adapter management */
223*4882a593Smuzhiyun	int (*lldd_clear_nexus_port)(struct sas_port *);
224*4882a593Smuzhiyun	int (*lldd_clear_nexus_ha)(struct sas_ha_struct *);
225*4882a593Smuzhiyun
226*4882a593SmuzhiyunA SAS LLDD should implement at least one of those.
227*4882a593Smuzhiyun
228*4882a593SmuzhiyunPhy management::
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun	/* Phy management */
231*4882a593Smuzhiyun	int (*lldd_control_phy)(struct sas_phy *, enum phy_func);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyunlldd_ha
234*4882a593Smuzhiyun    - set this to point to your HA struct. You can also
235*4882a593Smuzhiyun      use container_of if you embedded it as shown above.
236*4882a593Smuzhiyun
237*4882a593SmuzhiyunA sample initialization and registration function
238*4882a593Smuzhiyuncan look like this (called last thing from probe())
239*4882a593Smuzhiyun*but* before you enable the phys to do OOB::
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun    static int register_sas_ha(struct my_sas_ha *my_ha)
242*4882a593Smuzhiyun    {
243*4882a593Smuzhiyun	    int i;
244*4882a593Smuzhiyun	    static struct sas_phy   *sas_phys[MAX_PHYS];
245*4882a593Smuzhiyun	    static struct sas_port  *sas_ports[MAX_PHYS];
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun	    my_ha->sas_ha.sas_addr = &my_ha->sas_addr[0];
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun	    for (i = 0; i < MAX_PHYS; i++) {
250*4882a593Smuzhiyun		    sas_phys[i] = &my_ha->phys[i].sas_phy;
251*4882a593Smuzhiyun		    sas_ports[i] = &my_ha->sas_ports[i];
252*4882a593Smuzhiyun	    }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun	    my_ha->sas_ha.sas_phy  = sas_phys;
255*4882a593Smuzhiyun	    my_ha->sas_ha.sas_port = sas_ports;
256*4882a593Smuzhiyun	    my_ha->sas_ha.num_phys = MAX_PHYS;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_port_formed = my_port_formed;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_dev_found = my_dev_found;
261*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_dev_gone = my_dev_gone;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_execute_task = my_execute_task;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_abort_task     = my_abort_task;
266*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_abort_task_set = my_abort_task_set;
267*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_clear_aca      = my_clear_aca;
268*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_clear_task_set = my_clear_task_set;
269*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_I_T_nexus_reset= NULL; (2)
270*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_lu_reset       = my_lu_reset;
271*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_query_task     = my_query_task;
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_clear_nexus_port = my_clear_nexus_port;
274*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_clear_nexus_ha = my_clear_nexus_ha;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun	    my_ha->sas_ha.lldd_control_phy = my_control_phy;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun	    return sas_register_ha(&my_ha->sas_ha);
279*4882a593Smuzhiyun    }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun(2) SAS 1.1 does not define I_T Nexus Reset TMF.
282*4882a593Smuzhiyun
283*4882a593SmuzhiyunEvents
284*4882a593Smuzhiyun======
285*4882a593Smuzhiyun
286*4882a593SmuzhiyunEvents are **the only way** a SAS LLDD notifies the SAS layer
287*4882a593Smuzhiyunof anything.  There is no other method or way a LLDD to tell
288*4882a593Smuzhiyunthe SAS layer of anything happening internally or in the SAS
289*4882a593Smuzhiyundomain.
290*4882a593Smuzhiyun
291*4882a593SmuzhiyunPhy events::
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun	PHYE_LOSS_OF_SIGNAL, (C)
294*4882a593Smuzhiyun	PHYE_OOB_DONE,
295*4882a593Smuzhiyun	PHYE_OOB_ERROR,      (C)
296*4882a593Smuzhiyun	PHYE_SPINUP_HOLD.
297*4882a593Smuzhiyun
298*4882a593SmuzhiyunPort events, passed on a _phy_::
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun	PORTE_BYTES_DMAED,      (M)
301*4882a593Smuzhiyun	PORTE_BROADCAST_RCVD,   (E)
302*4882a593Smuzhiyun	PORTE_LINK_RESET_ERR,   (C)
303*4882a593Smuzhiyun	PORTE_TIMER_EVENT,      (C)
304*4882a593Smuzhiyun	PORTE_HARD_RESET.
305*4882a593Smuzhiyun
306*4882a593SmuzhiyunHost Adapter event:
307*4882a593Smuzhiyun	HAE_RESET
308*4882a593Smuzhiyun
309*4882a593SmuzhiyunA SAS LLDD should be able to generate
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun	- at least one event from group C (choice),
312*4882a593Smuzhiyun	- events marked M (mandatory) are mandatory (only one),
313*4882a593Smuzhiyun	- events marked E (expander) if it wants the SAS layer
314*4882a593Smuzhiyun	  to handle domain revalidation (only one such).
315*4882a593Smuzhiyun	- Unmarked events are optional.
316*4882a593Smuzhiyun
317*4882a593SmuzhiyunMeaning:
318*4882a593Smuzhiyun
319*4882a593SmuzhiyunHAE_RESET
320*4882a593Smuzhiyun    - when your HA got internal error and was reset.
321*4882a593Smuzhiyun
322*4882a593SmuzhiyunPORTE_BYTES_DMAED
323*4882a593Smuzhiyun    - on receiving an IDENTIFY/FIS frame
324*4882a593Smuzhiyun
325*4882a593SmuzhiyunPORTE_BROADCAST_RCVD
326*4882a593Smuzhiyun    - on receiving a primitive
327*4882a593Smuzhiyun
328*4882a593SmuzhiyunPORTE_LINK_RESET_ERR
329*4882a593Smuzhiyun    - timer expired, loss of signal, loss of DWS, etc. [1]_
330*4882a593Smuzhiyun
331*4882a593SmuzhiyunPORTE_TIMER_EVENT
332*4882a593Smuzhiyun    - DWS reset timeout timer expired [1]_
333*4882a593Smuzhiyun
334*4882a593SmuzhiyunPORTE_HARD_RESET
335*4882a593Smuzhiyun    - Hard Reset primitive received.
336*4882a593Smuzhiyun
337*4882a593SmuzhiyunPHYE_LOSS_OF_SIGNAL
338*4882a593Smuzhiyun    - the device is gone [1]_
339*4882a593Smuzhiyun
340*4882a593SmuzhiyunPHYE_OOB_DONE
341*4882a593Smuzhiyun    - OOB went fine and oob_mode is valid
342*4882a593Smuzhiyun
343*4882a593SmuzhiyunPHYE_OOB_ERROR
344*4882a593Smuzhiyun    - Error while doing OOB, the device probably
345*4882a593Smuzhiyun      got disconnected. [1]_
346*4882a593Smuzhiyun
347*4882a593SmuzhiyunPHYE_SPINUP_HOLD
348*4882a593Smuzhiyun    - SATA is present, COMWAKE not sent.
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun.. [1] should set/clear the appropriate fields in the phy,
351*4882a593Smuzhiyun       or alternatively call the inlined sas_phy_disconnected()
352*4882a593Smuzhiyun       which is just a helper, from their tasklet.
353*4882a593Smuzhiyun
354*4882a593SmuzhiyunThe Execute Command SCSI RPC::
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun	int (*lldd_execute_task)(struct sas_task *, gfp_t gfp_flags);
357*4882a593Smuzhiyun
358*4882a593SmuzhiyunUsed to queue a task to the SAS LLDD.  @task is the task to be executed.
359*4882a593Smuzhiyun@gfp_mask is the gfp_mask defining the context of the caller.
360*4882a593Smuzhiyun
361*4882a593SmuzhiyunThis function should implement the Execute Command SCSI RPC,
362*4882a593Smuzhiyun
363*4882a593SmuzhiyunThat is, when lldd_execute_task() is called, the command
364*4882a593Smuzhiyungo out on the transport *immediately*.  There is *no*
365*4882a593Smuzhiyunqueuing of any sort and at any level in a SAS LLDD.
366*4882a593Smuzhiyun
367*4882a593SmuzhiyunReturns:
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun   * -SAS_QUEUE_FULL, -ENOMEM, nothing was queued;
370*4882a593Smuzhiyun   * 0, the task(s) were queued.
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun::
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun    struct sas_task {
375*4882a593Smuzhiyun	    dev -- the device this task is destined to
376*4882a593Smuzhiyun	    task_proto -- _one_ of enum sas_proto
377*4882a593Smuzhiyun	    scatter -- pointer to scatter gather list array
378*4882a593Smuzhiyun	    num_scatter -- number of elements in scatter
379*4882a593Smuzhiyun	    total_xfer_len -- total number of bytes expected to be transferred
380*4882a593Smuzhiyun	    data_dir -- PCI_DMA_...
381*4882a593Smuzhiyun	    task_done -- callback when the task has finished execution
382*4882a593Smuzhiyun    };
383*4882a593Smuzhiyun
384*4882a593SmuzhiyunDiscovery
385*4882a593Smuzhiyun=========
386*4882a593Smuzhiyun
387*4882a593SmuzhiyunThe sysfs tree has the following purposes:
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun    a) It shows you the physical layout of the SAS domain at
390*4882a593Smuzhiyun       the current time, i.e. how the domain looks in the
391*4882a593Smuzhiyun       physical world right now.
392*4882a593Smuzhiyun    b) Shows some device parameters _at_discovery_time_.
393*4882a593Smuzhiyun
394*4882a593SmuzhiyunThis is a link to the tree(1) program, very useful in
395*4882a593Smuzhiyunviewing the SAS domain:
396*4882a593Smuzhiyunftp://mama.indstate.edu/linux/tree/
397*4882a593Smuzhiyun
398*4882a593SmuzhiyunI expect user space applications to actually create a
399*4882a593Smuzhiyungraphical interface of this.
400*4882a593Smuzhiyun
401*4882a593SmuzhiyunThat is, the sysfs domain tree doesn't show or keep state if
402*4882a593Smuzhiyunyou e.g., change the meaning of the READY LED MEANING
403*4882a593Smuzhiyunsetting, but it does show you the current connection status
404*4882a593Smuzhiyunof the domain device.
405*4882a593Smuzhiyun
406*4882a593SmuzhiyunKeeping internal device state changes is responsibility of
407*4882a593Smuzhiyunupper layers (Command set drivers) and user space.
408*4882a593Smuzhiyun
409*4882a593SmuzhiyunWhen a device or devices are unplugged from the domain, this
410*4882a593Smuzhiyunis reflected in the sysfs tree immediately, and the device(s)
411*4882a593Smuzhiyunremoved from the system.
412*4882a593Smuzhiyun
413*4882a593SmuzhiyunThe structure domain_device describes any device in the SAS
414*4882a593Smuzhiyundomain.  It is completely managed by the SAS layer.  A task
415*4882a593Smuzhiyunpoints to a domain device, this is how the SAS LLDD knows
416*4882a593Smuzhiyunwhere to send the task(s) to.  A SAS LLDD only reads the
417*4882a593Smuzhiyuncontents of the domain_device structure, but it never creates
418*4882a593Smuzhiyunor destroys one.
419*4882a593Smuzhiyun
420*4882a593SmuzhiyunExpander management from User Space
421*4882a593Smuzhiyun===================================
422*4882a593Smuzhiyun
423*4882a593SmuzhiyunIn each expander directory in sysfs, there is a file called
424*4882a593Smuzhiyun"smp_portal".  It is a binary sysfs attribute file, which
425*4882a593Smuzhiyunimplements an SMP portal (Note: this is *NOT* an SMP port),
426*4882a593Smuzhiyunto which user space applications can send SMP requests and
427*4882a593Smuzhiyunreceive SMP responses.
428*4882a593Smuzhiyun
429*4882a593SmuzhiyunFunctionality is deceptively simple:
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun1. Build the SMP frame you want to send. The format and layout
432*4882a593Smuzhiyun   is described in the SAS spec.  Leave the CRC field equal 0.
433*4882a593Smuzhiyun
434*4882a593Smuzhiyunopen(2)
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun2. Open the expander's SMP portal sysfs file in RW mode.
437*4882a593Smuzhiyun
438*4882a593Smuzhiyunwrite(2)
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun3. Write the frame you built in 1.
441*4882a593Smuzhiyun
442*4882a593Smuzhiyunread(2)
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun4. Read the amount of data you expect to receive for the frame you built.
445*4882a593Smuzhiyun   If you receive different amount of data you expected to receive,
446*4882a593Smuzhiyun   then there was some kind of error.
447*4882a593Smuzhiyun
448*4882a593Smuzhiyunclose(2)
449*4882a593Smuzhiyun
450*4882a593SmuzhiyunAll this process is shown in detail in the function do_smp_func()
451*4882a593Smuzhiyunand its callers, in the file "expander_conf.c".
452*4882a593Smuzhiyun
453*4882a593SmuzhiyunThe kernel functionality is implemented in the file
454*4882a593Smuzhiyun"sas_expander.c".
455*4882a593Smuzhiyun
456*4882a593SmuzhiyunThe program "expander_conf.c" implements this. It takes one
457*4882a593Smuzhiyunargument, the sysfs file name of the SMP portal to the
458*4882a593Smuzhiyunexpander, and gives expander information, including routing
459*4882a593Smuzhiyuntables.
460*4882a593Smuzhiyun
461*4882a593SmuzhiyunThe SMP portal gives you complete control of the expander,
462*4882a593Smuzhiyunso please be careful.
463