| From: HYDRA::AXPDEVELOPER "[email protected]" 3-JUN-1997 13:37:13.37
To: US3RMC::"[email protected]"
CC: AXPDEVELOPER
Subj: Fixed edpseudo.c
Yv,
The device driver support organization provided me with the following
version of the ed code. (Apparently the version shipped with the kit
was buggy).
Let me know when you have a chance to issue the command
#sysconfig -v -c edpseudo
along with sending what gets printed in the console/dxconsole
and a detailed description of the problems you encountered.
Thanks,
Donna,
Alpha Developer Support
P.S. Please refer to 1997-3671 when replying to this note.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
* *****************************************************************
* * *
* * Copyright (c) Digital Equipment Corporation, 1991, 1996 *
* * *
* * All Rights Reserved. Unpublished rights reserved under *
* * the copyright laws of the United States. *
* * *
* * The software contained on this media is proprietary to *
* * and embodies the confidential technology of Digital *
* * Equipment Corporation. Possession, use, duplication or *
* * dissemination of the software and media is authorized only *
* * pursuant to a valid written license from Digital Equipment *
* * Corporation. *
* * *
* * RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure *
* * by the U.S. Government is subject to restrictions as set *
* * forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, *
* * or in FAR 52.227-19, as applicable. *
* * *
* *****************************************************************
*/
/*
* HISTORY
*/
#pragma ident "@(#)$RCSfile: edpseudo.c,v $ $Revision: 1.1.2.2 $ (DEC) $Date: 1996/02/09 23:00:59 $"
/***************************************************
* edpseudo.c Driver for edpseudo device *
* *
* The /dev/edpseudo device driver shows you how *
* to write a static and loadable pseudo device *
* driver, a DEC UNIX Single Binary device driver *
* *
***************************************************/
/***************************************************
* A WORD ABOUT PSEUDODEVICE DRIVERS *
***************************************************/
/***************************************************
* FEATURES OF THE /dev/edpseudo DRIVER *
***************************************************
* *
* The following list highlights some features of *
* the /dev/edpseudo driver: *
* *
* o Single binary module *
* *
* The /dev/edpseudo driver is written to produce*
* a single driver image. This single driver *
* image has a file extension of .mod. You *
* compile a device driver as a single binary *
* module that can be configured into a Digital *
* UNIX kernel at any point in time. *
* *
* o Static build process with the cfgmgr framework*
* *
* The /dev/edpseudo driver is written and *
* compiled to be built into a Digital UNIX kernel*
* (/vmunix) or a sysconfigtab database image *
* when a user boots the kernel (/vmunix) or *
* when the OSFboot software links the *
* sysconfigtab database image. *
* *
* The /dev/edpseudo driver uses the runtime *
* framework provided by the cfgmgr framework to *
* accomplish the static build process. *
* *
* o Dynamic build process with cfgmgr framework *
* *
* The /dev/edpseudo driver is written and *
* compiled to be built into Digital UNIX kernel *
* (/vmunix) when a request is made at single *
* user or multiuser time. *
* *
***************************************************/
/***************************************************
* INTERFACES that /dev/edpseudo IMPLEMENTS *
***************************************************
* *
* o ed_configure (configure interface) *
* o register_device_files *
* o edpseudoopen (open interface) *
* o edpseudoclose (close interface) *
* o edpseudoread (read interface) *
* o edpseudowrite (write interface) *
* o edpseudoioctl (ioctl interface) *
* *
***************************************************/
/***************************************************
* Include Files Section *
***************************************************/
/***************************************************
* Common driver header files *
***************************************************/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/map.h>
#include <sys/buf.h>
#include <sys/vm.h>
#include <sys/file.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/devio.h>
#include <hal/cpuconf.h>
#include <sys/exec.h>
#include <io/common/devdriver.h>
#include <sys/sysconfig.h>
#include <machine/cpu.h>
#include <io/ED100/edpseudoreg.h> /* Device register header file */
#include <io/dec/tc/tc.h>
#undef ED_DEBUG
#define NO_DEV -1
#define MAJOR_INSTANCE 1
/***************************************************
* Declarations Section *
***************************************************/
/***************************************************
* Bits used in read/write operations *
***************************************************/
#define DN_RESET 0001 /* Device ready for data transfer */
#define DN_ERROR 0002 /* Indicate error */
/***************************************************
* Defines for softc structure *
***************************************************/
#define DN_OPEN 1 /* Device open bit */
#define DN_CLOSE 0 /* Device close bit */
extern int nodev(), nulldev();
/***************************************************
* Forward declarations of driver interfaces *
***************************************************/
int edpseudoopen(), edpseudoclose(), edpseudoread(), edpseudowrite();
int edpseudoioctl();
caddr_t edpseudommap();
/***************************************************
* Declare softc structure *
***************************************************/
struct edpseudo_softc {
int sc_openf; /* Open flag */
int sc_count; /* Count of characters written to device */
int sc_state; /* Device state, not currently used */
} edpseudo_softc[1];
int edpseudo_config = FALSE; /* State flags indicating driver configured */
int edpseudo_devno = NO_DEV; /* No major number assigned yet. */
int NED = 1;
/***************************************************
* The variable edpseudo_is_dynamic will be used to *
* control any differences in functions performed *
* by the static and loadable code paths of the *
* driver. In this manner any differences are *
* made on a run-time basis and not on a *
* compile-time basis. Whenever possible, *
* however, the driver is written so that the code *
* is applicable to both the loadable and static *
* code paths of the driver. *
* *
* A device driver calls the cfgmgr_get interface *
* to determine the cfgmgr state for the driver. *
* A device driver needs state information to *
* follow reconfigure and unconfigure requests *
* from the cfgmgr framework. *
***************************************************/
int edpseudo_is_dynamic = 0;
int edcallback_return_status = ESUCCESS;
/***************************************************
* Device switch structure for dynamic *
* configuration. The following is a definition *
* of the devsw entry that will be dynamically *
* added for the loadable and static driver. For *
* this reason the loadable and static driver does *
* not need to have its entry points statically *
* configured into conf.c. *
***************************************************/
struct dsent edpseudo_devsw_entry = {
edpseudoopen, /* d_open */
edpseudoclose, /* d_close */
nodev, /* d_strategy */
edpseudoread, /* d_read */
edpseudowrite, /* d_write */
edpseudoioctl, /* d_ioctl */
nodev, /* d_dump */
nodev, /* d_psize */
nodev, /* d_stop */
nodev, /* d_reset */
nodev, /* d_select */
0, /* d_mmap */
0, /* d_segmap */
NULL, /* d_ttys */
DEV_FUNNEL, /* d_funnel */
0, /* d_bflags */
0, /* d_cflags */
};
/***************************************************
* The following code declares variables that are *
* required by cfgmgr framework's driver method. *
* You use these variables as fields in the *
* driver's attribute table. The attribute table *
* for the /dev/edpseudo driver is called *
* ed_attributes. *
***************************************************/
static int majnum = NO_DEV;
static int dsflags = 0;
static int edpseudoversion = 0;
static int Ed_Developer_Debug = 0;
static unsigned char mcfgname[CFG_ATTR_NAME_SZ] = "rrr";
static unsigned char modtype[CFG_ATTR_NAME_SZ] = "";
static unsigned char devmajor[CFG_ATTR_NAME_SZ] = "";
static unsigned char unused[300] = "";
static unsigned char cma_dd[120] = "";
/***************************************************
* The cfgmgr framework uses the driver's attribute*
* table (a structure of type cfg_subsys_attr_t) *
* during static and dyanmic integration of a *
* device driver into the kernel. The cfgmgr *
* framework initializes the attributes table early*
* in the kernel boot process and whenever it *
* receives a sysconfig command request from *
* either the kernel or the user command line. *
* *
* NOTE *
* *
* There are a number of stanza fields *
* (attributes) that appear in the sysconfigtab *
* file fragment that do not appear in the device *
* driver's attribute table. The cfgmgr framewoork's *
* device driver method consumes these fields *
/* (attributes) to perform kernel configuration *
* work and to make device special files. *
***************************************************/
cfg_subsys_attr_t ed_attributes[] = {
/***********************************************
* Declares an array of cfg_subsys_attr_t *
* structures and calls it ed_attributes. *
* The device driver method of cfgmgr fills in *
* the elements in ed_attributes because *
* the operation types designated by these *
* are CFG_OP_CONFIGURE. The device driver *
* method of cfgmgr reads the entries for the *
* /dev/edpseudo driver from the sysconfigtab *
* database. (A sysconfigtab file *
* fragment was created for the /dev/edpseudo *
* driver. The sysconfigdb utility appends *
* this sysconfigtab file fragment to the *
* sysconfigtab database.) *
* *
* To determine if any of these element reads *
* failed, /dev/edpseudo driver verifies each *
* from the cfg_attr_t structure passed into *
* the ed_configure interface. *
* *
* Several of the following fields are used *
* in /dev/edpseudo device driver while other *
* fields exist to illustrate what can be *
* loaded by cfgmgr into the driver attributes *
* table. *
* *
* These fields can represent tunable *
* parameters to indicate whether the driver *
* is statically or dynamically integrated *
* into the kernel. *
***********************************************/
/* Fields used in this driver. */
{"Module_Config_Name", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)mcfgname,2,CFG_ATTR_NAME_SZ,0},
{"Module_Type", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)modtype,2,CFG_ATTR_NAME_SZ,0},
{"Device_Char_Major", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)devmajor,0,CFG_ATTR_NAME_SZ,0},
{"CMA_Option", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)cma_dd,0,300,0},
{"numunit", CFG_ATTR_INTTYPE, CFG_OP_QUERY | CFG_OP_CONFIGURE,
(caddr_t)&NED,0,1,0},
/*
* Karl, we need to place dummy entries for all the
* device driver entries that are defined in sysconfigtab for
* this subsystem. Otherwise error messages print out to
* the console when a driver is configured. These attributes
* all use the same variable because we do not care about them
* in the driver.
*/
{"Module_Path", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Subdir", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Block_Subdir", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Char_Subdir", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Major_Req", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Block_Major", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Block_Minor", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Block_Files", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Char_Major", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Char_Minor", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Char_Files", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_User", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Group", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
{"Device_Mode", CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE,
(caddr_t)unused,0,300,0},
/**********************************************
* The /dev/edpseudo device driver modifies *
* the following attributes during a configure*
* or unconfigure operation. The cfgmgr *
* deamon's device driver method uses these *
* attributes to provide the device special *
* files that loadable and static device *
* drivers need. *
**********************************************/
{"majnum", CFG_ATTR_INTTYPE, CFG_OP_QUERY,
(caddr_t)&majnum,0,512,0},
{"dsflags", CFG_ATTR_INTTYPE, CFG_OP_QUERY,
(caddr_t)&dsflags,0,8,0},
{"version", CFG_ATTR_INTTYPE, CFG_OP_QUERY,
(caddr_t)&edpseudoversion,0,9999999,0},
/**********************************************
* Device driver specific entries describing *
* configuration and operation of the driver *
* should go here. *
*********************************************/
/*
*
* edpseudo_developer_debug = 1 turn on these messages
* = 0 turn off these messages (Normal Case)
*
*/
{"Ed_Developer_Debug", CFG_ATTR_INTTYPE, CFG_OP_QUERY |
CFG_OP_RECONFIGURE | CFG_OP_CONFIGURE,
(caddr_t)&Ed_Developer_Debug,0,1,0},
{"",0,0,0,0,0,0}
};
/***************************************************
* The cfgmgr framework uses the driver's attribute*
* table (a structure of type cfg_subsys_attr_t) *
* during static and dyanmic integration of a *
* device driver into the kernel. The cfgmgr *
* framework initializes the attributes table early*
* in the kernel boot process and whenever it *
* receives a sysconfig command request from *
* either the kernel or the user command line. *
* *
* NOTE *
* *
* There are a number of stanza fields *
* (attributes) that appear in the sysconfigtab *
* file fragment that do not appear in the device *
* driver's attribute table.The cfgmgr framework's *
* device driver method consumes these fields *
* (attributes) to perform kernel configuration *
* work and to make device special files. *
***************************************************/
/***************************************************
* register_major_number() *
***************************************************
* Name: register_major_number *
* *
* Arguments: *
* *
* *
* Kernel support interface calls: *
* *
* o atoi *
* o cfgmgr_set_status *
* o atoi *
* o atoi *
* o devsw_reserve *
* o devsw_add *
* o strcmp *
* o strcpy *
* *
* Called by: *
* *
* o cfgmgr framework *
* *
* Return Codes: *
* *
* Success: ESUCCESS *
* *
* Failure: EBUSY *
* EINVAL *
* ESRCH *
* *
* Description: *
* *
***************************************************/
static int
register_major_number()
{
/*
* This call to devsw_add is responsible for adding the device
* driver information to the device switch table. The each allocation
* provides a bdev and cdev device entry for the device table.
*
*/
majnum = devsw_add(mcfgname, MAJOR_INSTANCE,
majnum, &edpseudo_devsw_entry);
if (majnum == NO_DEV) {
/***************************************************
* The call to devsw_add could fail if *
* the driver is requesting a specific *
* major number and that number is *
* currently in use, or if the devsw *
* table is currently full. *
***************************************************/
return (ENODEV);
}
/***************************************************
* Stash away the dev_t so that it can *
* be used later to unconfigure the *
* device. Save off the minor number *
* information. This will be returned *
* by the query call. *
***************************************************/
edpseudo_devno = majnum;
/***************************************************
* This is a character driver. For this *
* reason no block major number is *
* assigned. *
***************************************************/
edpseudo_config = TRUE;
return(ESUCCESS);
}
/***************************************************
* callback_register_major_number() *
***************************************************
* Name: callback_register_major_number *
* *
* Arguments: *
* *
* int point - driver callback point *
* int order - Priority at callback *
* ulong args - User argument *
* *
* Kernel support interface calls: *
* *
* o cfgmgr_set_status *
* o register_major_number *
* *
* Called by: *
* *
* o cfgmgr framework as static callback *
* *
* Return Codes: *
* *
* Success: ESUCCESS *
* *
* Failure: EBUSY *
* EINVAL *
* ESRCH *
* *
* Description: *
* *
* This is the Static cfgmgr jacket used to *
* do major number registration in the boot path. *
* This jacket routine handles the static callback *
* specific error handling but utilizes the same *
* configuration routine used by the driver when *
* dynamically loading. *
* *
***************************************************/
void
edcallback_register_major_number(int point,
int order,
ulong args,
ulong event_arg)
{
int status;
/*
* Detect if a previous failure has occured in
* statically configuring this driver. If so, the
* exit the callback without doing any configuration
* work.
*/
if(edcallback_return_status != ESUCCESS)
return;
/*
* Register this drivers configuration with the
* kernel's topology.
*/
status = register_major_number();
/*
* If configuration registration is successful then
* just return from this callback. Else signal the
* cfgmgr that this driver has failed to configure and
* set the callback_return_status to the failure
* condition. Note: A side effect of calling the
* cfgmgr_set_status() routine is that the configure
* routine or this driver is called with the
* unconfigure op passed. The unconfigure routine must
* be prepared for this event.
*/
if(status != ESUCCESS) {
cfgmgr_set_status(mcfgname);
edcallback_return_status = status;
return;
}
}
/***************************************************
* ed_configure() *
***************************************************
* Name: ed_configure *
* *
* Arguments: *
* *
* op Configure operation *
* indata Input data structure, cfg_attr_t *
* indatalen Size of input data structure *
* outdata Formal parameter not used *
* outdatalen Formal parameter not used *
* *
* Kernel support interface calls: *
* *
* o atoi *
* o bcopy *
* o devsw_add *
* o devsw_del *
* o cfgmgr_get_state *
* o configure_driver *
* o makedev *
* o printf *
* o register_callback *
* o register_major_number *
* o callback_register_major_number *
* o strcmp *
* o strcpy *
* o unconfigure_driver *
* *
* Called by: *
* *
* o cfgmgr framework *
* *
* Return Codes: *
* *
* Success: ESUCCESS *
* *
* Failure: EBUSY *
* EINVAL *
* ESRCH *
* *
* Description: *
* *
* The ed_configure interface is called *
* indirectly by the cfgmgr framework. The cfgmgr *
* framework is responsible for calling all single *
* binary modules for registration and integration *
* into the kernel. The cfgmgr framework requires *
* that a single binary module has both an *
* attributes table and a configure interface *
* before it (the single binary module) can be *
* registered as part of the cfgmgr framework and *
* the Digital UNIX kernel. *
* *
* The ed_configure interface cooperates with *
* the cfgmgr framework to complete configure, *
* unconfigure, query, and other requests. *
* These requests are differentiated by the "op" *
* argument. *
* *
* Specifically, the ed_configure interface *
* shows the code a device driver must supply to *
* produce a single binary module. This code *
* allows the /dev/edpseudo driver to be loaded as *
* a static or dynamic driver. *
***************************************************/
ed_configure(op, indata, indatalen, outdata, outdatalen)
cfg_op_t op;
cfg_attr_t *indata;
size_t indatalen;
cfg_attr_t *outdata;
size_t outdatalen;
{
int retval;
int i;
int driver_cfg_state;
switch(op) {
case CFG_OP_CONFIGURE:
/*
* If this device driver has already been configured
* either statically or dynamically then return this
* ed_configure call indicating an error.
*/
if(edpseudo_config == TRUE)
return(EINVAL);
/***************************************************
* The following code performs a check on the *
* configuration name. If the configuration name *
* is NULL, subsequent code uses the controller *
* name stored in driver structure's ctlr_name *
* member. The driver structure for /dev/edpseudo *
* driver is called edpseudodriver. This structure *
* was declared and initialized to appropriate *
* values in the Declarations Section of the *
* /dev/edpseudo driver. *
* *
* The name specified in the ctlr_name member will *
* be replaced if the mcfgname variable is not *
* NULL. The value stored in mcfgname supersedes *
* the controller name stored in ctlr_name during *
* configuration of the driver. *
***************************************************/
if(strcmp(mcfgname,"")==0) {
/* If the operator is interested in
knowing the configuration name of
this driver, you can set this attribute
to CFG_OP_QUERY in the driver's
cfg_subsys_attr_t structure.
*/
strcpy(mcfgname,"ed");
}
else {
/* Module_Config_Name attribute (mcfgname)
from sysconfigtab is used
to configure the device driver in
the following calls to the
configure_driver interface.
*/
}
if(cfgmgr_get_state(mcfgname, &driver_cfg_state) != ESUCCESS){
return(EINVAL); /* CFGMGR fatal error determining */
}
if(driver_cfg_state == SUBSYSTEM_STATICALLY_CONFIGURED) {
/*
* During Static cfgmgr configuration subsystem callbacks
* scheduled to run in the boot path have no way to determine
* if the previous callbacks worked. This global flag is looked
* at in each of the callback jackets to determine of this
* subsystem should still be configured in the boot path.
*/
edcallback_return_status = ESUCCESS;
/*
* During Static configuration the cfgmgr schedules work
* to be done at pre and post autoconfiguration but it
* does does not actuall know at this time wheather a subsystem
* will successfull configure into a kernel. The callbacks
* are responsible for determining the status of a subsystems
* configuration in the boot path and reporting failure to
* framework via the cfgmgr_set_state() call.
*/
edpseudo_is_dynamic = SUBSYSTEM_STATICALLY_CONFIGURED;
register_callback( edcallback_register_major_number, CFG_PT_POSTCONFIG,
CFG_ORD_NOMINAL, (long) 0 );
}
else {
/*
* During Dynamic Loadable configuration the cfgmgr is
* present when the following functionality is executed.
* The error returns here will signal the cfgmgr that
* the subsystems configuration has failed.
*/
edpseudo_is_dynamic = SUBSYSTEM_DYNAMICALLY_CONFIGURED;
retval = register_major_number();
if(retval != ESUCCESS)
return(retval);
}
break;
/***************************************************
* Unconfigure (unload) the driver. *
***************************************************/
case CFG_OP_UNCONFIGURE:
/***************************************************
* DEBUG STATEMENT *
***************************************************/
#ifdef ED_DEBUG
printf("ed_configure: CFG_OP_UNCONFIGURE.\n");
#endif /* ED_DEBUG */
/***************************************************
* Fail the unconfiguration if the driver *
* is not currently configured as a *
* dynamic subsystem. Statically *
* configured subsystems CANNOT be *
* unconfigure/unloaded. *
* *
* Static subsystems will all physically *
* remain in the kernel whether or not *
* they are configured. Dynamic subsystem *
* when they are unconfigured are also *
* unloaded from the kernel. *
***************************************************/
if(edpseudo_is_dynamic == SUBSYSTEM_STATICALLY_CONFIGURED)
{
return(EINVAL);
}
/***************************************************
* Do not allow the driver to be unloaded *
* if it is currently active. To see if *
* the driver is active look to see if *
* any users have the device open. *
***************************************************/
if (edpseudo_softc[0].sc_openf != 0) {
return(EBUSY);
}
/***************************************************
* Call devsw_del to remove the driver *
* entry points from the in-memory resident *
* devsw table. This is done prior to *
* deleting the loadable configuration *
* and handlers to prevent users from *
* accessing the device in the middle of *
* deconfigure operation. *
***************************************************/
retval = devsw_del(mcfgname, MAJOR_INSTANCE);
if (retval == NO_DEV) {
return(ESRCH);
}
#ifdef ED_DEBUG
printf("ed_configure:unconfigure_driver failed.\n");
#endif
edpseudo_is_dynamic = 0;
edpseudo_config = FALSE;
break;
/**************************************************
* Code to perform the tasks associated with a *
* system manager request to reconfigure the *
* currently loaded device driver. *
**************************************************/
case CFG_OP_RECONFIGURE:
break;
/**************************************************
* Requests to query a loadable subsystem will *
* only succeed if the CFG_OP_QUERY: entry *
* returns success. *
**************************************************/
case CFG_OP_QUERY:
break;
default: /* Unknown operation type */
return(ENOTSUP);
}
/***************************************************
* The driver's configure interface has *
* completed successfully. Return a success *
* status. *
***************************************************/
return(ESUCCESS);
}
/***************************************************
* edpseudoopen() *
***************************************************
* Name: edpseudoopen *
* *
* Arguments: *
* *
* dev Major/minor device number *
* flag Flags from /usr/sys/include/sys/file.h *
* format Format of special device *
* *
* Kernel support interface calls: *
* *
* Called by: *
* *
* The kernel calls the driver's open interface as *
* a result of an open system call. *
* *
* Return Codes: *
* *
* Success: ESUCCESS *
* *
* Failure: EBUSY *
* ENODEV *
* *
* Description: *
* *
* A device driver's open interface is called by *
* the kernel as a result of an open system call. *
* Its task is to open the specified device. *
* *
* The open interface for the /dev/edpseudo driver *
* is called edpseudoopen. The edpseudoopen *
* interface checks *
* to ensure that the open is unique, marks the *
* device as open, and returns the constant *
* ESUCCESS to the open system call to indicate *
* success. *
***************************************************/
edpseudoopen(dev, flag, format)
dev_t dev;
int flag;
int format;
{
struct edpseudo_softc *sc = &edpseudo_softc[0];
/***************************************************
* Make sure the open is unique. *
***************************************************/
if (sc->sc_openf == DN_OPEN)
return (EBUSY);
return(ESUCCESS);
}
/***************************************************
* edpseudoclose() *
***************************************************
* Name: edpseudoclose *
* *
* Arguments: *
* *
* dev Major/minor device number *
* flag Flags from /usr/sys/include/sys/file.h *
* format Format of special device *
* *
* Kernel support interface calls: *
* *
* o mb *
* o write_io_port *
* *
* Called by: *
* *
* The kernel calls the driver's close interface *
* as a result of a close system call. *
* *
* Return Codes: *
* *
* Success: ESUCCESS *
* *
* Failure: errno from errno.h *
* *
* Description: *
* *
* A device driver's close interface is called by *
* the kernel as a result of a close system call. *
* Its task is to close the specified device. *
* *
* The close interface for the /dev/edpseudo driver*
* is called edpseudoclose. Specifically, the *
* edpseudoclose *
***************************************************/
edpseudoclose(dev, flag, format)
dev_t dev;
int flag;
int format;
{
struct edpseudo_softc *sc = &edpseudo_softc[0];
/***************************************************
* Perform the following initializations: *
* *
* o Initialize unit to the minor device number *
* o Initialize the pointer to the controller *
* structure associated with this psuedo driver *
* o Initialize the pointer to the edpseudo_softc *
* structure associated with this psuedo driver *
* o Initialize the I/O handle (the reg variable) *
* to the address of the device registers (the *
* addr member of the controller structure). *
***************************************************/
/****************************************************
* Turn off the open flag for the specified device. *
****************************************************/
sc->sc_openf = DN_CLOSE;
return (ESUCCESS);
}
/***************************************************
* edpseudoread() *
***************************************************
* Name: edpseudoread *
* *
* Arguments: *
* *
* dev Major/minor device number *
* uio Pointer to uio structure *
* flag Access mode of device *
* *
* Kernel support interface calls: *
* *
* Called by: *
* *
* The kernel calls the driver's read interface as *
* a result of a read system call. *
* *
* Return Codes: *
* *
* Success: The number of bytes *
* actually read. *
* *
* Failure: An error number *
* *
* Description: *
* *
* A device driver's read interface is called by *
* the kernel as a result of a read system call. *
* Its main task is to read data from a device. *
* *
* The read interface for the /dev/edpseudo driver *
* is called edpseudoread. The edpseudoread *
* interface simply *
* returns success to the read system call because *
* the /dev/edpseudo driver always returns EOF on *
* read operations. *
* *
***************************************************/
edpseudoread(dev, uio, flag)
dev_t dev;
struct uio *uio;
int flag;
{
return (ESUCCESS); /* Return success */
}
/***************************************************
* edpseudowrite() *
***************************************************
* Name: edpseudowrite *
* *
* Arguments: *
* *
* dev Major/minor device number *
* uio Pointer to uio structure *
* flag Access mode of device *
* *
* Kernel support interface calls: *
* *
* o panic *
* *
* Called by: *
* *
* The kernel calls the driver's write interface *
* as a result of a read system call. *
* *
* Return Codes: *
* *
* Success: The number of bytes *
* actually written. *
* *
* Failure: An error number *
* *
* Description: *
* *
* A device driver's write interface is called by *
* the kernel as a result of a write system call. *
* Its main task is to write data to a device. *
* *
* The write interface for the /dev/edpseudo driver*
* is called edpseudowrite. The edpseudowrite *
* interface copies data from the address space *
* pointed to *
* by the uio structure to the device. Upon a *
* successful write, edpseudowrite returns the *
* value zero (0) to the write system call. *
* *
***************************************************/
edpseudowrite(dev, uio, flag)
dev_t dev;
struct uio *uio;
int flag;
{
return (ESUCCESS);
}
/***************************************************
* edpseudoioctl() *
***************************************************
* Name: edpseudoioctl *
* *
* Arguments: *
* *
* dev Major/minor device number *
* cmd The ioctl command *
* data ioctl command-specific data *
* flag Access mode of device *
* *
* Kernel support interface calls: *
* *
* Called by: *
* *
* The kernel calls the driver's ioctl interface *
* as a result of an ioctl system call. *
* *
* Return Codes: *
* *
* Success: ESUCCESS *
* *
* Failure: An error number from *
* errno.h *
* *
* Description: *
* *
* A device driver's ioctl interface is called by *
* the kernel as a result of an ioctl system call. *
* Its main task is to perform general-purpose *
* I/O control. *
* *
* The ioctl interface for the /dev/edpseudo driver is *
* called edpseudoioctl. Specifically, the edpseudoioctl*
* interface obtains and clears the count of bytes *
* that was previously written by edpseudowrite. When *
* a user program issues the command to obtain the *
* count, edpseudoioctl returns the count through the *
* data pointer that the kernel passes to the *
* edpseudoioctl interface. When a user program asks *
* to clear the count, the edpseudoioctl interface *
* does so. *
***************************************************/
edpseudoioctl(dev, cmd, data, flag)
dev_t dev;
unsigned int cmd;
caddr_t data;
int flag;
{
return (ESUCCESS);
}
/***********************************************************
MEMORY MAPPING
The rad_mmap routine is invoked by the kernel as a
result of an application calling the mmap(2) system
call. rad_mmap returns the page frame number corresponding
to the page at the specified offset.
***********************************************************/
caddr_t edpseudommap(dev_t dev, off_t off, int prot)
{
long kpfnum,flags;
register int unit = minor(dev);
register struct controller *ctlrptr = rad_cinfo[unit];
register io_handle_t reg = (io_handle_t) ctlrptr->addr;
caddr_t phys_addr=0;
if (rad_softc[unit].rad_pio_is_mapped){
if ((rad_softc[unit].rad_pio_am) & VME_DENSE)
flags = HANDLE_DENSE_SPACE;
else
flags = HANDLE_SPARSE_SPACE;
/* OR in the access type : eg. HANDLE_LONGWORD */
flags |= (u_int)(rad_softc[unit].rad_pio_access);
/* Change csr I/O handle to a physical address */
phys_addr =
((caddr_t)iohandle_to_phys((io_handle_t)reg, flags));
BPF("*** io_handle = 0x%lx\n",(u_long)reg);
BPF("*** Bus physical address = 0x%lx\n",phys_addr);
phys_addr = (char *)PHYS_TO_KSEG(phys_addr);
BPF("*** Kseg address = 0x%lx\n",phys_addr);
kpfnum = (long) ((((u_long)phys_addr + off) >> 13) & (0x1fffffL));
BPF("*** Page frame number = 0x%x\n",kpfnum);
return((caddr_t)kpfnum);
}else{
pf("rad_mmap: You must do an outbound mapping first. \n");
return(0);
}
}
|