Vyoms OneStopTesting.com - Testing EBooks, Tutorials, Articles, Jobs, Training Institutes etc.
OneStopGate.com - Gate EBooks, Tutorials, Articles, FAQs, Jobs, Training Institutes etc.
OneStopMBA.com - MBA EBooks, Tutorials, Articles, FAQs, Jobs, Training Institutes etc.
OneStopIAS.com - IAS EBooks, Tutorials, Articles, FAQs, Jobs, Training Institutes etc.
OneStopSAP.com - SAP EBooks, Tutorials, Articles, FAQs, Jobs, Training Institutes etc.
OneStopGRE.com - of GRE EBooks, Tutorials, Articles, FAQs, Jobs, Training Institutes etc.
Bookmark and Share Rss Feeds

A Device Driver In C++ (What? In C++?) | Articles | Recent Articles | News Article | Interesting Articles | Technology Articles | Articles On Education | Articles On Corporate | Company Articles | College Articles | Articles on Recession
Sponsored Ads
Hot Jobs
Fresher Jobs
Experienced Jobs
Government Jobs
Walkin Jobs
Placement Section
Company Profiles
Interview Questions
Placement Papers
Resources @ VYOMS
Companies In India
Consultants In India
Colleges In India
Exams In India
Latest Results
Notifications In India
Call Centers In India
Training Institutes In India
Job Communities In India
Courses In India
Jobs by Keyskills
Jobs by Functional Areas
Learn @ VYOMS
GATE Preparation
GRE Preparation
GMAT Preparation
IAS Preparation
SAP Preparation
Testing Preparation
MBA Preparation
News @ VYOMS
Freshers News
Job Articles
Latest News
India News Network
Interview Ebook
Get 30,000+ Interview Questions & Answers in an eBook.
Interview Success Kit - Get Success in Job Interviews
  • 30,000+ Interview Questions
  • Most Questions Answered
  • 5 FREE Bonuses
  • Free Upgrades

VYOMS TOP EMPLOYERS

Wipro Technologies
Tata Consultancy Services
Accenture
IBM
Satyam
Genpact
Cognizant Technologies

Home » Articles » A Device Driver In C++ (What? In C++?)

A Device Driver In C++ (What? In C++?)








Article Posted On Date : Thursday, June 16, 2011


A Device Driver In C++ (What? In C++?)
Advertisements

When you think of writing a device driver, your first reaction may be, "But I haven't brushed up on assembly language in some time." After taking a deep breath, you think of another approach: "Why can't I use a high-level language?" You can. One such language is C++.

In comparison with standard C, C++ offers some definite advantages, including ease of maintenance, portability, and reusability. You can encapsulate data and functions into classes, giving future coders an easier job of maintaining and enhancing what you've done. And you can take advantage of most (but not all) of the powerful features of C++ when you write stand-alone code.

You will run into a few gotchas, including the fact that polymorphism is available only if you do some extra work (for a definition of polymorphism, seedevelop,Issue 2, page 180). Because the virtual tables (vTables) reside in the jump-table segment, a stand- alone code resource can't get at the vTables directly (more on this topic later). You also have to deal with factors such as how parameters are passed to methods, how methods are called, how you return to the Device Manager, how you compile and link the DRVR resource, and how the DRVR resource is installed when the machine starts up. We'll tackle some of these obstacles as we work through the sample device driver presented later in this article.
WHY C++?

When someone suggests writing a device driver in anything other than assembly language, the common reaction is, "But you're talking to a device! Why would you want to use C++?"

For communication with devices, assembly language admittedly gets the job done in minimal time, with maximum efficiency. But if you're writing something where code maintenance, portability, and high-level language functionality are just as important as speed and efficiency, a higher level language is preferable. Not all device drivers actually communicate with physical devices. Many device drivers have more esoteric functions, such as interapplication communication, as in the sample driver in this article. (In fact, DAs are of resource type DRVR and behave exactly the same way device drivers behave. DAs are even created the same way.) For these kinds of device drivers, C++ is a great language to use because you can take advantage of all the features of a high- level language, plus most of the object-based features of C++. Finally, device drivers have some nice features that make them appealing for general usage:

    * They can remain in the system heap, providing a common interface for any application to easily call and use.
    * They get periodic time (if other applications are not hogging the CPU).

