Entry Points Routine

How do we pronounciate bdevsw and cdevsw Kernel resources ?

I presume it as block or charcter device software table. Am I Correct in my assumption ?

Thanks in advance.

They are tables of entry points to device drivers. All drivers have entries in these tables. The index to the tables is called the major number. By convention, if a device has both a block and character device, the same major number is used for both tables.

For example, if you have a device:
dev_t x;

You can do something like:
(*bdevsw[major(x)].strategy)(bp);

to call the proper strategy routine for the given device. That's how the kernel gets the right driver for the right device.

I do understand that Perderabo. I am working on SCO ver 5.05. SCO has following device driver entry points : close , halt , init , intr , ioctl , open , pminit , poll , print , probe , proc , read , start , strategy , write. Appologies if I am wrong.
I would like reframe my question again :
a)What is the full extension for the kernel resource structure 'bdevsw' and 'cdevsw' . Is it block or charcter device software table or just pronounced as 'bdevsw' and 'cdevsw'.
b)In a streams device driver is it that the all the modules in the driver read and write queue has its own read and write queues. Modules communicate with each other with respect to their read or wirte queues but are confied to the driver's read or write queue modules only. For elaborating my idea I put forward a virtual visual diagram. The pair of driver's read and write queues can be imagined as a pair of set of train tracks.Modules can be thaught as stations capable of doing some processing. It is not necessary that number of modules in write queue be the same in read queue of the driver.The module in the driver write queue can refer to its read/write queue but it cannot refer to the read or write queue's of any module in read queue of the driver.If you are abel to get the picture,is my opinion correct ?

Thanks in advance for all technical helps.

Thanks in advance.

I'll have to take your word for the list of entry points on SCO. It is a longer list than I used to seeing, but I haven't looked at many kernels.

You seem to asking how to verbally pronounce bdevsw and cdevsw. Gosh, I don't know. They're simply variable names. It never occurred to me to attempt to speak them nor have I ever heard anyone else try. It's obvious that the names come from "block device switch" and "character device switch". I hereby opine that the correct pronuciation is "bee dev switch" and "see dev switch" where "dev is pronounced like the first syllable of "devil". But I just made that up.

I am not really a Streams expert, but I *think* that your picture is wrong. First, I think that the modules on the read and write queues do indeed need to match. And in fact I think of it as a single module that simply handles both queues. I'd be a little surprised if I have this wrong.

Second, I am not sure if modules can peek at the queues of other modules or not. The case that has me worried is the need for exceptional processing for flow control. For example, in a tty driver driver, you may need to write an X-off character as soon as the read queues downstream start to back up. I am not at all sure about this, though.

When the UNIX operating system goes to process the open system call, it internally finds out the major number of the file.It uses the major number to index into a table of all of the character drivers installed ( if the file is a character special file ).The declaration within the table contains information in the structure "see dev switch" which has a member variable of type pointer to struct streamtab. The said variable is supposed to contain info about the read and write queues in type structure struct qinit format.The read queue need not have the put procedure while the write need not have open and close procedure.

I am bit confused at this junction. If the read and write queue has different entry points .... the modules on the read and write queues are not matching ? When we insert a module into the stream it is inserted just after the head and modules will be poped out in LIFO way. I am unable to get the full picture clear, the basic being how does the entry points modules linked to the read and write queue and as to how the picture looks like when modules are inserted. Further more where in the picture the "read/write services" fits in with respect to queues?

I know I would be sounding a bit foolish but I need to clear all my doubts at elementary level. Thanks in advance for all your help.

The stream head module has entry points for read, write, open, close, select, and ioctl. These entry points get placed in the cdevsw table and they are called pretty much like any other driver. In the case read and write, the data is coming from or going to buffers in the invoking process. The queue structures are not directly visable to the system calls. The stream head has the job of moving data between the queues and the user's buffers. It also does whatever else it takes to make the stream look like a device driver. This includes error checking the user's parameters and possibly setting errno. In the case a severe user error, it may not even look at the queue structures. Those queue structures are used for module to module communication.

Perderabo , as you say "The stream head module has entry points for read, write, open, close, select, and ioctl." , I just cannot figure it out then why,as I have stated "The declaration within the table contains information in the structure "see dev switch" has a member variable of type pointer to struct streamtab. The said variable is supposed to contain info about the read and write queues in type structure struct qinit format.The read queue need not have the put procedure while the write need not have open and close procedure. ", in my earlier posting, that why at all a read or write queue should be initialized if the stream head module has all the entry points ?

Thanks in advance for all help.

As far as I know, it doesn't; and you are in error if you think it does. Here is cdevsw from HP-UX 11.0:

 
/*
 * Character device switch.
 */
