Annotation of XNU/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2Controller.h, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: 
        !            23: #ifndef _APPLEPS2CONTROLLER_H
        !            24: #define _APPLEPS2CONTROLLER_H
        !            25: 
        !            26: #include <IOKit/IOInterruptEventSource.h>
        !            27: #include <IOKit/IOService.h>
        !            28: #include <IOKit/IOWorkLoop.h>
        !            29: #include <IOKit/IOCommandQueue.h>
        !            30: #include <IOKit/ps2/ApplePS2Device.h>
        !            31: 
        !            32: class ApplePS2KeyboardDevice;
        !            33: class ApplePS2MouseDevice;
        !            34: 
        !            35: //
        !            36: // This section describes the problem with the PS/2 controller design and what
        !            37: // we are doing about it (OUT_OF_ORDER_DATA_CORRECTION_FEATURE).
        !            38: //
        !            39: // While the controller processes requests sent by the client drivers, at some
        !            40: // point in most requests, a read needs to be made from the data port to check
        !            41: // an acknowledge or receive some sort of data.  We illustrate this issue with
        !            42: // an example -- a write LEDs request to the keyboard:
        !            43: //
        !            44: // 1. Write        Write LED command.
        !            45: // 2. Read   0xFA  Verify the acknowledge (0xFA).
        !            46: // 3. Write        Write LED state.
        !            47: // 4. Read   0xFA  Verify the acknowledge (0xFA).
        !            48: //
        !            49: // The problem is that the keyboard (when it is enabled) can send key events
        !            50: // to the controller at any time, including when the controller is expecting
        !            51: // to read an acknowledge next.  What ends up happening is this sequence:
        !            52: //
        !            53: // a. Write        Write LED command.
        !            54: // b. Read   0x21  Keyboard reports [F] key was depressed, not realizing that
        !            55: //                 we're still expecting a response to the command we  JUST
        !            56: //                 sent the keyboard.  We receive 0x21 as a response to our
        !            57: //                 command, and figure the command failed.
        !            58: // c. Get    0xFA  Keyboard NOW decides to respond to the command with an
        !            59: //                 acknowledge.    We're not waiting to read anything, so
        !            60: //                 this byte gets dispatched to the driver's interrupt
        !            61: //                 handler, which spews out an error message saying it
        !            62: //                 wasn't expecting an acknowledge.
        !            63: //
        !            64: // What can we do about this?  In the above case, we can take note of the fact
        !            65: // that we are specifically looking for the 0xFA acknowledgement byte (through
        !            66: // the information passed in the kPS2C_ReadAndCompare primitive).  If we don't
        !            67: // receive this byte next on the input data stream, we put the byte we did get
        !            68: // aside for a moment, and give the keyboard (or mouse) a second chance to
        !            69: // respond correctly.
        !            70: //
        !            71: // If we receive the 0xFA acknowledgement byte on the second read, that we
        !            72: // assume that situation described above just happened.   We transparently
        !            73: // dispatch the first byte to the driver's interrupt handler, where it was
        !            74: // meant to go, and return the second correct byte to the read-and-compare
        !            75: // logic, where it was meant to go.  Everyone wins.
        !            76: //
        !            77: // The only situation this feature cannot help is where a kPS2C_ReadDataPort
        !            78: // primitive is issued in place of a kPS2C_ReadDataPortAndCompare primitive.
        !            79: // This is necessary in some requests because the driver does not know what
        !            80: // it is going to receive.   This can be illustrated in the mouse get info
        !            81: // command.
        !            82: //
        !            83: // 1. Write        Prepare to write to mouse.
        !            84: // 2. Write        Write information command.
        !            85: // 3. Read   0xFA  Verify the acknowledge (0xFA). __-> mouse can report mouse
        !            86: // 4. Read         Get first information byte.    __-> packet bytes in between
        !            87: // 5. Read         Get second information byte.   __-> these reads
        !            88: // 6. Rrad         Get third information byte.
        !            89: //
        !            90: // Controller cannot build any defenses against this.  It is suggested that the
        !            91: // driver writer disable the mouse first, then send any dangerous commands, and
        !            92: // re-enable the mouse when the command completes. 
        !            93: //
        !            94: // Note that the OUT_OF_ORDER_DATA_CORRECTION_FEATURE can be turned off at
        !            95: // compile time.    Please see the readDataPort:expecting: method for more
        !            96: // information about the assumptions necessary for this feature.
        !            97: //
        !            98: 
        !            99: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        !           100: // Definitions
        !           101: //
        !           102: 
        !           103: // Enable debugger support (eg. mini-monitor).
        !           104: 
        !           105: #define DEBUGGER_SUPPORT 1
        !           106: 
        !           107: // Enable dynamic "second chance" re-ordering of input stream data if a
        !           108: // command response fails to match the expected byte.
        !           109: 
        !           110: #define OUT_OF_ORDER_DATA_CORRECTION_FEATURE 1
        !           111: 
        !           112: // PS/2 device types.
        !           113: 
        !           114: typedef enum { kDT_Keyboard, kDT_Mouse } PS2DeviceType;
        !           115: 
        !           116: // Interrupt definitions.
        !           117: 
        !           118: #define kIRQ_Keyboard           1
        !           119: #define kIRQ_Mouse              12
        !           120: #define kIPL_Keyboard           6
        !           121: #define kIPL_Mouse              3
        !           122: 
        !           123: // Port timings.
        !           124: 
        !           125: #define kDataDelay              7       // usec to delay before data is valid
        !           126: 
        !           127: // Ports used to control the PS/2 keyboard/mouse and read data from it.
        !           128: 
        !           129: #define kDataPort               0x60    // keyboard data & cmds (read/write)
        !           130: #define kCommandPort            0x64    // keybd status (read), command (write)
        !           131: 
        !           132: // Bit definitions for kCommandPort read values (status).
        !           133: 
        !           134: #define kOutputReady            0x01    // output (from keybd) buffer full
        !           135: #define kInputBusy              0x02    // input (to keybd) buffer full
        !           136: #define kSystemFlag             0x04    // "System Flag"
        !           137: #define kCommandLastSent        0x08    // 1 = cmd, 0 = data last sent
        !           138: #define kKeyboardInhibited      0x10    // 0 if keyboard inhibited
        !           139: #define kMouseData              0x20    // mouse data available
        !           140: 
        !           141: #if DEBUGGER_SUPPORT
        !           142: // Definitions for our internal keyboard queue (holds keys processed by the
        !           143: // interrupt-time mini-monitor-key-sequence detection code).
        !           144: 
        !           145: #define kKeyboardQueueSize 32            // number of KeyboardQueueElements
        !           146: 
        !           147: typedef struct KeyboardQueueElement KeyboardQueueElement;
        !           148: struct KeyboardQueueElement
        !           149: {
        !           150:   queue_chain_t chain;
        !           151:   UInt8         data;
        !           152: };
        !           153: #endif DEBUGGER_SUPPORT
        !           154: 
        !           155: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        !           156: // ApplePS2Controller Class Declaration
        !           157: //
        !           158: 
        !           159: class ApplePS2Controller : public IOService
        !           160: {
        !           161:   OSDeclareDefaultStructors(ApplePS2Controller);
        !           162: 
        !           163: public:                                // interrupt-time variables and functions
        !           164:   IOInterruptEventSource * _interruptSourceKeyboard;
        !           165:   IOInterruptEventSource * _interruptSourceMouse;
        !           166: 
        !           167: #if DEBUGGER_SUPPORT
        !           168:   void lockController(void);
        !           169:   void unlockController(void);
        !           170: 
        !           171:   bool doEscape(UInt8 key);
        !           172:   bool dequeueKeyboardData(UInt8 * key);
        !           173:   void enqueueKeyboardData(UInt8 key);
        !           174: #endif DEBUGGER_SUPPORT
        !           175: 
        !           176: private:
        !           177:   IOCommandQueue *         _commandQueue;
        !           178:   IOWorkLoop *             _workLoop;
        !           179: 
        !           180:   OSObject *               _interruptTargetKeyboard;
        !           181:   OSObject *               _interruptTargetMouse;
        !           182:   PS2InterruptAction       _interruptActionKeyboard;
        !           183:   PS2InterruptAction       _interruptActionMouse;
        !           184:   bool                     _interruptInstalledKeyboard;
        !           185:   bool                     _interruptInstalledMouse;
        !           186: 
        !           187:   ApplePS2MouseDevice *    _mouseDevice;          // mouse nub
        !           188:   ApplePS2KeyboardDevice * _keyboardDevice;       // keyboard nub
        !           189: 
        !           190: #if DEBUGGER_SUPPORT
        !           191:   usimple_lock_data_t      _controllerLock;       // mach simple spin lock
        !           192:   int                      _controllerLockOldSpl; // spl before lock taken
        !           193: 
        !           194:   KeyboardQueueElement *   _keyboardQueueAlloc;   // queues' allocation space
        !           195:   queue_head_t             _keyboardQueue;        // queue of available keys
        !           196:   queue_head_t             _keyboardQueueUnused;  // queue of unused entries
        !           197: 
        !           198:   bool                     _extendedState;
        !           199:   UInt16                   _modifierState;
        !           200: #endif DEBUGGER_SUPPORT
        !           201: 
        !           202:   virtual void  dispatchDriverInterrupt(PS2DeviceType deviceType, UInt8 data);
        !           203:   virtual void  interruptOccurred(IOInterruptEventSource *, int);
        !           204:   virtual void  processRequest(PS2Request * request, void *, void *, void *);
        !           205:   static  void  submitRequestAndBlockCompletion(void *, void * param);
        !           206: 
        !           207:   virtual UInt8 readDataPort(PS2DeviceType deviceType);
        !           208:   virtual void  writeCommandPort(UInt8 byte);
        !           209:   virtual void  writeDataPort(UInt8 byte);
        !           210: 
        !           211: #if OUT_OF_ORDER_DATA_CORRECTION_FEATURE
        !           212:   virtual UInt8 readDataPort(PS2DeviceType deviceType, UInt8 expectedByte);
        !           213: #endif
        !           214: 
        !           215: public:
        !           216:   virtual bool init(OSDictionary * properties);
        !           217:   virtual bool start(IOService * provider);
        !           218:   virtual void stop(IOService * provider);
        !           219: 
        !           220:   virtual IOWorkLoop * getWorkLoop() const;
        !           221: 
        !           222:   virtual void installInterruptAction(PS2DeviceType      deviceType,
        !           223:                                       OSObject *         target,
        !           224:                                       PS2InterruptAction action);
        !           225:   virtual void uninstallInterruptAction(PS2DeviceType deviceType);
        !           226: 
        !           227:   virtual PS2Request * allocateRequest();
        !           228:   virtual void         freeRequest(PS2Request * request);
        !           229:   virtual bool         submitRequest(PS2Request * request);
        !           230:   virtual void         submitRequestAndBlock(PS2Request * request);
        !           231: };
        !           232: 
        !           233: #endif /* _APPLEPS2CONTROLLER_H */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.