xref: /illumos-gate/usr/src/uts/sun4/sys/fcode.h (revision 4f364e7c95ee7fd9d5bbeddc1940e92405bb0e72)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef	_SYS_FCODE_H
27 #define	_SYS_FCODE_H
28 
29 #include <sys/sysmacros.h>
30 #include <sys/ddi.h>
31 #include <sys/sunddi.h>
32 #include <sys/fc_plat.h>
33 #include <sys/pci.h>
34 
35 #ifdef	__cplusplus
36 extern "C" {
37 #endif
38 
39 /*
40  * The FCode driver presents a private interface to the fcode
41  * user level interpreter.  This interface is subject to change
42  * at any time and is only provided for use by the fcode interpreter.
43  *
44  * The user program opens the device, causing a new instance of
45  * the driver to be cloned.  This instance is specific to a specific
46  * instance of a new device managed by the kernel and driver framework.
47  *
48  * The interpreter does an FC_GET_PARAMETERS ioctl to get the fcode
49  * length, which can be mmap-ed (at offset 0) to provide access to a copy
50  * of the device's fcode.
51  *
52  * The interpreter uses the FC_RUN_PRIV ioctl to request privileged
53  * operations to be run by the driver.
54  *
55  * The interpreter sends an FC_VALIDATE ioctl to notify the
56  * driver that it's done interpreting FCode to signify a normal
57  * ending sequence when the interpreter later closes the device.
58  * This way the driver can easily distinguish between the user
59  * level interpreter failing and finishing normally, thus validating
60  * the interpreters actions and the state it downloads to the driver.
61  * The 'arg' value in the FC_VALIDATE ioctl is ignored, there
62  * are no arguments to this ioctl.
63  */
64 
65 #define	FCIOC			(0xfc<<8)
66 #define	FC_GET_PARAMETERS	(FCIOC | 1)
67 #define	FC_RUN_PRIV		(FCIOC | 2)
68 #define	FC_VALIDATE		(FCIOC | 3)
69 #define	FC_GET_MY_ARGS		(FCIOC | 4)
70 #define	FC_GET_FCODE_DATA	(FCIOC | 5)
71 #define	FC_SET_FCODE_ERROR	(FCIOC | 6)
72 
73 #define	FC_GET_MY_ARGS_BUFLEN	256	/* Max my-args length */
74 
75 /*
76  * FC_GET_PARAMETERS: Expected as the first ioctl after a successful
77  * open and blocking read (the read returns 0 when there's something
78  * to interpret).  The ioctl arg is a pointer to an fc_parameters
79  * data structure which is filled in by the driver with the fcode
80  * len (if any) and unit address of the new device.
81  * Offset 0 .. fcode len may be used as the offset to an mmap call to
82  * provide access to a copy of the device fcode. The unit address is
83  * returned as a NULL terminated string.
84  */
85 
86 struct fc_parameters {
87 	int32_t	fcode_size;
88 	char	unit_address[OBP_MAXPATHLEN];
89 	int	config_address;
90 };
91 
92 
93 
94 /*
95  * FC_RUN_PRIV: The ioctl 'arg' is a pointer to an array of fc_cell_t's
96  * in the following format:
97  *
98  * fc_cell_t[0]: Pointer to a NULL terminated string: service name
99  * fc_cell_t[1]: Number of input arguments (Call this value 'A')
100  * fc_cell_t[2]: Number of output result cells allocated (Call this val 'R')
101  * fc_cell_t[3]: Error Cell (See below)
102  * fc_cell_t[4]: Priv Violation Cell (non-zero if priv. violation)
103  * fc_cell_t[5]: Argument cell[0] (Possibly none)
104  * fc_cell_t[5 + 'A']: Result cell[0] (Possibly none)
105  *
106  * The array is variable sized, and must contain a minimum of 5 fc_cell_t's.
107  * The size (in fc_cell_t's) is 5 + 'A' + 'R'.
108  *
109  * The argument cells are filled in by the caller.  The result cells
110  * (if any) and error cell are returned to the caller by the driver.
111  * The error cell and priv violation cell are filled in and returned
112  * to the caller by the driver.
113  *
114  * Error Cell Values:
115  *
116  *	-1:	The call itself failed (the service name was unknown).
117  *
118  *	0:	No error (though the result cells may indicate results
119  *		that signify an error consistent with the service request.)
120  *
121  * Priv Violation Cell Values:
122  *
123  *	0:	No priv violation
124  *
125  *	-1:	Executing the request caused a priv. violation.
126  *		For example, an rl@ from an address not mapped in
127  *		by the interpreter.
128  */
129 
130 #define	FC_ERR_NONE	fc_int2cell(0)
131 #define	FC_ERR_SVC_NAME	fc_int2cell(-1)
132 
133 #define	FC_PRIV_OK	fc_intcell(0)
134 #define	FC_PRIV_ERROR	fc_int2cell(-1)
135 
136 /*
137  * Client interface template:
138  * The actual number of arguments is nargs.
139  * The actual number of results is nresults.
140  * The variable array 'v' contains 'nargs + nresults' elements
141  */
142 struct fc_client_interface {
143 	fc_cell_t	svc_name;
144 	fc_cell_t	nargs;
145 	fc_cell_t	nresults;
146 	fc_cell_t	error;
147 	fc_cell_t	priv_error;
148 	fc_cell_t	v[1];	/* variable array of args and results */
149 };
150 
151 typedef	struct fc_client_interface fc_ci_t;
152 
153 #define	fc_arg(cp, i)		(cp->v[(i)])
154 #define	fc_result(cp, i)	(cp->v[fc_cell2int(cp->nargs) + (i)])
155 
156 #define	FCC_FIXED_CELLS			5
157 
158 /*
159  * FC_GET_FCODE_DATA: This ioctl allows userland portion of the fcode
160  * interpreter to get the fcode into a local buffer without having
161  * to use mmap() interface.
162  * This allows DR kernel cage memory to be relocated while this
163  * fcode buffer is allocated.
164  *
165  * The ioctl arg is a pointer to an fc_fcode_info structure which
166  * has the fcode_size field set with the expected fcode length.
167  * The driver uses this field to validate correct size before using
168  * copyout() to fill in the fcode_ptr buffer with fcode data.
169  */
170 typedef struct fc_fcode_info {
171 	int32_t	fcode_size;
172 	char	*fcode_ptr;
173 } fc_fcode_info_t;
174 
175 /*
176  * The service name len (max) is limited by the size of a method name
177  */
178 #define	FC_SVC_NAME_LEN		OBP_MAXPROPNAME
179 
180 /*
181  * "Internally" generated service names ...
182  */
183 #define	FC_SVC_VALIDATE		"sunos,validate"
184 #define	FC_SVC_INVALIDATE	"sunos,invalidate"
185 #define	FC_SVC_EXIT		"sunos,exit"
186 
187 #define	FC_OPEN_METHOD		"open"
188 #define	FC_CLOSE_METHOD		"close"
189 #define	FC_FIND_FCODE		"$find"
190 
191 /*
192  * Property related group:
193  *
194  * sunos,get*proplen ( propname-cstr phandle -- proplen )
195  * sunos,get*prop ( propname-cstr buf phandle -- proplen )
196  *
197  * sunos,property ( propname-cstr buf len phandle -- )
198  */
199 
200 #define	FC_GET_MY_PROPLEN	"sunos,get-my-proplen"
201 #define	FC_GET_MY_PROP		"sunos,get-my-prop"
202 
203 #define	FC_GET_IN_PROPLEN	"sunos,get-inherited-proplen"
204 #define	FC_GET_IN_PROP		"sunos,get-inherited-prop"
205 
206 #define	FC_GET_PKG_PROPLEN	"sunos,get-package-proplen"
207 #define	FC_GET_PKG_PROP		"sunos,get-package-prop"
208 
209 #define	FC_CREATE_PROPERTY	"sunos,property"
210 
211 /*
212  * Register access and dma ... same as 1275
213  *
214  * dma-map-in maps in a suitable aligned user address.
215  */
216 #define	FC_RL_FETCH		"rl@"
217 #define	FC_RW_FETCH		"rw@"
218 #define	FC_RB_FETCH		"rb@"
219 
220 #define	FC_RL_STORE		"rl!"
221 #define	FC_RW_STORE		"rw!"
222 #define	FC_RB_STORE		"rb!"
223 
224 #define	FC_MAP_IN		"map-in"
225 #define	FC_MAP_OUT		"map-out"
226 #define	FC_DMA_MAP_IN		"dma-map-in"
227 #define	FC_DMA_MAP_OUT		"dma-map-out"
228 
229 /*
230  * PCI configuration space access methods ... same as pci binding
231  */
232 #define	FC_PCI_CFG_L_FETCH	"config-l@"
233 #define	FC_PCI_CFG_W_FETCH	"config-w@"
234 #define	FC_PCI_CFG_B_FETCH	"config-b@"
235 
236 #define	FC_PCI_CFG_L_STORE	"config-l!"
237 #define	FC_PCI_CFG_W_STORE	"config-w!"
238 #define	FC_PCI_CFG_B_STORE	"config-b!"
239 
240 /*
241  * Device node creation ...
242  *
243  * Create a new device with the given name, unit-address, parent.phandle
244  * with a phandle that must have been previously allocated using
245  * sunos,alloc-phandle.  finish-device marks the device creation and
246  * the creation of its properties as complete. (It's a signal to the
247  * the OS that the node is now reasonably complete.)
248  *
249  * sunos,new-device ( name-cstr unit-addr-cstr parent.phandle phandle -- )
250  * finish-device ( phandle  -- )
251  */
252 #define	FC_NEW_DEVICE		"sunos,new-device"
253 #define	FC_FINISH_DEVICE	"sunos,finish-device"
254 
255 /*
256  * Navigation and configuration:
257  *
258  * sunos,probe-address ( -- phys.lo ... )
259  * sunos,probe-space ( -- phys.hi )
260  *
261  * sunos,ap-phandle ( -- ap.phandle )
262  *	Return attachment point phandle
263  *
264  * sunos,parent ( child.phandle -- parent.phandle )
265  *
266  * child ( parent.phandle -- child.phandle )
267  * peer ( phandle -- phandle.sibling )
268  *
269  * sunos,alloc-phandle ( -- phandle )
270  * Allocates a unique phandle, not associated with the device tree
271  *
272  * sunos,config-child ( -- child.phandle )
273  * Return the phandle of the child being configured.
274  */
275 
276 #define	FC_PROBE_ADDRESS	"sunos,probe-address"
277 #define	FC_PROBE_SPACE		"sunos,probe-space"
278 #define	FC_AP_PHANDLE		"sunos,ap-phandle"
279 #define	FC_PARENT		"sunos,parent"
280 #define	FC_CHILD_FCODE		"child"
281 #define	FC_PEER_FCODE		"peer"
282 #define	FC_ALLOC_PHANDLE	"sunos,alloc-phandle"
283 #define	FC_CONFIG_CHILD		"sunos,config-child"
284 
285 /*
286  * Fcode Drop In Routines:
287  * sunos,get_fcode_size ( cstr -- len )
288  * Returns the size in bytes of the Fcode for a given drop in.
289  * sunos,get_fcode (cstr buf len -- status? )
290  * Returns the Fcode image for a given drop in.
291  */
292 #define	FC_GET_FCODE_SIZE	"sunos,get-fcode-size"
293 #define	FC_GET_FCODE		"sunos,get-fcode"
294 
295 /*
296  * Values for fc_request 'error'. This has been moved from the _KERNEL
297  * area to allow the FC_SET_FCODE_ERROR ioctl to use these values to
298  * signal the kernel as to the disposition of the userland interpreter.
299  * NOTE: Positive values are used to indicate a kernel error,
300  * negative values are used to identify userland interpreter errors.
301  */
302 #define	FC_SUCCESS	0		/* FCode interpreted successfully */
303 #define	FC_TIMEOUT	1		/* Timer expired */
304 #define	FC_ERROR	-1		/* Interpreter error */
305 #define	FC_EXEC_FAILED	-2		/* Interpreter failed to exec */
306 #define	FC_NO_FCODE	-3		/* Interpreter couldn't find fcode */
307 #define	FC_FCODE_ABORT	-4		/* Interpreter called exit(1) */
308 #define	FC_ERROR_VALID(s) ((s) >= FC_FCODE_ABORT) && ((s) <= FC_TIMEOUT)
309 
310 /*
311  * kernel internal data structures and interfaces
312  * for the fcode interpreter.
313  */
314 #if defined(_KERNEL)
315 
316 /*
317  * PCI bus-specific arguments.
318  *
319  * We can't get the physical config address of the child from the
320  * unit address, so we supply it here, along with the child's dip
321  * as the bus specific argument to pci_ops_alloc_handle.
322  */
323 
324 struct pci_ops_bus_args {
325 	int32_t config_address;		/* phys.hi config addr component */
326 };
327 
328 /*
329  * Define data structures for resource lists and handle management
330  *
331  * 'untyped' resources are managed by the provider.
332  */
333 struct fc_dma_resource {
334 	void *virt;
335 	size_t len;
336 	ddi_dma_handle_t h;
337 	uint32_t devaddr;
338 	struct buf *bp;
339 };
340 
341 struct fc_map_resource {
342 	void *virt;
343 	size_t len;
344 	ddi_acc_handle_t h;
345 	void *regspec;
346 };
347 
348 struct fc_nodeid_resource {
349 	int nodeid;		/* An allocated nodeid */
350 };
351 
352 struct fc_contigious_resource {
353 	void *virt;
354 	size_t len;
355 };
356 struct fc_untyped_resource {
357 	int utype;		/* providers private type field */
358 	void (*free)(void *);	/* function to free the resource */
359 	void *resource;		/* Pointer to the resource */
360 };
361 
362 typedef enum {
363 	RT_DMA = 0,
364 	RT_MAP,
365 	RT_NODEID,
366 	RT_CONTIGIOUS,
367 	RT_UNTYPED
368 } fc_resource_type_t;
369 
370 struct fc_resource {
371 	struct fc_resource *next;
372 	fc_resource_type_t type;
373 	union {
374 		struct fc_dma_resource d;
375 		struct fc_map_resource m;
376 		struct fc_nodeid_resource n;
377 		struct fc_contigious_resource c;
378 		struct fc_untyped_resource r;
379 	} un;
380 };
381 
382 #define	fc_dma_virt	un.d.virt
383 #define	fc_dma_len	un.d.len
384 #define	fc_dma_handle	un.d.h
385 #define	fc_dma_devaddr	un.d.devaddr
386 #define	fc_dma_bp	un.d.bp
387 
388 #define	fc_map_virt	un.m.virt
389 #define	fc_map_len	un.m.len
390 #define	fc_map_handle	un.m.h
391 #define	fc_regspec	un.m.regspec
392 
393 #define	fc_nodeid_r	un.n.nodeid
394 
395 #define	fc_contig_virt	un.c.virt
396 #define	fc_contig_len	un.c.len
397 
398 #define	fc_untyped_type	un.r.utype
399 #define	fc_untyped_free	un.r.free
400 #define	fc_untyped_r	un.r.resource
401 
402 struct fc_phandle_entry {
403 	struct fc_phandle_entry *next;
404 	dev_info_t	*dip;
405 	fc_phandle_t	h;
406 };
407 
408 extern void fc_phandle_table_alloc(struct fc_phandle_entry **);
409 extern void fc_phandle_table_free(struct fc_phandle_entry **);
410 extern dev_info_t *fc_phandle_to_dip(struct fc_phandle_entry **, fc_phandle_t);
411 extern fc_phandle_t fc_dip_to_phandle(struct fc_phandle_entry **, dev_info_t *);
412 extern void fc_add_dip_to_phandle(struct fc_phandle_entry **, dev_info_t *,
413     fc_phandle_t);
414 
415 /*
416  * Structures and functions for managing our own subtree rooted
417  * at the attachment point. The parent linkage is established
418  * at node creation time.  The 'downwards' linkage isn't established
419  * until the node is bound.
420  */
421 struct fc_device_tree {
422 	dev_info_t *dip;
423 	struct fc_device_tree *child;
424 	struct fc_device_tree *peer;
425 };
426 
427 void fc_add_child(dev_info_t *child, dev_info_t *parent,
428     struct fc_device_tree *head);
429 
430 void fc_remove_child(dev_info_t *child, struct fc_device_tree *head);
431 
432 dev_info_t *fc_child_node(dev_info_t *parent, struct fc_device_tree *head);
433 dev_info_t *fc_peer_node(dev_info_t *devi, struct fc_device_tree *head);
434 struct fc_device_tree *fc_find_node(dev_info_t *, struct fc_device_tree *);
435 
436 void fc_create_device_tree(dev_info_t *ap, struct fc_device_tree **head);
437 void fc_remove_device_tree(struct fc_device_tree **head);
438 
439 /*
440  * Our handles represent a list of resources associated with an
441  * attachment point.  The handles chain, just as the ops functions
442  * do, with the ops caller responsible for remembering the handle
443  * of the ops function below it. NB: Externally, this data structure
444  * is opaque. (Not all members may be present in each chained cookie.)
445  * For example, the dtree head is valid in only a single instance
446  * of a set of chained cookies, so use the access function to find it.)
447  */
448 struct fc_resource_list {
449 	struct fc_resource *head;
450 	void *next_handle;		/* next handle in chain */
451 	dev_info_t *ap;			/* Attachment point dip */
452 	dev_info_t *child;		/* Child being configured, if any */
453 	dev_info_t *cdip;		/* Current node, if any */
454 	int cdip_state;			/* node creation state - see below */
455 	void *fcode;			/* fcode kernel address */
456 	size_t fcode_size;		/* fcode size or zero */
457 	char *unit_address;		/* childs unit address */
458 	char *my_args;			/* initial setting for my-args */
459 	void *bus_args;			/* bus dependent arguments */
460 	struct fc_phandle_entry *ptable; /* devinfo/phandle table */
461 	struct fc_device_tree *dtree;	/* Our subtree (leaf cookie only) */
462 };
463 
464 typedef struct fc_resource_list *fco_handle_t;
465 
466 /*
467  * Values for cdip_state:
468  */
469 #define	FC_CDIP_NOSTATE		0x00	/* No state - no nodes created */
470 #define	FC_CDIP_STARTED		0x01	/* Node started - dip in cdip */
471 #define	FC_CDIP_DONE		0x02	/* Node finished - last dip in cdip */
472 #define	FC_CDIP_CONFIG		0x10	/* subtree configured */
473 
474 /*
475  * Functions to allocate handles for the fcode_interpreter.
476  *
477  * This function allocates a handle, used to store resources
478  * associated with this fcode request including the address of
479  * the mapped in and copied in fcode and it's size or NULL, 0
480  * if there is no fcode (the interpreter may look for a drop-in
481  * driver if there is no fcode), the unit address of child and
482  * bus specific arguments.  For PCI, the bus specific arguments
483  * include the child's prototype dip and the config address of
484  * the child, which can't be derived from the unit address.
485  *
486  * The 'handle' returned also contains resource information
487  * about any allocations of kernel resources that the fcode
488  * may have created.  Thus, the handle's life is the life
489  * of the plug-in card and can't be released until the card
490  * is removed.  Upon release, the resources are released.
491  */
492 extern fco_handle_t
493 fc_ops_alloc_handle(dev_info_t *ap, dev_info_t *config_child,
494     void *fcode, size_t fcode_size, char *unit_address, void *bus_args);
495 
496 extern fco_handle_t
497 pci_fc_ops_alloc_handle(dev_info_t *ap, dev_info_t *config_child,
498     void *fcode, size_t fcode_size, char *unit_address,
499     struct pci_ops_bus_args *bus_args);
500 
501 extern fco_handle_t
502 gp2_fc_ops_alloc_handle(dev_info_t *ap, dev_info_t *config_child,
503     void *fcode, size_t fcode_size, char *unit_address,
504     char *my_args);
505 
506 extern void pci_fc_ops_free_handle(fco_handle_t handle);
507 extern void gp2_fc_ops_free_handle(fco_handle_t handle);
508 extern void fc_ops_free_handle(fco_handle_t handle);
509 
510 extern struct fc_phandle_entry **fc_handle_to_phandle_head(fco_handle_t rp);
511 
512 struct fc_device_tree **fc_handle_to_dtree_head(fco_handle_t);
513 struct fc_device_tree *fc_handle_to_dtree(fco_handle_t);
514 
515 /*
516  * fc_ops_t is the main glue back to the framework and attachment point driver
517  * for privileged driver operations.  The framework/driver provides a pointer
518  * to the fc_ops function to handle the request given in the args.  The dip
519  * and handle are passed back to the framework/driver to distinguish
520  * requests, if necessary.  The argument array is an array of fc_cell_t's
521  * and is defined in fcode.h
522  *
523  * The ops function should return -1 to indicate that the service name is
524  * unknown and return the value 0 to indicate that the service name was known
525  * and processed (even if it failed).  ops functions may chain, using the
526  * return code to communicate if the current function handled the service
527  * request. Using this technique, the driver can provide certain ops functions
528  * and allow a framework ops function to handle standardized ops functions,
529  * or work hand in hand with a framework function so both can handle an op.
530  * If an ops function is not handled, thus returning -1 to the driver, the
531  * driver will log an error noting the name of the service and return the
532  * error to the caller.
533  */
534 typedef int (fc_ops_t)(dev_info_t *, fco_handle_t, fc_ci_t *);
535 
536 extern fc_ops_t fc_ops;
537 extern fc_ops_t pci_fc_ops;
538 extern fc_ops_t gp2_fc_ops;
539 
540 /*
541  * Internal structure used to enque an fcode request
542  * The 'next' and 'busy' fields are protected by a mutex.
543  * Thread synchronization is accomplished via use of the 'busy' field.
544  */
545 struct fc_request {
546 	struct fc_request *next;	/* Next in chain (private) */
547 	int		busy;		/* Waiters flag (private; see below) */
548 	int		error;		/* Interpreter return code (private) */
549 	dev_info_t	*ap_dip;	/* Attachment point. ie: pci nexus */
550 	fc_ops_t	*ap_ops;	/* driver's fcode ops function */
551 	fco_handle_t	handle;		/* Caller's private identifier */
552 	timeout_id_t	timeout;	/* Timeout identifier */
553 };
554 
555 /*
556  * Values for 'busy'.  The requester initializes the field to FC_R_INIT (0),
557  * then waits for it be set to FC_R_DONE.  The framework sets it to
558  * FC_R_BUSY while working on the request so it can distinguish between
559  * an inactive and an active request.
560  */
561 #define	FC_R_INIT	0		/* initialized, on queue */
562 #define	FC_R_BUSY	1		/* request is active, busy */
563 #define	FC_R_DONE	2		/* request is done and may be deq'd */
564 
565 /*
566  * Function to call to invoke the fcode interpreter.
567  *
568  * This function will wait and return when the interpreter either
569  * completes successfully or fails, returning pass/fail status as
570  * the return code.  Interim calls to the driver's ops function will
571  * be made for both priv. ops and to create device nodes and properties.
572  *
573  * Calling this function will log a message to userland to request the
574  * eventd to start the userland fcode interpreter process. The interpreter
575  * opens /dev/fcode, which clones an instance of the driver, and then
576  * waits in a 'read' until there's an active request.
577  * XXX: For the prototype, we can start it manually or use an init.d script.
578  *
579  * 'ap' is the attachment point dip: that is, the driving parent's dev_info_t
580  * ie: for pci devices, this will be the dip of the pci nexus.
581  *
582  * The 'handle' is provided for the caller, and can be used to
583  * identify the request along with the attachment point dip, both
584  * of which will be passed back to the driver's ops function.
585  * The handle is allocated first by calling a bus-specific
586  * <bus>_ops_handle_alloc function.
587  *
588  * ops functions may chain; an ops function should return -1 if
589  * the call was not recognized, or 0 if the call was recognized.
590  */
591 extern int fcode_interpreter(dev_info_t *, fc_ops_t *, fco_handle_t);
592 
593 /*
594  * The fcode implementation uses this function to wait for and 'de-queue'
595  * an fcode request.  It's triggered by a 'read' request from the
596  * userland interpreter. It uses a 'sig' form of waiting (cv_wait_sig),
597  * so the interpreter can interrupt the read.
598  */
599 extern struct fc_request *fc_get_request(void);
600 
601 /*
602  * When the fcode implementation is finished servicing a request, it calls this
603  * function to mark the request as done and to signal the originating thread
604  * (now waiting in fcode_interpreter) that the request is done.
605  */
606 extern void fc_finish_request(struct fc_request *);
607 
608 /*
609  * The fcode implementation uses these functions to manage
610  * resource items and resource lists ...
611  */
612 extern void fc_add_resource(fco_handle_t, struct fc_resource *);
613 extern void fc_rem_resource(fco_handle_t, struct fc_resource *);
614 extern void fc_lock_resource_list(fco_handle_t);
615 extern void fc_unlock_resource_list(fco_handle_t);
616 
617 /*
618  * ops common and helper functions
619  */
620 extern int fc_fail_op(dev_info_t *, fco_handle_t, fc_ci_t *);
621 extern int fc_success_op(dev_info_t *, fco_handle_t, fc_ci_t *);
622 
623 extern int fc_syntax_error(fc_ci_t *, char *);
624 extern int fc_priv_error(fc_ci_t *, char *);
625 
626 /*
627  * Recharacterized ddi functions we need to define ...
628  *
629  * The only difference is we call through the attachment point driver,
630  * as a proxy for the child that isn't yet attached. The ddi functions
631  * optimize these functions by not necessarily calling through the
632  * attachment point driver.
633  */
634 int fc_ddi_dma_alloc_handle(dev_info_t *dip, ddi_dma_attr_t *attr,
635     int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep);
636 int fc_ddi_dma_buf_bind_handle(ddi_dma_handle_t handle, struct buf *bp,
637     uint_t flags, int (*waitfp)(caddr_t), caddr_t arg,
638     ddi_dma_cookie_t *cookiep, uint_t *ccountp);
639 int fc_ddi_dma_unbind_handle(ddi_dma_handle_t handle);
640 void fc_ddi_dma_free_handle(ddi_dma_handle_t *handlep);
641 int fc_ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, uint_t whom);
642 
643 /*
644  * The ndi prop functions aren't appropriate for the interpreter.
645  * We create byte-array, untyped properties.
646  */
647 
648 int fc_ndi_prop_update(dev_t, dev_info_t *, char *, uchar_t *, uint_t);
649 
650 /*
651  * The setup and teardown parts of physio()
652  */
653 int fc_physio_setup(struct buf **bpp, void *io_base, size_t io_len);
654 void fc_physio_free(struct buf **bpp, void *io_base, size_t io_len);
655 
656 /*
657  * debugging macros
658  */
659 extern int fcode_debug;
660 #define	dcmn_err(level, args) if (fcode_debug >= level) cmn_err args
661 
662 #ifdef DEBUG
663 
664 void fc_debug(char *, uintptr_t, uintptr_t,
665     uintptr_t, uintptr_t, uintptr_t);
666 
667 #define	FC_DEBUG0(level, flag, s) if (fcode_debug >= level) \
668     fc_debug(s, 0, 0, 0, 0, 0)
669 #define	FC_DEBUG1(level, flag, fmt, a1) if (fcode_debug >= level) \
670     fc_debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0);
671 #define	FC_DEBUG2(level, flag, fmt, a1, a2) if (fcode_debug >= level) \
672     fc_debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
673 #define	FC_DEBUG3(level, flag, fmt, a1, a2, a3) \
674     if (fcode_debug >= level) \
675     fc_debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), (uintptr_t)(a3), 0, 0);
676 #else
677 #define	FC_DEBUG0(level, flag, s)
678 #define	FC_DEBUG1(level, flag, fmt, a1)
679 #define	FC_DEBUG2(level, flag, fmt, a1, a2)
680 #define	FC_DEBUG3(level, flag, fmt, a1, a2, a3)
681 #endif
682 
683 
684 #endif	/* defined(_KERNEL) */
685 
686 #ifdef	__cplusplus
687 }
688 #endif
689 
690 #endif	/* _SYS_FCODE_H */
691