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