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