Good examples of nondevice drivers are the .MPP (AppleTalk ) driver and the .IPC (A/ROSETM interprocess communication) driver. Both these drivers provide pretty high-level functionality, but neither directly manipulates a device as such (except for the very low-level AppleTalk manipulations of communication ports). Of course, if you were writing code to communicate quickly and efficiently to a modem, for example, assembly language might be the better choice, depending on your need for efficiency and timing. For the purposes of this article, any reference to a device driver includes both types of drivers.

Clearly, higher level languages have a place, but what about object-based languages? Object-based languages provide a great framework for encapsulation of data and functions and hence increase the ease of maintenance and portability (if used elegantly). One question still remains: Why C++?

Notables such as Bjarne Stroustrup and Stanley Lippman have pointed out some of the advantages C++ offers over conventional high-level languages. C++ offers great extensions, such as operator and function overloading, to standard C. C++ is much more strongly type checked than C, so it saves us programmers from ourselves. C++ classes offer a way to encapsulate data--and functions that operate on the data--within one unit. You can make different elements and functions "private" to objects of only one class or "public" to objects of every type. The private and public nature of data and member functions allows you to accomplish real encapsulation.
COMPARING C++ AND ASSEMBLY LANGUAGE
    C++    Assembly Language
Pros    Portable    Fast
    Reusable    Efficient
    Easy to maintain    Compact
    Object-based design    Direct access to CPU
    High-level language features    
    Data encapsulation    
Cons    Three separate source files    Not portable
    multiple compiles    Hard to maintain
    Speed inefficient    Lacking high-level language
    Polymorphism difficult    features such as loops
    in stand-alone code    and IF-THEN-ELSE
SOME LIMITATIONS
As noted, one valuable feature of C++, polymorphism, is not readily available when you write a device driver in C++. Other limitations involve working with assembly language, possible speed sacrifices, work-arounds for intersegment calls, and mangled procedure names.

POLYMORPHISM

Because a device driver is a stand-alone code resource, there is no "global" space or jump table. C++'s virtual function tables (vTables), which are the means to the polymorphism end, live in an application's global space. The loss of virtual tables is a limitation of stand-alone code, not a limitation of C++. Patrick Beard's article, "Polymorphic Code Resources in C++" (this issue), shows one way to work around this limitation. The work-around takes some extra work and is dependent on the current implementation of CFront, which may make future compatibility a problem. In the interests of clarity and compatibility, I have chosen not to use polymorphism for the example in this article.

ASSEMBLY-LANGUAGE MUCK
Another difficulty is that we have to get our hands assembly-language dirty. The Device Manager is going to call the device driver with a few registers pointing to certain structures, and we'll have to put those on the stack so the C++ routines can get to them. Specifically, A0 points to the parameter block that is being passed, and A1 has a handle to the Device Control Entry for the driver. Having to do some assembler work is a limitation of the operating system; the toolbox doesn't push the parameters onto the stack (now if there were glue to do that--).

These registers must somehow make their way onto the stack as parameters to our routines because procedures take their parameters off the stack. When we've finished, we also have to deal with jumping to jIODone or plain RTSing, depending on the circumstances. For the simple driver shown in the example, we will in reality almost always jump via jIODone when finished with our routines. But, for drivers that wish to allow more than one operation at a time, the Prime, Control, and Status calls must return via an RTS to signal the Device Manager that the request has not been completed. The driver's routines should jump to jIODone only when the request is complete.

We must also decide whether or not to call a C++ method directly from the assembly language "glue." If we call the method directly, we have to put the "this" pointer on the stack because it's passed implicitly to all object methods. We also have to use the "mangled" name generated by the compiler and used by the linker. (If you haven't had the opportunity to see mangled names, you'll find they're a joy to figure out without the help of our friend Mr. Unmangle.) So, if we choose to call extern C functions, as the example does, we run into yet another level of "indirection" before we get to the real meat of the matter.