struct cdevsw
{
        d_open_t        d_open;
        d_close_t       d_close;
        d_read_t        d_read;
        d_write_t       d_write;
        d_ioctl_t       d_ioctl;
        d_select_t      d_select;
        d_option1_t     d_option1;
        int             d_flags;       /* C_MGR_IS_MP is valid for this field */
        void            *d_drv_info;
        pfilter_t       *d_pfilter_s;
        aio_ops_t       *d_aio_ops;
};

To use d_read as an example, The type of d_read is:
typedef int (*d_read_t) __((dev_t dev, struct uio *uio));
And that typedef does not magically change into a pointer to a qinit structure if the current entry happens to be a streams based driver. Any time the read or readv system call invokes the read routine of a character driver, that read routine is passed a device and a uio structure. Every read of a character device is treated this way. No there no exception for streams-based character drivers.

The cdevsw for osf1 is similiar but with much less type checking:

struct cdevsw
{
        int     (*d_open)();
        int     (*d_close)();
        int     (*d_read)();
        int     (*d_write)();
        int     (*d_ioctl)();
        int     (*d_stop)();
        int     (*d_reset)();
        struct tty *d_ttys;
        int     (*d_select)();
        int     (*d_mmap)();
        int     d_funnel;       /* serial code compatibility */
        int     (*d_segmap)();          /* xxx_segmap() entry point */
        int     d_flags;                /* if (C_DDIDKI), driver follows
                                           SVR4 DDI/DKI interfaces*/
};

Without strong typechecking it's hard to prove exactly what d_read is. But that DDI/DKI stands for Device Driver Interface/Driver Kernel Interface. You can be sure that a system that supports that standard is not going to turn d_read into a pointer to a qinit structure.

If you post again claiming that your cdevsw has pointers to qinit (or other stream) structures, please also post some evidence as well. I would also like to know which stream structure you think that your d_ioctl points to.

As originally posted by Perderabo
"No there no exception for streams-based character drivers. "

Following is the cdevsw structure that we are using for developing stream device drivers in Sun and Sco unix Servers.
strcut cdevsw {
int (*d_open)( );
int (*d_close)( );
int (*d_read)( );
int (*d_write)( );
int (*d_ioctl)( );
struct tty *d_ttys ;
strcut streamtab *d_str;
char *d_name ;
};
Streams drivers have some similarites with character device drivers. A Stream driver may include init, start , halt and intr entry points.They must include open and close entry points.In addition, there are entry points that are specific to Streams driver: read and write queue service (xxsrv) read and write queue put functions.The put entry points are required with exception of the read side of a driver.The service entry points are optional.The put and service entry points are associated with each queue, and since each module and driver has two queues, each module and driver may have two put and two service entry points.The put routine is called to place a message on a queue and perform any processing that must be done immediately.The Stream head converts a write system call into a message and invokes the put routine for downstream module's write queue.This routine examines the message, performs any processing and either passes the message downstream or places it on its own queue for later processing.The Stream Device driver on the write side must provide a put entry point that may be called by the upstream module to pass message message down the stream.It may provide a write side service routine.On the read side the interrupt or poll takes the data from device and passes it to the driver's read queue or any module upstream.
.....
.....
int xxopen(),xxclose(),...... ;
static struct qinit rinit = { NULL , NULL , xxopen,xxclose,.......} ;
static struct qinit winit = { xxput, xxsrv,NULL,.......};
strcut streamtab xxinfo = {&rinit,&winit,.......};
The qinit structure contians the info for read and write queues.

I do hope I justify my stand quiet clear and sound now.The read and write queue need to be intialized.But I need a bit more of explanation.As in reference to ioctl , I think the context in which it is called is blockable but in case of streams the ioctls are transparent.That's all I know.

Well, I went looking for Sun's cdevsw. It took me several minutes to figure out why I can't find it. They don't have one. Sun uses a structure called cb_ops instead. (Are you getting your driver to compile on a Sun?? Which version of the OS?) But anyway, they do have full prototypes. The read entry is:
int (*cb_read)(dev_t dev, struct uio *uiop, Cred_t *credp)

However, the cb_ops table does indeed contain a pointer to a streamtab strucrure! I just called a friend of mine who has access to an SCO box. He mailed me his conf.h file and sure enough there is a pointer to a streamtab structure there. Like you, I don't understand what that pointer is for.

Looking at Sun's website, I found this SunOS streams-based pty driver and I can't believe what I see. They are setting cb_read and cb_write to nodev!! I can only guess that the read() system call will notice the "nodev" and the presence of the streamtab pointer and then do what is needed to invoke the read queue directly.

I don't understand this implementation but apparently, if you establish the proper streamtab and qinit structures it's gonna work on a Sun. And maybe that's how SCO works as well.

As originally posted by Perderabo
"No there no exception for streams-based character drivers. "
I guess I'll have to eat those words. It would seem to depend on the specific OS.