Contained Within
Find More Documentation
Featured Support Resources
| PDF로 이 문서 다운로드
Summary of Solaris 2.4 DDI/DKI Services
C
- This chapter discusses, by category, the interfaces provided by the Solaris 2.4 DDI/DKI. After each category is introduced, each function in that category is listed with a brief description. These descriptions should not be considered complete or definitive, nor do they provide a thorough guide to usage. The descriptions are intended to describe what the functions do in general terms, and what the arguments and return values mean. See the manual pages for more detailed information. The categories are:
-
-
- STREAMS interfaces are not discussed here; to learn about them, see the STREAMS Programmer's Guide.
buf(9S) Handling
- These interfaces manipulate the buf(9S) data structure. It is used to encode block I/O transfer requests, but some character drivers also use buf(9S) to encode character I/O requests with physio(9F). Drivers that use buf(9S) as their primary means of encoding I/O requests have to implement a strategy(9E) routine. See Chapter 9, "Drivers for Block Devices," and Chapter 8, "Drivers for Character Devices" for more information.
-
-
void biodone(struct buf *bp);
-
biodone(9F) marks the I/O described by the buf(9S) structure pointed to by bp as complete by setting the B_DONE flag in bp->b_flags. biodone(9F) then notifies any threads waiting in biowait(9F) for this buffer. Call biodone(9F) on bp when the I/O request it encodes is finished.
-
-
void bioerror(struct buf *bp, int error);
-
bioerror(9F) marks the error bits in the I/O described by the buf(9S) structure pointed to by bp with error.
-
-
void bioreset(struct buf *bp);
bioreset(9F) is used to reset the buf(9S) structure pointed to by bp
allowing a device driver to reuse privately allocated buffers. bioreset(9F)
resets the buffer header to its initially allocated state.
int biowait(struct buf *bp);
-
biowait(9F) suspends the calling thread until the I/O request described by bp completes. A call to biodone(9F) unblocks the waiting thread. Usually, if a driver does synchronous I/O, it calls biowait(9F) in its strategy(9E) routine, and calls biodone(9F) in its interrupt handler when the request is complete.
-
biowait(9F) is usually not called by the driver, instead it is called by physio(9F), or by the file system after calling strategy(9F). The driver is responsible for calling biodone(9F) when the I/O request is complete.
-
-
void bp_mapin(struct buf *bp);
-
bp_mapin(9F) maps the data buffer associated with the buf(9S) structure pointed to by bp into the kernel virtual address space so the driver can access it. Programmed I/O device drivers often use bp_mapin(9F) because they have to transfer data explicitly between the buf(9S) structure's buffer and a device buffer. See "bp_mapin( )" on page 177 for more information.
-
-
void bp_mapout(struct buf *bp);
bp_mapout(9F) unmaps the data buffer associated with the buf(9S) structure
pointed to by bp. The buffer must have been mapped previously by
bp_mapin(9F). bp_mapout(9F) can only be called from user or kernel context.
void clrbuf(struct buf *bp);
-
clrbuf(9F) zeroes bp->b_bcount bytes starting at bp->b_un.b_addr.
-
-
void disksort(struct diskhd *dp, struct buf *bp);
-
disksort(9F) implements a queueing strategy for block I/O requests to block-oriented devices. dp is a pointer to a diskhd structure that represents the head of the request queue for a the disk. disksort(9F) sorts bp into this queue in ascending order of cylinder number. The cylinder number is stored in the b_resid field of the buf(9S) structure. This strategy minimizes seek time for some disks.
-
-
void freerbuf(struct buf *bp);
freerbuf(9F) frees the buf(9S) structure pointed to by bp. The structure must
have been allocated previously by getrbuf(9F).
int geterror(struct buf *bp);
-
geterror(9F) returns the error code stored in bp if the B_ERROR flag is set in bp->b_flags. It returns zero if no error occurred.
-
-
struct buf *getrbuf(long sleepflag);
-
getrbuf(9F) allocates a buf(9S) structure and returns a pointer to it. sleepflag should be either KM_SLEEP or KM_NOSLEEP, depending on whether getrbuf(9F) should wait for a buf(9S) structure to become available if one cannot be allocated immediately.
-
-
int physio(int (*strat)(struct buf *), struct buf *bp,
dev_t dev, int rw, void (*mincnt)(struct buf *),
struct uio *uio);
-
physio(9F) translates a read or write I/O request encoded in a uio(9S) structure into a buf(9S) I/O request. strat is a pointer to a strategy(9E) routine which physio(9F) calls to handle the I/O request. If bp is NULL, physio(9F) allocates a private buf(9S) structure.
- Before calling strategy(9E), physio(9F) locks down the memory referred to by the buf(9S) structure (initialized from the uio(9S) structure). For this reason, many drivers which do DMA must use physio(9F) as it is the only way to lock down memory.
- In most block device drivers, read(9E) and write(9E) handle raw I/O requests, and consist of little more than a call to physio(9F).
-
-
void minphys(struct buf *bp);
-
minphys(9F) can be passed as the mincnt argument to physio(9F). This causes physio(9F) to make I/O requests to the strategy routine that are no larger than the system default maximum data transfer size. If the original uio(9S) I/O request is to transfer a greater amount of data than minphys(9F) allows, physio(9F) calls strategy(9E) repeatedly.
Copying Data
- These interfaces are data copying utilities, used both for copying data within the kernel, and for copying data between the kernel and an application program.
-
-
void bcopy(caddr_t from, caddr_t to, size_t bcount);
-
bcopy(9F) copies count bytes from the location pointed to by from to the location pointed to by to.
-
-
int copyin(caddr_t userbuf, caddr_t driverbuf,
size_t cn);
-
copyin(9F) copies data from an application program's virtual address space to the kernel virtual address space, where the driver can address the data. The driver developer must ensure that adequate space is allocated for driverbuf.
-
-
int copyout(caddr_t driverbuf, caddr_t userbuf,
size_t cn);
-
copyout(9F) copies data from the kernel virtual address space to an application program's virtual address space.
-
-
int ddi_copyin(caddr_t buf, caddr_t driverbuf,
size_t cn, int flags);
- This routine is designed for use in driver ioctl (9E) routines. It copies data from a source address to a driver buffer. The driver developer must ensure that adequate space is allocated for the destination address.
- The flags argument is used to determine the address space information about buf. If the FKIOCTL flag is set, it indicates that buf is a kernel address, and ddi_copyin (9F) behaves like bcopy (9F). Otherwise buf is interpreted as a user buffer address, and ddi_copyin (9F) behaves like copyin(9F).
- The value of the flags argument to ddi_copyin (9F) should be passed through directly from the mode argument of ioctl (9E) untranslated.
-
-
int ddi_copyout(caddr_t driverbuf, caddr_t buf,
size_t cn, int flags);
- This routine is designed for use in driver ioctl (9E) routines for drivers that support layered I/O controls. ddi_copyout (9F) copies data from a driver buffer to a destination address, buf.
- The flags argument is used to determine the address space information about buf. If the FKIOCTL flag is set, it indicates that buf is a kernel address, and ddi_copyout (9F) behaves like bcopy (9F). Otherwise buf is interpreted as a user buffer address, and ddi_copyin (9F) behaves like copyout(9F).
- The value of the flags argument to ddi_copyout(9F) should be passed through directly from the mode argument of ioctl (9E) untranslated.
Device Access
- These interfaces verify the credentials of application threads making system calls into drivers. They are sometimes used in the open(9E) entry point to restrict access to a device, though this is usually achieved with the permissions on the special files in the file system.
-
-
int drv_priv(cred_t *credp);
-
drv_priv(9F) returns zero if the credential structure pointed to by credp is that of a privileged thread. It returns EPERM otherwise. Only use drv_priv(9F) in place of calls to the obsolete suser() function and when making explicit checks of a calling thread's UID.
Device Configuration
- These interfaces are used in setting up a driver and preparing it for use. Some of these routines handle the dynamic loading of device driver modules into the kernel, and some manage the minor device nodes in /devices that are the interface to a device for application programs. All of these routines are intended to be called in the driver's _init(9E), _fini(9E), _info(9E), attach(9E), detach(9E), and probe(9E) entry points.
-
-
int ddi_create_minor_node(dev_info_t *dip, char *name,
int spec_type, int minor_num, char *node_type,
int is_clone);
-
ddi_create_minor_node(9F) advertises a minor device node, which will eventually appear in the /devices directory and refer to the device specified by dip.
-
-
void ddi_remove_minor_node(dev_info_t *dip,
char *name);
-
ddi_remove_minor_node(9F) removes the minor device node name for the device dip from the system. name is assumed to have been created by ddi_create_minor_node(9F). If name is NULL, all minor node information is removed.
-
-
int mod_install(struct modlinkage *modlinkage);
-
mod_install(9F) links the calling driver module into the system and prepares the driver to be used. modlinkage is a pointer to the modlinkage structure defined in the driver. mod_install(9F) must be called from the _init(9E) entry point.
-
-
int mod_remove(struct modlinkage *modlinkage);
-
mod_remove(9F) unlinks the calling driver module from the system. modlinkage is a pointer to the modlinkage structure defined in the driver. mod_remove(9F) must be called from the _fini(9E) entry point.
-
-
int mod_info(struct modlinkage *modlinkage,
struct modinfo *modinfop);
-
mod_info(9F) reports the status of a dynamically loadable driver module. It must be called from the _info(9E) entry point.
Device Information
- These interfaces provide information to the driver about a device, such as whether the device is self-identifying, what instance number the system has assigned to a device instance, the name of the dev_info node for the device, and the dev_info node of the device's parent.
-
-
int ddi_dev_is_sid(dev_info_t *dip);
ddi_dev_is_sid(9F) returns DDI_SUCCESS if the device identified by dip is
self-identifying (see "Device Identification" on page 14). Otherwise, it returns
DDI_FAILURE.
int ddi_get_instance(dev_info_t *dip);
-
ddi_get_instance(9F) returns the instance number assigned by the system for the device instance specified by dip.
-
-
char *ddi_get_name(dev_info_t *dip);
-
ddi_get_name(9F) returns a pointer to a character string that is the name of the dev_info tree node specified by dip. ddi_get_name(9F) should be called in the identify(9E) entry point and the result compared to the name of the device.
-
-
dev_info_t *ddi_get_parent(dev_info_t *dip);
ddi_get_parent(9F) returns the dev_info_t pointer for the parent
dev_info node of the passed node, identified by dip.
int ddi_slaveonly(dev_info_t *dip);
-
ddi_slaveonly(9F) returns DDI_SUCCESS if the device indicated by dip is installed in a slave access only bus slot. It returns DDI_FAILURE otherwise.
DMA Handling
- These interfaces allocate and release DMA resources for devices capable of directly accessing system memory. The family of setup functions are all wrappers around the main setup function, ddi_dma_setup(9F). The wrappers make it easier to allocate DMA resources for use with kernel virtual addresses (ddi_dma_addr_setup(9F)), and buf(9S) structures
- (ddi_dma_buf_setup(9F)). The setup functions pass back a pointer to a DMA handle, which identifies the allocated DMA resources in future calls to other DMA handling functions.
- The DMA setup functions take a pointer to a DMA limits structure as an argument. The DMA limits structure allows any constraints which the device's DMA controller may impose on DMA transfers to be specified, such as a limited transfer size.
- The DMA setup functions also provide a callback mechanism where a function can be specified to be called later if the requested mapping can't be set up immediately.
- The DMA window functions allow resources to be allocated for a large object. The resources can be moved from one part of the object to another by moving the DMA window.
- The DMA engine functions allow drivers to manipulate the system DMA engine, if there is one. These are currently used on x86 systems.
-
-
int ddi_dma_addr_setup(dev_info_t *dip,
struct as *as, caddr_t addr, u_int len,
u_int flags, int (*waitfp)(caddr_t),
caddr_t arg, ddi_dma_lim_t *lim,
ddi_dma_handle_t *handlep);
-
ddi_dma_addr_setup(9F) allocates resources for an object of length len at kernel address addr, subject to any constraints specified by lim. waitfp is a pointer to a callback function to be called later if the DMA resources cannot be allocated right away. If the resources are allocated successfully, ddi_dma_addr_setup(9F) passes back the DMA handle for the mapping in the location pointed to by handlep. NULL should be passed for as.
-
-
int ddi_dma_buf_setup(dev_info_t *dip, struct buf *bp,
u_int flags, int (*waitfp)(caddr_t),
caddr_t arg, ddi_dma_lim_t *lim,
ddi_dma_handle_t *handlep);
-
ddi_dma_buf_setup(9F) allocates resources for an object described by a buf(9F) structure pointed to by bp, subject to constraints specified by lim. waitfp is a pointer to a callback function to be called later if the DMA resources cannot be allocated right away. If the resources are allocated successfully, ddi_dma_buf_setup(9F) passes back the DMA handle for the resources in the location pointed to by handlep.
-
-
int ddi_dma_burstsizes(ddi_dma_handle_t handle);
-
ddi_dma_burstsizes(9F) returns an integer that encodes the allowed burst sizes for the DMA resources specified by handle. Allowed power of two burst sizes are bit-encoded in the return value. For a mapping that allows only two-byte bursts, for example, the return value would be 0x2. For a mapping that allows 1, 2, 4, and 8 byte bursts, the return value would be 0xf.
-
-
int ddi_dma_coff(ddi_dma_handle_t handle,
ddi_dma_cookie_t *cookiep, off_t *offp);
-
ddi_dma_coff(9F) passes back, in the location pointed to by offp, an offset into a DMA object. The mapping is specified by handle, and the offset offp is derived from the DMA cookie referred to by cookiep. ddi_dma_coff(9F) can be used after a DMA transfer is complete to find out where the DMA controller stopped.
-
-
int ddi_dma_curwin(ddi_dma_handle_t handle,
off_t *offp, u_int *lenp);
-
ddi_dma_curwin(9F) passes back the offset and length of the current DMA window in the locations pointed to by offp and lenp, respectively.
-
-
int ddi_dma_devalign(ddi_dma_handle_t handle,
u_int *alignment, u_int *minxfr);
-
ddi_dma_devalign(9F) passes back, in the location pointed to by alignment, the required alignment for the beginning of a DMA transfer using the resources identified by handle. The alignment will be a power of two. ddi_dma_devalign(9F) also passes back in the location pointed to by minxfr the minimum number of bytes of the mapping that will be read or written in a single transfer.
-
-
int ddi_dma_htoc(ddi_dma_handle_t handle, off_t off,
ddi_dma_cookie_t *cookiep);
-
ddi_dma_htoc(9F) passes back a DMA cookie in the location pointed to by cookiep that represents a DMA transfer starting at off in the DMA resources identified by handle. The DMA cookie is described in ddi_dma_cookie(9S) that contains information about a potential DMA transfer. The field dmac_address contains the transfer address for the DMA controller.
-
-
int ddi_dma_movwin(ddi_dma_handle_t handle,
off_t *offp, u_int *lenp,
ddi_dma_cookie_t *cookiep);
-
ddi_dma_movwin(9F) moves the current DMA window in the mapping identified by handle. The new window offset and length are passed back in the locations pointed to by offp and lenp, respectively. If a pointer to a DMA cookie structure is passed in cookiep, ddi_dma_movwin(9F) calls ddi_dma_htoc(9F) passes back a new DMA cookie in the location pointed to by cookiep.
-
-
int ddi_dma_nextseg(ddi_dma_win_t win,
ddi_dma_seg_t seg, ddi_dma_seg_t *nseg);
-
ddi_dma_nextseg(9F) gets the next DMA segment within the specified window win. If the current segment is NULL, the first DMA segment within the window is returned.
-
-
int ddi_dma_nextwin(ddi_dma_handle_t handle,
ddi_dma_win_t win, ddi_dma_win_t *nwin);
- ddi_dma_nextwin(9F) shifts the current DMA window win within the object referred to by handle to the next DMA window nwin. If the current window is NULL, the first window within the object is returned.
-
-
int ddi_dma_segtocookie(ddi_dma_seg_t seg,
off_t *offp, off_t *lenp,
ddi_dma_cookie_t *cookiep);
-
ddi_dma_segtocookie(9F) takes a DMA segment and fills in the cookie pointed to by cookiep with the appropriate address, length, and bus type to be used to program the DMA engine. ddi_dma_segtocookie(9F) also fills in *offp and *lenp, which specify the range within the object.
-
-
int ddi_dma_setup(dev_info_t *dip,
struct ddi_dma_req *dmareqp,
ddi_dma_handle_t *handlep);
-
ddi_dma_setup(9F) is the main DMA resource allocation function. It allocates resources based on the DMA request structure pointed to by dmareqp, and passes back a DMA handle that identifies the mapping in the location pointed to by handlep.
-
-
int ddi_dma_free(ddi_dma_handle_t handle);
ddi_dma_free(9F) calls ddi_dma_sync(9F) and frees the resources
associated with the DMA mapping identified by handle.
int ddi_dma_sync(ddi_dma_handle_t handle, off_t off,
u_int length, u_int type);
-
ddi_dma_sync(9F) assures that any CPU and the device see the same data starting at off bytes into the DMA resources identified by handle and continuing for len bytes. type should be:
-
-
DDI_DMA_SYNC_FORDEV to make sure the device sees any changes made by a CPU.
-
DDI_DMA_SYNC_FORCPU to make sure all CPUs see any changes made by the device.
-
DDI_DMA_SYNC_FORKERNEL, similar to DDI_DMA_SYNC_FORCPU, except that only the kernel view of the object is synchronized.
-
-
int ddi_dmae_alloc(dev_info_t *dip, int chnl,
int (*dmae_waitfp)(), caddr_t arg);
ddi_dmae_alloc(9F) allocates a DMA channel from the system DMA engine.
It must be called prior to any operation on a channel.
int ddi_dmae_release(dev_info_t *dip, int chnl);
-
ddi_dmae_release(9F) releases a previously allocated DMA channel.
-
-
int ddi_dmae_prog(dev_info_t *dip,
struct ddi_dmae_req *dmaereqp,
ddi_dma_cookie_t *cookiep, int chnl);
- The ddi_dmae_prog(9F) function programs the DMA channel for an operation. This function allows access to various capabilities of the DMA engine hardware. It disables the channel prior to setup, and enables the channel before returning.
- The DMA address and count are specified by passing ddi_dmae_prog(9F) a cookie obtained from ddi_dma_segtocookie(9F). Other DMA engine parameters are specified by the DMA engine request structure passed in through dmaereqp. The fields of that structure are documented in ddi_dmae_req(9S).
-
-
int ddi_dmae_disable(dev_info_t *dip, int chnl);
The ddi_dmae_disable(9F) function disables the DMA channel so that it no
longer responds to a device's DMA service requests.
int ddi_dmae_enable(dev_info_t *dip, int chnl);
- The ddi_dmae_enable(9F) function enables the DMA channel for operation. This may be used to re-enable the channel after a call to ddi_dmae_disable(9F). The channel is automatically enabled after successful programming by ddi_dmae_prog(9F).
-
-
int ddi_dmae_stop(dev_info_t *dip, int chnl);
The ddi_dmae_stop(9F) function disables the channel and terminates any
active operation.
int ddi_dmae_getcnt(dev_info_t *dip, int chnl,
int *countp);
- The ddi_dmae_getcnt(9F) function examines the count register of the DMA channel and sets (*countp) to the number of bytes remaining to be transferred. The channel is assumed to be stopped.
-
-
int ddi_dmae_1stparty(dev_info_t *dip, int chnl);
- The ddi_dmae_1stparty(9F) function is used, by device drivers using first-party DMA, to configure a channel in the system's DMA engine to operate in a ''slave'' mode.
-
-
int ddi_dmae_getlim(dev_info_t *dip,
ddi_dma_lim_t *limitsp);
- The ddi_dmae_getlim(9F) function fills in the DMA limit structure, pointed to by limitsp, with the DMA limits of the system DMA engine. This limit structure must be passed to the DMA setup routines so that they will know how to break the DMA request into windows and segments. If the device has any particular restrictions on transfer size or granularity (for example, a disk sector size), the driver should further restrict the values in the structure members before passing them to the DMA setup routines. The driver must not relax any of the restrictions embodied in the structure after it is filled in by ddi_dmae_getlim(9F).
-
-
int ddi_iomin(dev_info_t *dip, int initial,
int streaming);
-
ddi_iomin(9F) returns an integer that encodes the required alignment and the minimum number of bytes that must be read or written by the DMA controller of the device identified by dip. ddi_iomin(9F) is like ddi_dma_devalign(9F), but the memory object is assumed to be primary memory, and the alignment is assumed to be equal to the minimum possible transfer.
-
-
int ddi_iopb_alloc(dev_info_t *dip,
ddi_dma_lim_t *limits, u_int length,
caddr_t *iopbp);
-
ddi_iopb_alloc(9F) allocates a block of length bytes of memory, subject to constraints specified by limits. A block of memory so allocated is commonly called an "I/O parameter block", or IOPB, and is usually used to encode a device command. This block of consistent memory can be directly accessed by the device. A pointer to the allocated IOPB is passed back in the location pointed to by iopbp.
-
-
void ddi_iopb_free(caddr_t iopb);
-
ddi_iopb_free(9F) frees the I/O parameter block pointed to by iopb, which must have been allocated previously by ddi_iopb_alloc(9F).
Flow of Control
- These interfaces influence the flow of program control in a driver. These are mostly callback mechanisms, functions that schedule another function to run at a later time. Many drivers schedule a function to run every so often to check on the status of the device, and possibly issue an error message if some strange condition is detected.
-
Note - The detach(9E) entry point must assure that no callback functions are pending in the driver before returning successfully. See Chapter 5, "Autoconfiguration."
-
-
int timeout(void (*ftn)(caddr_t), caddr_t arg,
long ticks);
-
timeout(9F) schedules the function pointed to by ftn to be run after ticks clock ticks have elapsed. arg is passed to the function when it is run. timeout(9F) returns a "timeout ID" that can be used to cancel the timeout later.
-
-
int untimeout(int id);
-
untimeout(9F) cancels the timeout indicated by the timeout ID id. If the number of clock ticks originally specified to timeout(9F) have not elapsed, the callback function will not be called.
Interrupt Handling
- These interfaces manage device interrupts and software interrupts. The basic model is to register with the system an interrupt handling function to be called when a device interrupts or a software interrupt is triggered.
-
-
int ddi_add_intr(dev_info_t *dip, u_int inumber,
ddi_iblock_cookie_t *iblock_cookiep,
ddi_idevice_cookie_t *idevice_cookiep,
u_int (*int_handler)(caddr_t),
caddr_t int_handler_arg);
-
ddi_add_intr(9F) tells the system to call the function pointed to by int_handler when the device specified by dip issues the interrupt identified by inumber. ddi_add_intr(9F) passes back an interrupt block cookie in the location pointed to by iblock_cookiep, and an interrupt device cookie in the location pointed to by idevice_cookiep. The interrupt block cookie is used to initialize mutual exclusion locks (mutexes) and other synchronization variables. The device interrupt cookie is used to program the level at which the device interrupts, for those devices that support such programming.
-
-
void ddi_remove_intr(dev_info_t *dip, u_int inumber,
ddi_iblock_cookie_t iblock_cookie);
-
ddi_remove_intr(9F) tells the system to stop calling the interrupt handler registered for the interrupt inumber on the device identified by dip. iblock_cookie is the interrupt block cookie that was returned by ddi_add_intr(9F) when the interrupt handler was set up. Device interrupts must be disabled before calling ddi_remove_intr(9F), and always call ddi_remove_intr(9F) in the detach(9E) entry point before returning successfully (if any interrupts handlers were added).
-
-
int ddi_add_softintr(dev_info_t *dip, int preference,
ddi_softintr_t *idp, ddi_iblock_cookie_t *ibcp,
ddi_idevice_cookie_t *idcp,
u_int (*int_handler)(caddr_t),
caddr_t int_handler_arg);
-
ddi_add_softintr(9F) tells the system to call the function pointed to by int_handler when a certain software interrupt is triggered. ddi_add_softintr(9F) returns a software interrupt ID in the location pointed to by idp. This ID is later used by ddi_trigger_softintr(9F) to trigger the software interrupt.
-
-
void ddi_trigger_softintr(ddi_softintr_t id);
-
ddi_trigger_softintr(9F) triggers the software interrupt identified by id. The interrupt handling function that was set up for this software interrupt by ddi_add_softintr(9F) is then called.
-
-
void ddi_remove_softintr(ddi_softintr_t id);
-
ddi_remove_softintr(9F) tells the system to stop calling the software interrupt handler for the software interrupt identified by id. If the driver has soft interrupts registered, it must call ddi_remove_softintr(9F) in the detach(9E) entry point before returning successfully.
-
-
int ddi_dev_nintrs(dev_info_t *dip, int *result);
-
ddi_dev_nintr(9F) passes back in the location pointed to by result the number of different interrupt specifications that the device indicated by dip can generate. This is useful when dealing with a device that can interrupt at more than one level.
-
-
int ddi_intr_hilevel(dev_info_t *dip, u_int inumber);
-
ddi_intr_hilevel(9F) returns non-zero if the system considers the interrupt specified by inumber on the device identified by dip to be high level. Otherwise, it returns zero.
Kernel Statistics
- These interfaces allow device drivers to store statistics about the device in the kernel for later retrieval by applications.
-
-
kstat_t *kstat_create(char *module, int instance,
char *name, char *class, uchar_t type,
ulong_t ndata, uchar_t ks_flag);
-
kstat_create(9F) allocates and performs necessary system initialization of a kstat(9S) structure. After a successful call to kstat_create(9F) the driver must perform any necessary initialization of the data structure and then use kstat_install(9F) to make the kstat(9S) structure accessible to user land applications.
-
-
void kstat_delete(kstat_t *ksp);
kstat_delete(9F) removes the kstat(9S) structure pointed to by ksp
from the kernel statistics data and frees associated system resources.
void kstat_install(kstat_t *ksp);
kstat_install(9F) allows the kstat(9S) structure pointed to by ksp to
be accessible by the user land applications.
void kstat_named_init(kstat_named_t *knp, char *name,
uchar_t data_type);
-
kstat_named_init(9F) associates the name pointed to by name and the type specified in data_type with the kstat_named(9S) structure pointed to by knp.
-
-
void kstat_waitq_enter(kstat_io_t *kiop);
-
kstat_waitq_enter(9F) is used to update the kernel_io(9S) structure pointed to by kiop indicating that a request has arrived but has not yet be processed.
-
-
void kstat_waitq_exit(kstat_io_t *kiop);
kstat_waitq_exit(9F) is used to update the kernel_io(9S) structure
pointed to by kiop indicating that the request is about to be serviced.
void kstat_runq_enter(kstat_io_t *kiop);
-
kstat_runq_enter(9F) is used to update the kernel_io(9S) structure pointed to by kiop indicating that the request is in the process of being serviced. kstat_runq_enter(9F) is generally invoked after a call to kstat_waitq_exit(9F).
-
-
void kstat_runq_exit(kstat_io_t *kiop);
-
kstat_runq_exit(9F)is used to update the kernel_io(9S) structure pointed to by kiop indicating that the request is serviced.
-
-
void kstat_waitq_to_runq(kstat_io_t *kiop);
-
kstat_waitq_to_runq(9F) is used to update the kernel_io(9S) structure pointed to by kiop indicating that the request is transitioning from one state to the next. kstat_waitq_to_runq(9F) is used when a driver would normally call kstat_waitq_exit(9F) followed immediately by
-
-
kstat_runq_enter(9F).
void kstat_runq_to_waitq(kstat_io_t *kiop);
-
kstat_runq_to_waitq(9F) is used to update the kernel_io(9S) structure pointed to by kiop indicating that the request is transitioning from one state to the next. kstat_runq_to_waitq(9F) is used when a driver would normally call kstat_runq_exit(9F) followed immediately by a call to kstat_waitq_enter(9F).
Memory Allocation
- These interfaces dynamically allocate memory for the driver to use.
-
-
void *kmem_alloc(size_t size, int flag);
-
kmem_alloc(9F) allocates a block of kernel virtual memory of length size and returns a pointer to it. If flag is KM_SLEEP, kmem_alloc(9F) may block waiting for memory to become available. If flag is KM_NOSLEEP, kmem_alloc(9F) returns NULL if the request cannot be satisfied immediately.
-
-
void kmem_free(void *cp, size_t size);
kmem_free(9F) releases a block of memory of length size starting at address
addr that was previously allocated by kmem_alloc(9F). size must be the
original amount allocated.
void *kmem_zalloc(size_t size, int flags);
-
kmem_zalloc(9F) calls kmem_alloc(9F) to allocate a block of memory of length size, and calls bzero(9F) on the block to zero its contents before returning its address.
Polling
- These interfaces support the poll(2) system call, which provides a mechanism for application programs to "poll" character-oriented devices, inquiring about their readiness to perform certain I/O operations. See the poll(2) manual page for details.
-
-
int nochpoll(dev_t dev, short events, int anyyet,
short *reventsp, struct pollhead **pollhdrp);
Use nochpoll(9F) as the chpoll entry in the cb_ops(9S) structure if the
driver does not support polling.
void pollwakeup(struct pollhead *php, short event);
- If the driver does implement a chpoll(9E) entry point to support polling, it should call pollwakeup(9F) whenever the event occurs.
Printing System Messages
- These interfaces are functions that display messages on the system console.
-
-
void cmn_err(int level, char *format, ...);
-
cmn_err(9F) is the mechanism for printing messages on the system console. level may be one of CE_NOTE, CE_WARN, CE_CONT, or CE_PANIC. CE_NOTE indicates a purely informational message. CE_WARN indicates a warning to the user. CE_CONT continues a previous message. And CE_PANIC issues a fatal error and crashes the system. Use CE_PANIC only for unrecoverable system errors!
- Whenever possible, CE_CONT should be used to print system messages. Note that CE_PANIC, CE_NOTE, and CE_WARN cause cmn_err(9F) to always append a new line to the message.
-
-
void ddi_report_dev(dev_info_t *dip);
-
ddi_report_dev(9F) possibly prints a message announcing the presence of a device on the system. Call this function before returning from a successful attach(9E).
-
-
char *sprintf(char *buf, const char *fmt, ...);
sprintf(9F) is just like the C library's sprintf(3). Use it to format a message
and place it in buf.
void vcmn_err(int level, char *format, va_list ap);
-
vcmn_err(9F) is a version of cmn_err(9F) that uses varargs (see the stdarg(5) manual page).
-
-
char *vsprintf(char *buf, const char *fmt, va_list ap);
-
vsprintf(9F) is a version of sprintf(9F) that uses varargs (see the stdarg(5) manual page).
Process Signaling
- These interfaces allow a device driver to send signals to a process in a multithread safe manner.
-
-
void *proc_ref(void);
proc_ref(9F) retrieves an unambiguous reference to the process of the
current thread for signalling purposes.
int proc_signal(void *pref, int sig);
-
proc_signal(9F) sends the signal indicated in sig to the process defined by pref that has been referenced by proc_ref(9F).
-
-
void proc_unref(void *pref);
-
proc_unref(9F) unreferences the process defined by pref.
Properties
- Properties are name-value pairs defined by the PROM or the kernel at boot time, by hardware configuration files, or by calls to ddi_prop_create(9F). These interfaces handle creating, modifying, retrieving, and reporting properties.
-
-
int ddi_prop_create(dev_t dev, dev_info_t *dip,
int flags, char *name, caddr_t valuep,
int length);
-
ddi_prop_create(9F) creates a property of the name pointed to by name and the value pointed to by valuep.
-
-
int ddi_prop_modify(dev_t dev, dev_info_t *dip,
int flags, char *name, caddr_t valuep,
int length);
-
ddi_prop_modify(9F) changes the value of the property identified by name to the value pointed to by valuep.
-
-
int ddi_prop_remove(dev_t dev, dev_info_t *dip,
char *name);
-
ddi_prop_remove(9F) frees the resources associated with the property identified by name.
-
-
void ddi_prop_remove_all(dev_info_t *dip);
-
ddi_prop_remove_all(9F) frees the resources associated with all properties belonging to dip. ddi_prop_remove_all(9F) should be called in the detach(9E) entry point if the driver defines properties.
-
-
int ddi_prop_undefine(dev_t dev, dev_info_t *dip,
int flags, char *name);
-
ddi_prop_undefine(9F) marks the value of the property identified by name as temporarily undefined. The property continues to exist, however, and may be redefined later using ddi_prop_modify(9F).
-
-
int ddi_prop_op(dev_t dev, dev_info_t *dip,
ddi_prop_op_t prop_op, int flags, char *name,
caddr_t valuep, int *lengthp);
-
ddi_prop_op(9F) is the generic interface for retrieving properties. ddi_prop_op(9F) should be used as the prop_op(9E) entry in the cb_ops(9S) structure if the driver does not have a prop_op(9E) routine. See "Properties" on page 59 for more information.
-
-
int ddi_getprop(dev_t dev, dev_info_t *dip, int flags,
char *name, int defvalue);
-
ddi_getprop(9F) is a wrapper around ddi_prop_op(9F). It can be used to retrieve boolean and integer sized properties.
-
-
int ddi_getlongprop(dev_t dev, dev_info_t *dip,
int flags, char *name, caddr_t valuep,
int *lengthp);
-
ddi_getlongprop(9F) is a wrapper around ddi_prop_op(9F). It is used to retrieve properties having values of arbitrary length. The value returned is stored in a buffer allocated by kmem_alloc(9F), which the driver must free with kmem_free(9F) when the value is no longer needed.
-
-
int ddi_getlongprop_buf(dev_t dev, dev_info_t *dip,
int flags, char *name, caddr_t valuep,
int *lengthp);
-
ddi_getlongprop_buf(9F) is a wrapper around ddi_prop_op(9F). It is used retrieve a property having a value of arbitrary length and to copy that value into a buffer supplied by the driver. valuep must point to this buffer.
-
-
int ddi_getproplen(dev_t dev, dev_info_t *dip,
int flags, char *name, int *lengthp);
-
ddi_getproplen(9F) is a wrapper around ddi_prop_op(9F) that passes back in the location pointed to by lengthp the length of the property identified by name.
Register and Memory Mapping
- These interfaces support the mapping of device memory and device registers into kernel memory so a device driver can address them.
-
-
int ddi_dev_nregs(dev_info_t *dip, int *resultp);
ddi_dev_nregs(9F) passes back in the location pointed to by resultp the
number of register specifications a device has.
int ddi_dev_regsize(dev_info_t *dip, u_int rnumber,
off_t *resultp);
-
ddi_dev_regsize(9F) passes back in the location pointed to by resultp the size of the register set identified by rnumber on the device identified by dip.
-
-
int ddi_map_regs(dev_info_t *dip, u_int rnumber,
caddr_t *kaddrp, off_t offset, off_t len);
-
ddi_map_regs(9F) maps the register specification identified by rnumber on the device identified by dip into kernel memory starting at offset bytes from the base of the register specification. ddi_map_regs(9F) then passes back in the location pointed to by kaddrp a pointer to the base of the register specification plus offset.
-
-
void ddi_unmap_regs(dev_info_t *dip, u_int rnumber,
caddr_t *kaddrp, off_t offset, off_t len);
-
ddi_unmap_regs(9F) unmaps the register specification identified by rnumber on the device identified by dip. The associated mapping resources are freed, and the driver may no longer address the registers.
-
-
int ddi_segmap(dev_t dev, off_t offset, struct as *as,
caddr_t *addrp, off_t len, u_int prot,
u_int maxprot, u_int flags, cred_t *credp);
-
ddi_segmap(9F) supports the mmap(2) system call, which allows application programs to map device memory into their address spaces. ddi_segmap(9F) should be used as the segmap(9E) entry in the cb_ops(9S) structure.
-
-
int ddi_mapdev(dev_t dev, off_t offset, struct as *as,
caddr_t *addrp, off_t len, u_int prot,
u_int maxprot, u_int flags, cred_t *credp,
struct ddi_mapdev_ctl *ctl,
ddi_mapdev_handle_t *handle, void *devprivate);
-
ddi_mapdev(9F) sets up user mappings to device space in the same manner as ddi_segmap(9F). However, unlike mappings created with ddi_segmap(9F), mappings created with ddi_mapdev(9F) have a set of driver entry points and a mapping handle associated with them. The driver is notified via these entry points in response to user events on the mappings.
-
-
int ddi_mapdev_intercept(ddi_mapdev_handle_t *handle,
off_t offset, off_t len);
int ddi_mapdev_intercept(ddi_mapdev_handle_t *handle,
off_t offset, off_t len);
-
ddi_mapdev_intercept(9F) and ddi_mapdev_nointercept(9F) control whether or not user accesses to the device mappings created by ddi_mapdev(9F) in the specified range will generate an access event notification to the device driver.
-
ddi_mapdev_intercept(9F) tells the system to intercept mapping accesses and invalidates the mapping translations. ddi_mapdev_nointercept(9F) prevents the system from intercepting mapping accesses and validates the mapping translations.
I/O Port Access
- These interfaces support the accessing of device registers from the device driver.
-
-
unsigned char inb(int port);
unsigned short inw(int port);
unsigned long inl(int port);
void repinsb(int port, unsigned char *addr, int count);
void repinsw(int port, unsigned short *addr,
int count);
void repinsd(int port, unsigned long *addr, int count);
- These routines read data of various sizes from the I/O port with the address specified by port.
- The inb(9F), inw(9F), and inl(9F) functions read 8 bits, 16 bits, and 32 bits of data respectively, returning the resulting values.
- The repinsb(9F), repinsw(9F), and repinsd(9F) functions read multiple 8-bit, 16-bit, and 32-bit values, respectively. count specifies the number of values to be read. addr is a pointer to a buffer that will receive the input data. The buffer must be long enough to hold count values of the requested size.
-
-
void outb(int port, unsigned char value);
void outw(int port, unsigned short value);
void outl(int port, unsigned long value);
void repoutsb(int port, unsigned char *addr,
int count);
void repoutsw(int port, unsigned short *addr,
int count);
void repoutsd(int port, unsigned long *addr,
int count);
- These routines write data of various sizes to the I/O port with the address specified by port.
- The outb(9F), outw(9F), and outl(9F) functions write 8 bits, 16 bits, and 32 bits of data respectively, writing the data specified by value.
- The repoutsb(9F), repoutsw(9F), and repoutsd(9F) functions write multiple 8-bit, 16-bit, and 32-bit values, respectively. count specifies the number of values to be written. addr is a pointer to a buffer from which the output values are fetched.
SCSI and SCSA
- These interfaces are part of the Sun Common SCSI Interface, routines that support the writing of "target drivers" to drive SCSI devices. Most of these routines handle allocating SCSI command "packets", formulating SCSI commands within those packets, and "transporting" the packets to the host adapter driver for execution. See Chapter 10, "SCSI Target Drivers."
-
-
struct scsi_pkt *get_pktiopb(struct scsi_address *ap,
caddr_t *datap, int cdblen, int statuslen,
int datalen, int readflag,
int (*callback)(void));
-
get_pktiopb(9F) allocates a SCSI packet structure with a small data area in the system IOPB (I/O parameter block) map for the target device denoted by ap. get_pktiopb(9F) calls scsi_dmaget(9F) to allocate the data area, and calls scsi_resalloc(9F) to allocate the scsi_pkt(9S) structure itself. If func is not NULL_FUNC and resources cannot be allocated right away, the function pointed to by func will be called when resources may have become available. func can call get_pktiopb(9F) again. If callback is SLEEP_FUNC, scsi_dmaget(9F) may block waiting for resources.
- Target drivers often use get_pktiopb() to allocate packets for the REQUEST SENSE or INQUIRY SCSI commands, which need a small amount of cache-consistent memory. Use IOPB packets sparingly, though, because they are allocated from scarce DMA memory resources.
-
-
void free_pktiopb(struct scsi_pkt *pkt, caddr_t datap,
int datalen);
-
free_pktiopb(9F) frees a scsi_pkt(9S) structure and related DMA resources previously allocated by get_pktiopb(9F).
-
-
void makecom_g0(struct scsi_pkt *pkt,
struct scsi_device *devp, int flag,
int cmd, int addr, int cnt);
-
makecom_g0(9F) formulates a group 0 SCSI command for the target device denoted by devp in the scsi_pkt(9S) structure pointed to by pkt. The target must be a non-sequential access device. Use makecom_g0_s(9F) to formulate group 0 commands for sequential access devices.
-
-
void makecom_g0_s(struct scsi_pkt *pkt,
struct scsi_device *devp, int flag, int cmd,
int cnt, int fixbit);
-
makecom_g0_s(9F) formulates a group 0 SCSI command for the sequential access target device denoted by devp in the scsi_pkt(9S) structure pointed to by pkt. Use makecom_g0(9F) to formulate group 0 commands for non-sequential access devices.
-
-
void makecom_g1(struct scsi_pkt *pkt,
struct scsi_device *devp, int flag, int cmd,
int addr, int cnt);
-
makecom_g1(9F) formulates a group 1 SCSI command for the target device denoted by devp in the scsi_pkt(9S) structure pointed to by pkt.
-
-
void makecom_g5(struct scsi_pkt *pkt,
struct scsi_device *devp, int flag, int cmd,
int addr, int cnt);
-
makecom_g5(9F) formulates a group 5 SCSI command for the target device denoted by devp in the scsi_pkt(9S) structure pointed to by pkt.
-
-
int scsi_abort(struct scsi_address *ap,
struct scsi_pkt *pkt);
-
scsi_abort(9F) cancels the command encoded in the scsi_pkt(9S) structure pointed to by pkt at the SCSI address denoted by ap. To indicate the current target, pass in ap the sd_address field of the scsi_device(9S) structure for the target. To abort the current command, pass NULL for pkt.
-
-
struct buf *scsi_alloc_consistent_buf(
struct scsi_address *ap, struct buf *bp,
int datalen, ulong bflags,
int (*callback)(caddr_t), caddr_t arg);
-
scsi_alloc_consistent_buf(9F) allocates a buffer header and the associated data buffer for direct memory access (DMA) transfer. This buffer is allocated from the IOPB space, which is considered consistent memory. If bp is NULL, a new buffer header will be allocated using getrbuf(9F). If datalen is non-zero, a new buffer will be allocated using ddi_iopb_alloc(9F).
- If callback is not NULL_FUNC and the requested DMA resources are not immediately available, the function pointed to by callback will be called when resources may have become available. callback can call scsi_alloc_consistent_buf(9F) again. If callback is SLEEP_FUNC, scsi_alloc_consistent_buf(9F) may block waiting for resources.
-
-
char *scsi_cname(u_char cmd, char **cmdvec);
-
scsi_cname(9F) searches for the command code cmd in the command vector cmdvec, and returns the command name. Each string in cmdvec starts with a one-character command code, followed by the name of the command. To use scsi_cname(9F), the driver must define a command vector that contains strings of this kind for all the SCSI commands it supports.
-
-
struct scsi_pkt *scsi_dmaget(struct scsi_pkt *pkt,
opaque_t dmatoken, int (*callback)(void));
-
scsi_dmaget(9F) allocates resources for an existing scsi_pkt(9S) structure pointed to by pkt. Pass in dmatoken a pointer to the buf(9S) structure that encodes original I/O request.
- If callback is not NULL_FUNC and the requested DMA resources are not immediately available, the function pointed to by callback will be called when resources may have become available. callback can call scsi_dmaget(9F) again. If callback is SLEEP_FUNC, scsi_dmaget(9F) may block waiting for resources.
-
-
void scsi_dmafree(struct scsi_pkt *pkt);
scsi_dmafree(9F) frees the DMA resources previously allocated by
scsi_dmaget(9F) for the scsi_pkt(9S) structure pkt.
char *scsi_dname(int dtype);
scsi_dname(9F) decodes the device type code dtype found in the INQUIRY
data and returns a character string denoting this device type.
void scsi_free_consistent_buf(struct buf *bp);
-
scsi_free_consistent_buf(9F) frees a buffer header and consistent data buffer that was previously allocated using scsi_alloc_consistent_buf(9F).
-
-
int scsi_ifgetcap(struct scsi_address *ap,
char *cap, int whom);
-
scsi_ifgetcap(9F) returns the current value of the host adapter capability denoted by cap for the host adapter servicing the target at the SCSI address pointed to by ap. See the manual page for a list of supported capabilities. whom indicates whether the capability applies only to the target at the specified SCSI address, or to all targets serviced by the host adapter.
-
-
int scsi_ifsetcap(struct scsi_address *ap,
char *cap, int value, int whom);
-
scsi_ifsetcap(9F) sets the current value of the host adapter capability denoted by cap, for the host adapter servicing the target at the SCSI address pointed to by ap, to value. See the manual page for a list of supported capabilities. whom indicates whether the capability applies only to the target at the specified SCSI address, or to all targets serviced by the host adapter.
-
-
struct scsi_pkt *scsi_init_pkt(
struct scsi_address *ap, struct scsi_pkt *pktp,
struct buf *bp, int cmdlen, int statuslen,
int privatelen, int flags,
int (*callback)(caddr_t), caddr_t arg);
-
scsi_init_pkt(9F) requests the transport layer to allocate a command packet for commands and, possibly, data transfers. If pktp is NULL, a new scsi_pkt(9S) is allocated. If bp is non-NULL and contains a valid byte count, the buf(9S) structure is set up for DMA transfer. If bp was allocated by scsi_alloc_consistent_buf(9F), the PKT_CONSISTENT flag must be set. If privatelen is set, additional space is allocated for the pkt_private area of the scsi_pkt(9S) structure, otherwise pkt_private is a pointer that is typically used to store the bp during execution of the command. The flags are set in the command portion of the scsi_pkt(9S) structure.
- If callback is not NULL_FUNC and the requested DMA resources are not immediately available, the function pointed to by callback will be called when resources may have become available. callback can call scsi_init_pkt(9F) again. If callback is SLEEP_FUNC, scsi_init_pkt(9F) may block waiting for resources.
-
-
char *scsi_mname(u_char msg);
-
scsi_mname(9F) decodes the SCSI message code msg and returns the corresponding message string.
-
-
struct scsi_pkt *scsi_pktalloc(
struct scsi_address *ap, int cmdlen,
int statuslen, int (*callback)(void));
-
scsi_pktalloc(9F) allocates and returns a pointer to a SCSI command packet for the target at the SCSI address pointed to by ap. cmdlen and statuslen tell scsi_pktalloc(9F) what size command descriptor block (CDB) and status completion block (SCB) to allocate. Use scsi_pktalloc(9F) only for commands that do no actual I/O. Use scsi_resalloc(9F) for I/O commands.
- If callback is not NULL_FUNC and the requested DMA resources are not immediately available, the function pointed to by callback will be called when resources may have become available. If callback is SLEEP_FUNC, scsi_pktalloct(9F) may block waiting for resources.
-
-
void scsi_pktfree(struct scsi_pkt *pkt);
scsi_pktfree(9F) frees the scsi_pkt(9S) structure pointed to by pkt that
was previously allocated by scsi_pktalloc(9F).
int scsi_poll(struct scsi_pkt *pkt);
-
scsi_poll(9F) transports the command packet pointed to by pkt to the host adapter driver for execution and waits for it to complete before it returns. Use scsi_poll(9F) sparingly and only for commands that must execute synchronously.
-
-
int scsi_probe(struct scsi_device *devp,
int (*callback)(void *));
-
scsi_probe(9F) determines whether a target/lun is present and sets up the scsi_device(9S) structure with inquiry data. scsi_probe(9F) uses the SCSI INQUIRY command to test if the device exists. It may retry the INQUIRY command as appropriate. If scsi_probe(9F) is successful, it will fill in the scsi_inquiry(9S) structure pointed to by the sd_inq member of the scsi_device(9S) structure, and return SCSI_PROBE_EXISTS.
- If callback is not NULL_FUNC and necessary resources are not immediately available, the function pointed to by callback will be called when resources may have become available. If callback is SLEEP_FUNC, scsi_probe(9F) may block waiting for resources.
-
-
struct scsi_pkt *scsi_resalloc(
struct scsi_address *ap, int cmdlen,
int statuslen, opaque_t dmatoken,
int (*callback)(void));
-
scsi_resalloc(9F) allocates and returns a pointer to a SCSI command packet for the target at the SCSI address pointed to by ap. cmdlen and statuslen tell scsi_resalloc(9F) what size command descriptor block (CDB) and
- status completion block (SCB) to allocate. Pass in dmatoken a pointer to the buf(9S) structure encoding the original I/O request. Use scsi_pktalloc(9F) for commands that do no actual I/O.
- If callback is not NULL_FUNC and the requested DMA resources are not immediately available, the function pointed to by callback will be called when resources may have become available. If callback is SLEEP_FUNC, scsi_resalloc(9F) may block waiting for resources.
-
-
int scsi_reset(struct scsi_address *ap, int level);
scsi_reset(9F) requests the host adapter driver to reset the target at the SCSI
address pointed to by ap if level is RESET_TARGET. If level is RESET_ALL,
the entire SCSI bus is reset.
void scsi_resfree(struct scsi_pkt *pkt);
scsi_resfree(9F) frees the scsi_pkt(9S) structure pointed to by pkt and
related DMA resources that were previously allocated by scsi_resalloc(9F).
char *scsi_rname(u_char reason);
scsi_rname(9F) decodes the packet completion reason code reason, and
returns the corresponding reason string.
int scsi_slave(struct scsi_device *devp,
int (*callback)(void));
-
scsi_slave(9F) issues, to the device indicated by devp, a TEST UNIT READY command, one or more REQUEST SENSE commands, and an INQUIRY command to determine whether the target is present and ready. It returns a code indicating the state of the target.
- If callback is not NULL_FUNC and necessary resources are not immediately available, the function pointed to by callback will be called when resources may have become available. If callback is SLEEP_FUNC, scsi_slave(9F) may block waiting for resources.
-
-
char *scsi_sname(u_char sense_key);
scsi_sname(9F) decodes the SCSI sense key sense_key, and returns the
corresponding sense key string.
int scsi_transport(struct scsi_pkt *pkt);
scsi_transport(9F) requests the host adapter driver to schedule the
command packet pointed to by pkt for execution. Use scsi_transport(9F)
to issue most SCSI command. scsi_poll(9F) may be used to issue
synchronous commands.
void scsi_unprobe(struct scsi_device *devp);
-
scsi_unprobe(9F) is used to free any resources that were allocated on the driver's behalf during scsi_probe(9F).
-
-
void scsi_unslave(struct scsi_device *devp);
-
scsi_unslave(9F) is used to free any resources that were allocated on the driver's behalf during scsi_slave(9F).
Soft State Management
- These interfaces comprise the soft state structure allocator, a facility that simplifies the management of state structures for driver instances. These routines are the recommended way to keep track of per instance data.
-
-
int ddi_soft_state_init(void **state_p,
size_t size, size_t n_items);
-
ddi_soft_state_init(9F) sets up the soft state allocator to keep track of soft state structures for all device instances. state_p points a pointer to an opaque object that keeps track of the soft state structures.
-
-
void ddi_soft_state_fini(void **state_p);
ddi_soft_state_fini(9F) is the inverse operation to
ddi_soft_state_init(9F). state_p points a pointer to an opaque object
that keeps track of the soft state structures.
int ddi_soft_state_zalloc(void *state, int item);
ddi_soft_state_zalloc(9F) allocates and zeroes a new instance of a soft
state structure. statep points to an opaque object that keeps track of the soft
state structures.
void *ddi_get_soft_state(void *state, int item);
-
ddi_get_soft_state(9F) returns a pointer to the soft state structure for the device instance item. statep points to an opaque object that keeps track of the soft state structures.
-
-
void ddi_soft_state_free(void *state, int item);
-
ddi_soft_state_free(9F) releases the resources associated with the soft state structure for item. statep points to an opaque object that keeps track of the soft state structures.
String Manipulation
- These interfaces are generic string manipulation utilities similar to, and in most cases identical to the routines of the same names defined in the standard C library used by application programmers.
-
-
int stoi(char **str);
-
stoi(9F) converts the ASCII decimal numeric string pointed to by *str to an integer and returns the integer. *str is updated to point to the last character examined.
-
-
void numtos(unsigned long num, char *s);
numtos(9F) converts the integer num to an ASCII decimal string and copies the
string to the location pointed to by s. The driver must provide the storage for
the string s and assure that it can contain the result.
char *strchr(const char *str, int chr);
strchr(9F) returns a pointer to the first occurrence of the character chr in the
string pointed to by str, or NULL, if chr is not found in the string.
int strcmp(const char *s1, const char *s2);
strcmp(9F) compares two null-terminated character strings. It returns zero if
they are identical; otherwise, it returns a non-zero value.
int strncmp(const char *s1, const char *s2, size_t n);
strncmp(9F) compares the first n characters of the two strings. It returns zero
if these characters are identical; otherwise, it returns a non-zero value.
char *strcpy(char *dst, const char *srs);
strcpy(9F) copies the character string pointed to by srs to the location
pointed to by dst. The driver must provide storage for the string dst and
assure that it is long enough.
char *strncpy(char *dst, const char *srs, size_t n);
-
strncpy(9F) copies n characters from the string pointed to by srs to the string pointed to by dst. The driver must provide storage for the string dst and assure that it is long enough.
-
-
size_t strlen(const char *sp);
-
strlen(9F) returns the length of the character string pointed to by sp, not including the null-termination character.
System Information
- These interfaces return current information about the system, such as the root node of the system dev_info tree, and the values of certain system-wide parameters.
-
-
dev_info_t *ddi_root_node(void);
ddi_root_node(9F) returns a pointer to the root node of the system
dev_info tree. Device drivers rarely use this.
int drv_getparm(unsigned long parm,
unsigned long *valuep);
-
drv_getparm(9F) retrieves the value of the system parameter parm and returns that value in the location pointed to by valuep. See the manual page for a list of possible parameters.
Thread Synchronization
- These interfaces allow a device to exploit multiple CPUs on multiprocessor machines. They prevent the corruption of data by simultaneous access by more than one thread. The mechanisms for doing this are mutual exclusion locks (mutexes), condition variables, readers/writer locks, and semaphores.
-
-
void cv_init(kcondvar_t *cvp, char *name,
kcv_type_t type, void *arg);
cv_init(9F) prepares the condition variable pointed to by cvp for use.
CV_DRIVER should be specified for type.
void cv_destroy(kcondvar_t *cvp);
-
cv_destroy(9F) releases the resources associated with the condition variable pointed to by cvp.
-
-
void cv_wait(kcondvar_t *cvp, kmutex_t *mp);
-
cv_wait(9F) must be called while holding the mutex pointed to by mp. cv_wait(9F) releases the mutex and blocks until a call is made to cv_signal(9F) or cv_broadcast(9F) for the condition variable pointed to by cvp. cv_wait(9F) then reacquires the mutex and returns.
- Use cv_wait(9F) to block on a condition that may take a while to change.
-
-
void cv_signal(kcondvar_t *cvp);
cv_signal(9F) unblocks one cv_wait(9F) call that is blocked on the
condition variable pointed to by cvp. Call cv_signal(9F) when the condition
that cv_wait(9F) is waiting for becomes true. To unblock all threads blocked
on this condition variable, use cv_broadcast(9F).
void cv_broadcast(kcondvar_t *cvp);
cv_broadcast(9F) unblocks all threads that are blocked on the condition
variable pointed to by cvp. To unblock only one thread, use cv_signal(9F).
int cv_wait_sig(kcondvar_t *cvp, kmutex_t *mp);
-
cv_wait_sig(9F) is like cv_wait(9F), but if the calling thread receives a signal while cv_wait_sig(9F) is blocked, cv_wait_sig(9F) immediately reacquires the mutex and returns zero.
-
-
int cv_timedwait(kcondvar_t *cvp, kmutex_t *mp,
long timeout);
-
cv_timedwait(9F) is like cv_wait(9F), but it returns -1 at time timeout if the condition has not occurred. timeout is given as a number of clock ticks since the last reboot. drv_usectohz(9F) converts microseconds, a platform independent time, to clock ticks.
-
-
int cv_timedwait_sig(kcondvar_t *cvp, kmutex_t *mp,
long timeout);
-
cv_timedwait_sig(9F) is like cv_timedwait(9F) and cv_wait_sig(9F), except that it returns -1 at time timeout if the condition has not occurred. If the calling thread receives a signal while cv_timedwait_sig(9F) is blocked, cv_timedwait_sig(9F) immediately returns zero. In all cases, cv_timedwait_sig(9F) reacquires the mutex before returning.
-
-
void mutex_init(kmutex_t *mp, char *name,
kmutex_type_t type, void *arg);
-
mutex_init(9F) prepares the mutual exclusion lock pointed to by mp for use. MUTEX_DRIVER should be specified for type, and pass an interrupt block cookie of type ddi_iblock_cookie_t for arg. The interrupt block cookie is returned by ddi_add_intr(9F).
-
-
void mutex_enter(kmutex_t *mp);
-
mutex_enter(9F) acquires the mutual exclusion lock pointed to by mp. If another thread holds the mutex, mutex_enter(9F) will either block, or spin waiting for the mutex to become available.
-
-
Mutexes are not reentrant: if a thread calls
mutex_enter(9F) on a mutex it already holds, the system will
panic.
-
mp is assumed to protect a certain set of data, often a single data structure, and all driver threads accessing those data must first acquire the mutex by calling mutex_enter(9F). This is accomplished by mutual agreement and consistency among all driver code paths that access the data in question; mutex_enter(9F) in no way prevents other threads from accessing the data. It is only when all driver code paths agree to acquire the mutex before accessing the data that the data are safe.
-
-
void mutex_exit(kmutex_t *mp);
-
mutex_exit(9F) releases the mutual exclusion lock pointed to by mp.
-
-
void mutex_destroy(kmutex_t *mp);
mutex_destroy(9F) releases the resources associated with the mutual
exclusion lock pointed to by mp.
int mutex_owned(kmutex_t *mp);
mutex_owned(9F) returns non-zero if the mutual exclusion lock pointed to by
mp is currently held; otherwise, it returns zero. Use mutex_owned(9F) only in
an expression used in ASSERT(9F).
int mutex_tryenter(kmutex_t *mp);
mutex_tryenter(9F) is similar to mutex_enter(9F), but it does not block
waiting for the mutex to become available. If the mutex is held by another
thread, mutex_tryenter(9F) returns zero. Otherwise, mutex_tryenter(9F)
acquires the mutex and returns non-zero.
void rw_destroy(krwlock_t *rwlp);
rw_destroy(9F) releases the resources associated with the readers/writer lock
pointed to by rwlp.
void rw_downgrade(krwlock_t *rwlp);
- If the calling thread holds the lock pointed to by rwlp for writing, rw_downgrade(9F) releases the lock for writing, but retains the lock for reading. This allows other readers to acquire the lock unless a thread is waiting to acquire the lock for writing.
-
-
void rw_enter(krwlock_t *rwlp, krw_t enter_type);
- If enter_type is RW_READER, rw_enter(9F) acquires the lock pointed to by rwlp for reading if no thread currently holds the lock for writing, and if no thread is waiting to acquire the lock for writing. Otherwise, rw_enter(9F) blocks.
- If enter_type is RW_WRITER, rw_enter(9F) acquires the lock for writing if no thread holds the lock for reading or writing, and if no other thread is waiting to acquire the lock for writing. Otherwise, rw_enter(9F) blocks.
-
-
void rw_exit(krwlock_t *rwlp);
rw_exit(9F) releases the lock pointed to by rwlp.
void rw_init(krwlock_t *rwlp, char *name,
krw_type_t type, void *arg);
-
rw_init(9F) prepares the readers/writer lock pointed to by rwlp for use. RW_DRIVER should be passed for type.
-
-
int rw_read_locked(krwlock_t *rwlp);
- The lock pointed to by rwlp must be held during a call to rw_read_locked(9F). If the calling thread holds the lock for reading, rw_read_locked(9F) returns a non-zero value. If the calling thread holds the lock for writing, rw_read_locked(9F) returns zero.
-
-
int rw_tryenter(krwlock_t *rwlp, krw_t enter_type);
-
rw_tryenter(9F) attempts to enter the lock, like rw_enter(9F), but never blocks. It returns a non-zero value if the lock was successfully entered, and zero otherwise.
-
-
int rw_tryupgrade(krwlock_t *rwlp);
- If the calling thread holds the lock pointed to by rwlp for reading, rw_tryupgrade(9F) acquires the lock for writing if no other threads hold the lock, and no thread is waiting to acquire the lock for writing. If rw_tryupgrade(9F) cannot acquire the lock for writing, it returns zero.
-
-
void sema_init(ksema_t *sp, u_int val, char *name,
ksema_type_t type, void *arg);
-
sema_init(9F) prepares the semaphore pointed to by sp for use. SEMA_DRIVER should be passed for type. count is the initial count for the semaphore, which usually should be 1 or 0. In almost all cases, drivers should pass 1 for count.
-
-
void sema_destroy(ksema_t *sp);
sema_destroy(9F) releases the resources associated with the semaphore
pointed to by sp.
void sema_p(ksema_t *sp);
sema_p(9F) acquires the semaphore pointed to by sp by decrementing the
counter if its value is greater than zero. If the semaphore counter is zero,
sema_p(9F) blocks waiting to acquire the semaphore.
int sema_p_sig(ksema_t *sp);
-
sema_p_sig(9F) is like sema_p(9F), except that if the calling thread has a signal pending, and the semaphore counter is zero, sema_p_sig(9F) returns zero without blocking.
-
-
void sema_v(ksema_t *sp);
-
sema_v(9F) releases the semaphore pointed to by sp by incrementing its counter.
-
-
int sema_tryp(ksema_t *sp);
-
sema_tryp(9F) is similar to sema_p(9F), but if the semaphore counter is zero, sema_tryp(9F) immediately returns zero.
Timing
- These are delay and time value conversion routines.
-
-
void delay(long ticks);
delay(9F) blocks the calling thread for at least ticks clock ticks (using
timeout(9F)).
void drv_usecwait(clock_t microsecs);
-
drv_usecwait(9F) busy-waits for microsecs microseconds.
-
-
clock_t drv_hztousec(clock_t hertz);
drv_hztousec(9F) converts hertz clock ticks to microseconds, and returns
the number of microseconds.
clock_t drv_usectohz(clock_t microsecs);
-
drv_usectohz(9F) converts microsecs microseconds to clock ticks, and returns the number of clock ticks.
uio(9S) Handling
- These interfaces all deal with moving data using the uio(9S) data structure.
-
-
int uiomove(caddr_t address, long nbytes,
enum uio_rw rwflag, struct uio *uio_p);
-
uiomove(9F) copies data between the address address and the uio(9S) structure pointed to by uio_p. If rwflag is UIO_READ, data are transferred from address to a data buffer associated with the uio(9S) structure. If rwflag is UIO_WRITE, data are transferred from a data buffer associated with the uio(9S) structure to address.
-
-
int ureadc(int c, uio_t *uio_p);
ureadc(9F) appends the character c to the a data buffer associated with the
uio(9S) structure pointed to by uio_p.
int uwritec(uio_t *uio_p);
-
uwritec(9F) removes a character from a data buffer associated with the uio(9S) structure pointed to by uio_p, and returns the character.
Utility Functions
- These interfaces are miscellaneous utilities that driver may use.
-
-
void ASSERT(EX);
- The ASSERT(9F) macro does nothing if EX evaluates to non-zero. If EX evaluates to zero, ASSERT(9F) panics the system. ASSERT(9F) is useful in debugging a driver, since it can be used to stop the system when an unexpected situation is encountered, such as an erroneously NULL pointer.
-
ASSERT(9F) exhibits this behavior only when the DEBUG preprocessor symbol is defined.
-
-
int bcmp(char *s1, char *s2, size_t len);
bcmp(9F) compares len bytes of the byte arrays starting at s1 and s2. If these
bytes are identical, bcmp(9F) returns zero. Otherwise, bcmp(9F) returns a non-
zero value.
unsigned long btop(unsigned long numbytes);
btop(9F) converts a size n expressed in bytes to a size expressed in terms of
the main system MMU page size, rounded down to the nearest page.
unsigned long btopr(unsigned long numbytes);
btopr(9F) converts a size n expressed in bytes to a size expressed in terms of
the main system MMU page size, rounded up to the nearest page.
void bzero(caddr_t addr, size_t bytes);
bzero(9F) zeroes bytes bytes starting at addr.
unsigned long ddi_btop(dev_info_t *dip,
unsigned long bytes);
-
ddi_btop(9F) converts a size expressed in bytes to a size expressed in terms of the parent bus nexus page size, rounded down to the nearest page.
-
-
unsigned long ddi_btopr(dev_info_t *dip,
unsigned long bytes);
ddi_btopr(9F) converts a size expressed in bytes to a size expressed in terms
of the parent bus nexus page size, rounded up to the nearest page.
unsigned long ddi_ptob(dev_info_t *dip,
unsigned long pages);
ddi_ptob(9F) converts a size expressed in terms of the parent bus nexus page
size to a size expressed in bytes.
int ddi_ffs(long mask);
-
ddi_ffs(9F) returns the number of the first (least significant) bit set in mask.
-
-
int ddi_fls(long mask);
-
ddi_fls(9F) returns the number of the last (most significant) bit set in mask.
-
-
caddr_t ddi_get_driver_private(dev_info_t *dip);
ddi_get_driver_private(9F) returns a pointer to the data stored in the
driver-private area of the dev_info node identified by dip.
void ddi_set_driver_private(dev_info_t *dip,
caddr_t data);
-
ddi_set_driver_private(9F) sets the driver-private data of the dev_info node identified by dip to the value data.
-
-
int ddi_peekc(dev_info_t *dip, char *addr,
char *valuep);
-
ddi_peekc(9F) reads a character from the address addr to the location pointed to by valuep.
-
-
int ddi_peeks(dev_info_t *dip, short *addr,
short *valuep);
ddi_peeks(9F) reads a short integer from the address addr to the location
pointed to by valuep.
int ddi_peekl(dev_info_t *dip, long *addr,
long *valuep);
ddi_peekl(9F) reads a long integer from the address addr to the location
pointed to by valuep.
int ddi_peekd(dev_info_t *dip, longlong_t *addr,
longlong_t *valuep);
ddi_peekd(9F) reads a double long integer from the address addr to the
location pointed to by valuep.
int ddi_pokec(dev_info_t *dip, char *addr, char value);
ddi_pokec(9F) writes the character in value to the address addr.
int ddi_pokes(dev_info_t *dip, short *addr,
short value);
ddi_pokes(9F) writes the short integer in value to the address addr.
int ddi_pokel(dev_info_t *dip, long *addr, long value);
ddi_pokel(9F) writes the long integer in value to the address addr.
int ddi_poked(dev_info_t *dip, longlong_t *addr,
longlong_t value);
ddi_poked(9F) writes the double long integer in value to the address addr.
major_t getmajor(dev_t dev);
-
getmajor(9F) decodes the major device number from dev and returns it.
-
-
minor_t getminor(dev_t dev);
getminor(9F) decodes the minor device number from dev and returns it.
dev_t makedevice(major_t majnum, minor_t minnum);
makedevice(9F) constructs and returns a device number of type dev_t from
the major device number majnum and the minor device number minnum.
int max(int int1, int int2);
max(9F) returns the larger of the integers int1 and int2.
int min(int int1, int int2);
min(9F) returns the lesser of the integers int1 and int2.
int nodev();
nodev(9F) returns an error. Use nodev(9F) as the entry in the cb_ops(9S)
structure for any entry point for which the driver must always fail.
int nulldev();
-
nulldev(9F) always returns zero, a return which for many entry points implies success. See the manual pages in Section 9 of the man Pages(9E): DDI and DKI Driver Entry Points to learn about entry point return semantics.
-
-
unsigned long ptob(unsigned long numpages);
-
ptob(9F) converts a size expressed in terms of the main system MMU page size to a size expressed in bytes.
|
|