Annotation of XNU/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2Controller.h, revision 1.1.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.