SPEED
Some might say we sacrifice speed as well as efficiency--and they're correct. In general, compilers can't generate optimally speed-efficient code. They can come close, but nothing even approaches how the human mind tackles some tricky machine-level issues. Thus, we're at the mercy of the compiler--the loss of speed is the result of the compiler's inefficiency.

You'll probably find the sample driver presented in this article pretty inefficient. But the trade-off is acceptable because speed isn't important in this case, and you can use all the features of an object-based language. In fact, in most instances you can limit assembly language to a few routines, which must be tightly coded, and use C++ for the rest.

MANGLED IDENTIFIERS
If you're familiar with C++, you've undoubtedly seen the visions of unreadability created by CFront. But, if you're still unfamiliar with C++ in practice, here's an explanation. CFront is simply a preprocessor that creates C code, which is passed to the C compiler. So CFront has to somehow take a function of the form

TDriver::iacOpen(ParmBlkPtr aParmBlkPtr)

and create a C function name the C compiler can understand. The problem is that when the linker complains, it will use the mangled name, which is hard to decipher.

Here's how it looks:
from MPW Shell document

unmangle iacOpen__7TDriverFP13ParamBlockRec
Unmangled symbol: TDriver::iacOpen(ParamBlockRec*)

It's clear why these names are referred to as mangled and unmangled. Fortunately, the unmangle tool provided with MPW allows you to derive the unmangled name from the mangled.
A SAMPLE C++ DRIVER
The sample driver that follows illustrates some of the issues involved in writing a device driver in general, and specifically in C++. The code is in the folder labeled C++ Driver on the Developer Essentials disc.

INTERAPPLICATION COMMUNICATION
The sample driver performs one basic function--interapplication communication (IAC)--under System 6. Under System 7 the services of this sample driver aren't necessary because IAC is built into the system. But the concepts presented here are still sound, and the driver works as well under System 7 as it does under System 6. The driver is installed at Init time with code that walks through the unit table looking for a slot.

CLASS STRUCTURE
The classes are fairly straightforward, serving as an example of how to use C++ to encapsulate data with methods without getting into some gnarly class hierarchies that would only obfuscate the point (and that aren't yet possible with stand-alone code). Two classes suffice:TDriver and TMessage. TDriver handles all the driving; it responds to each control and status call defined and handles opening and closing the driver. It keeps two simple data structures--an array of application names that have registered and an array of TMessage pointers that need to be received. TMessage handles the messages--who they're from, who they're addressed to, and what the message is. I think you'll find the declarations easy reading.

from TDriver.h

class TDriver: public HandleObject {
public:
        // Constructor and destructor.
        TDriver();
        ~TDriver();

    /* Generic driver routines. These are the only public interfaces
     * we show to the world.                                */
    OSErr   iacOpen(ParmBlkPtr oParmBlock);
    OSErr   iacPrime(ParmBlkPtr pParmBlock);
    OSErr   iacControl(ParmBlkPtr cntlParmBlock);
    OSErr   iacStatus(ParmBlkPtr sParmBlock);
    OSErr   iacClose(ParmBlkPtr cParmBlock);
    
private:
    // Control Routines.
    /* RegisterApp takes the string in iacRecord.appName and finds
     * a slot in the array for the name (hence it "registers"
     * the application). SendMessage sends a message from one
     * application to another (as specified by the iacRecord fields).
     * ReceiveMessage puts the message string into the
     * iacRecord.msgString field if there's a message for the
     * requesting application.  UnregisterApp removes the
     * application's name from the array (hence the application is
     * "unregistered").                                 */
    short       RegisterApp(IACRecord   *anIACPtr);
    short       SendMessage(IACRecord   *anIACPtr);
    short       ReceiveMessage(IACRecord    *anIACPtr);
    short       UnregisterApp(IACRecord *anIACPtr);
   
    // Status Routines
    /* WhosThere returns the signature of other applications that
     * have registered.
     * AnyMessagesForMe returns the number of messages waiting for
     * the requesting application in iacRecord.actualCount.     */
    void        WhosThere(IACRecord *anIACPtr);
    Boolean AnyMessagesForMe(IACRecord  *anIACPtr);
   
    // Message array handling routines.
    /* GetMessage gets the TMessPtr in fMessageArray[signature].
     * SetMessage sets the pointer in fMessageArray[signature] to
     * aMsgPtr.                                 */
    TMessPtr    GetMessage(short signature);
    void        SetMessage(short index, TMessPtr    aMsgPtr);
   
    // AppName array handling routines.
    /* GetAppName gets the application name in
     * fAppNameArray[signature].  SetAppName sets the application
     * in fAppNameArray[signature] to anAppName.            */
    char        *GetAppName(short signature);
    void        SetAppName(short signature, char *anAppName);
   

    /* We keep an array of applications that can register with the
     * driver. I've arbitrarily set this at 16. We also keep an array
     * of TMessage pointers to be passed around. This is also
     * arbitrarily set at 16. In the future, I'd probably implement
     * this as a list of messages.                                */
    char        fAppNameArray[kMaxApps] [255];
    TMessPtr    fMessageArray[kMaxMessages];
};

from TMessage.h

class TMessage {
public:
        /* Constructor and destructor. Constructor will build the
         * message with the appropriate data members passed in.    */
        TMessage(char *message, short senderSig, short receiverSig);
        ~TMessage();
               
        /* Two Boolean functions that simply query the message to see
         * if the message is destined for the signature of the
         * Requestor. Nice example of function overloading-in the
         * one case I just wanted to return true or false; in the
         * other case I wanted to return who the message was from and
         * the actual message string. This is also nice because we
         * have only one public member function returning any private
         * information.                                            */
    Boolean IsMessageForMe(short sigOfRequestor);
    Boolean IsMessageForMe(short sigOfRequestor, short *senderSig,
                     char *messageString);
   
private:
    /* GetSenderSig returns fSenderSig.
     * SetSenderSig sets fSenderSig to signature.           */
    short       GetSenderSig();
    void        SetSenderSig(short signature);
   
    /* GetReceiverSig returns fReceiverSig.
     * SetReceiverSig sets fReceiverSig to signature.       */
    short       GetReceiverSig();
    void        SetReceiverSig(short signature);
   
    /* GetMessageString returns fMessageString.
     * SetMessageString sets fMessageString to msgString.   */
    char        *GetMessageString();
    void        SetMessageString(char *msgString);
   


    // Private data members. Again, we keep storage for the string
    // here.
    short       fSenderSig;
    short       fReceiverSig;
    char        fMessageString[255];
};

The only remaining structure worthy of note is the IACRecordstructure. This structure is passed in the csParam field of the parameter block pointers passed to the driver. Essentially the IACRecord structure contains all the control information, or returns all the status information, the application needs to communicate--the signatures of the sender and receiver, the message and application name strings, and a couple of other control fields.

from IACHeaders.h

struct IACRecord    {
    // Signature number of application sending/receiving.
    short   mySignature;

    // Signature of app that's either sent a message or        
    // of app to which the current app is sending.
    short   partnerSig;
                   
    // Index to cycle through the apps that have registered.
    short   indexForWhosThere;

    // Nonzero if messages there for recipient.
    short   actualCount;

    // Message string being sent or received.
    char*   messageString;

    // String to register as.
    char    *appName;
};

REGISTERING WITH THE DRIVER
To use the driver, an application registers itself with the driver, thus signifying that the application is able to receive and send messages. The driver returns a unique signature for the application to use throughout the communication session. A second (or third, or fourth) application also registers and communicates with other applications by sending and receiving messages using the correct signature. When an application is finished, it simply unregisters itself. Here are four of the methods that do most of the work:from TDriver.cp

/*********************************Comment**************************
* TDriver::RegisterApp looks to see if there's an open "slot".
* If so, it sets the new AppName for that "slot" and
* returns the "slot" as the signature.  If it couldn't find any
* open "slots" then it returns the kNoMore error.
 *********************************End Comment*********************/
short
TDriver::RegisterApp(IACRecord *anIACPtr)
{
short       i = 0;
short       canDo = kNoMore;

while ((i < kMaxApps) && (canDo == kNoMore))
    {
    if((this->GetAppName(i))[0] == kZeroChar)
        {
        canDo = kNoErr;
        anIACPtr->mySignature = i;
        this->SetAppName(i,anIACPtr->appName);
        }
    i++;
    }
return (canDo);
} //  TDriver::RegisterApp

/*********************************Comment**************************
* TDriver::SendMessage has to instantiate a new message object.  It
* also has to remember that message for later when someone tries to
* receive it.  To remember it, the TDriver object places it in the
* message pointer array.  If it couldn't find an open "slot" in
* the array, it returns the error kMsgMemErr, meaning it has no
* memory to store the pointer to the message and hence the message
* didn't get sent. Since the TDriver object is creating a new
* TMessage, it will destroy the TMessage when the time comes.
 *********************************End Comment*********************/
short
TDriver::SendMessage(IACRecord *anIACPtr)
{
TMessPtr    aMsgPtr;
short       canDo = kNoMore;
short       i = 0;

aMsgPtr = new TMessage(anIACPtr->messageString,
        anIACPtr->mySignature, anIACPtr->partnerSig);

if(aMsgPtr)
    {
    while ((i < kMaxMessages) && (canDo == kNoMore))
        {
        if(this->GetMessage(i) == nil)
            {
            this->SetMessage(i, aMsgPtr);
            canDo = kNoErr;
            }
        i++;
        }
    if (canDo == kNoMore)
        delete aMsgPtr;
    } // if aMsgPtr
else
    canDo = kMsgMemErr;
return (canDo);    
} //  TDriver::SendMessage

/**********************************Comment***************************
* TDriver::ReceiveMessage finds any messages for the application
* whose signature is mySignature. It first checks to see if there
* are any  messages. If so, it gets the message and asks the TMessage
* object to return the message string. Then it copies the message
* string to the calling application's message buffer, puts the
* sender's signature in "partnerSig", and puts the sender's
* application name in appName. It then sets the "slot" in the
* message array to nil and disposes of the TMessage object. If there
* were messages, it returns the kYesMessagesForMe value; otherwise it
* returns kNoMore.
 **********************************End Comment*********************/
short
TDriver::ReceiveMessage(IACRecord *anIACPtr)
{
TMessPtr        aMsgPtr;
short           sender;
char            *bufP = nil;

if(this->AnyMessagesForMe(anIACPtr))
    {
    aMsgPtr = this->GetMessage(anIACPtr->actualCount);
    (void) aMsgPtr->IsMessageForMe
        (anIACPtr->mySignature,&sender,bufP);  
    anIACPtr->partnerSig = sender;
    tseStrCpy(anIACPtr->messageString,bufP);
    tseStrCpy(anIACPtr->appName,
        this->GetAppName(anIACPtr->partnerSig));
    this->SetMessage(anIACPtr->actualCount,nil);

        delete aMsgPtr;
        return (kYesMessagesForMe);
        }
else
        return(kNoMore);
} // TDriver::ReceiveMessage

/************************Comment***************************
* TDriver::UnregisterApp receives all the messages for the
* application that is unregistering. Those messages will
* just get thrown away. So, all the messages destined for
* it are disposed of, and then it sets the name to '






Sponsored Ads



Interview Questions
HR Interview Questions
Testing Interview Questions
SAP Interview Questions
Business Intelligence Interview Questions
Call Center Interview Questions

Databases

Clipper Interview Questions
DBA Interview Questions
Firebird Interview Questions
Hierarchical Interview Questions
Informix Interview Questions
Microsoft Access Interview Questions
MS SqlServer Interview Questions
MYSQL Interview Questions
Network Interview Questions
Object Relational Interview Questions
PL/SQL Interview Questions
PostgreSQL Interview Questions
Progress Interview Questions
Relational Interview Questions
SQL Interview Questions
SQL Server Interview Questions
Stored Procedures Interview Questions
Sybase Interview Questions
Teradata Interview Questions

Microsof Technologies

.Net Database Interview Questions
.Net Deployement Interview Questions
ADO.NET Interview Questions
ADO.NET 2.0 Interview Questions
Architecture Interview Questions
ASP Interview Questions
ASP.NET Interview Questions
ASP.NET 2.0 Interview Questions
C# Interview Questions
Csharp Interview Questions
DataGrid Interview Questions
DotNet Interview Questions
Microsoft Basics Interview Questions
Microsoft.NET Interview Questions
Microsoft.NET 2.0 Interview Questions
Share Point Interview Questions
Silverlight Interview Questions
VB.NET Interview Questions
VC++ Interview Questions
Visual Basic Interview Questions

Java / J2EE

Applet Interview Questions
Core Java Interview Questions
Eclipse Interview Questions
EJB Interview Questions
Hibernate Interview Questions
J2ME Interview Questions
J2SE Interview Questions
Java Interview Questions
Java Beans Interview Questions
Java Patterns Interview Questions
Java Security Interview Questions
Java Swing Interview Questions
JBOSS Interview Questions
JDBC Interview Questions
JMS Interview Questions
JSF Interview Questions
JSP Interview Questions
RMI Interview Questions
Servlet Interview Questions
Socket Programming Interview Questions
Springs Interview Questions
Struts Interview Questions
Web Sphere Interview Questions

Programming Languages

C Interview Questions
C++ Interview Questions
CGI Interview Questions
Delphi Interview Questions
Fortran Interview Questions
ILU Interview Questions
LISP Interview Questions
Pascal Interview Questions
Perl Interview Questions
PHP Interview Questions
Ruby Interview Questions
Signature Interview Questions
UML Interview Questions
VBA Interview Questions
Windows Interview Questions
Mainframe Interview Questions


Copyright © 2001-2020 Vyoms.com. All Rights Reserved. Home | About Us | Advertise With Vyoms.com | Jobs | Contact Us | Feedback | Link to Us | Privacy Policy | Terms & Conditions
Placement Papers | Get Your Free Website | IAS Preparation | C++ Interview Questions | C Interview Questions | Report a Bug | Romantic Shayari | CAT 2020

Fresher Jobs | Experienced Jobs | Government Jobs | Walkin Jobs | Company Profiles | Interview Questions | Placement Papers | Companies In India | Consultants In India | Colleges In India | Exams In India | Latest Results | Notifications In India | Call Centers In India | Training Institutes In India | Job Communities In India | Courses In India | Jobs by Keyskills | Jobs by Functional Areas

Testing Articles | Testing Books | Testing Certifications | Testing FAQs | Testing Downloads | Testing Interview Questions | Testing Jobs | Testing Training Institutes

Gate Articles | Gate Books | Gate Colleges | Gate Downloads | Gate Faqs | Gate Jobs | Gate News | Gate Sample Papers | Gate Training Institutes

MBA Articles | MBA Books | MBA Case Studies | MBA Business Schools | MBA Current Affairs | MBA Downloads | MBA Events | MBA Notifications | MBA FAQs | MBA Jobs
MBA Job Consultants | MBA News | MBA Results | MBA Courses | MBA Sample Papers | MBA Interview Questions | MBA Training Institutes

GRE Articles | GRE Books | GRE Colleges | GRE Downloads | GRE Events | GRE FAQs | GRE News | GRE Training Institutes | GRE Sample Papers

IAS Articles | IAS Books | IAS Current Affairs | IAS Downloads | IAS Events | IAS FAQs | IAS News | IAS Notifications | IAS UPSC Jobs | IAS Previous Question Papers
IAS Results | IAS Sample Papers | IAS Interview Questions | IAS Training Institutes | IAS Toppers Interview

SAP Articles | SAP Books | SAP Certifications | SAP Companies | SAP Study Materials | SAP Events | SAP FAQs | SAP Jobs | SAP Job Consultants
SAP Links | SAP News | SAP Sample Papers | SAP Interview Questions | SAP Training Institutes |


Copyright ©2001-2020 Vyoms.com, All Rights Reserved.
Disclaimer: VYOMS.com has taken all reasonable steps to ensure that information on this site is authentic. Applicants are advised to research bonafides of advertisers independently. VYOMS.com shall not have any responsibility in this regard.