Keyboard.cpp

Go to the documentation of this file.
00001 /* ES40 emulator.
00002  * Copyright (C) 2007-2008 by the ES40 Emulator Project
00003  *
00004  * WWW    : http://sourceforge.net/projects/es40
00005  * E-mail : camiel@camicom.com
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020  * 
00021  * Although this is not required, the author would appreciate being notified of, 
00022  * and receiving any modifications you may make to the source code that might serve
00023  * the general public.
00024  */
00025 
00063 #include "StdAfx.h"
00064 #include "System.h"
00065 #include "Keyboard.h"
00066 #include "AliM1543C.h"
00067 #include <math.h>
00068 
00069 #include "gui/scancodes.h"
00070 #include "gui/keymap.h"
00071 
00075 CKeyboard::CKeyboard(CConfigurator* cfg, CSystem* c) : CSystemComponent(cfg, c)
00076 {
00077   if(theKeyboard != 0)
00078     FAILURE(Configuration, "More than one Keyboard controller");
00079   theKeyboard = this;
00080 }
00081 
00085 void CKeyboard::init()
00086 {
00087   int i;
00088 
00089   cSystem->RegisterMemory(this, 0, U64(0x00000801fc000060), 1);
00090   cSystem->RegisterMemory(this, 1, U64(0x00000801fc000064), 1);
00091 
00092   resetinternals(1);
00093 
00094   state.kbd_internal_buffer.led_status = 0;
00095   state.kbd_internal_buffer.scanning_enabled = 1;
00096 
00097   state.mouse_internal_buffer.num_elements = 0;
00098   for(i = 0; i < BX_MOUSE_BUFF_SIZE; i++)
00099     state.mouse_internal_buffer.buffer[i] = 0;
00100   state.mouse_internal_buffer.head = 0;
00101 
00102   state.status.pare = 0;
00103   state.status.tim = 0;
00104   state.status.auxb = 0;
00105   state.status.keyl = 1;
00106   state.status.c_d = 1;
00107   state.status.sysf = 0;
00108   state.status.inpb = 0;
00109   state.status.outb = 0;
00110 
00111   state.kbd_clock_enabled = 1;
00112   state.aux_clock_enabled = 0;
00113   state.allow_irq1 = 1;
00114   state.allow_irq12 = 1;
00115   state.kbd_output_buffer = 0;
00116   state.aux_output_buffer = 0;
00117   state.last_comm = 0;
00118   state.expecting_port60h = 0;
00119   state.irq1_requested = 0;
00120   state.irq12_requested = 0;
00121   state.expecting_mouse_parameter = 0;
00122   state.bat_in_progress = 0;
00123   state.scancodes_translate = 1;
00124 
00125   state.timer_pending = 0;
00126 
00127   // Mouse initialization stuff
00128   state.mouse.captured = myCfg->get_bool_value("mouse.enabled", true);
00129   state.mouse.sample_rate = 100;    // reports per second
00130   state.mouse.resolution_cpmm = 4;  // 4 counts per millimeter
00131   state.mouse.scaling = 1;          /* 1:1 (default) */
00132   state.mouse.mode = MOUSE_MODE_RESET;
00133   state.mouse.enable = 0;
00134   state.mouse.delayed_dx = 0;
00135   state.mouse.delayed_dy = 0;
00136   state.mouse.delayed_dz = 0;
00137   state.mouse.im_request = 0;       // wheel mouse mode request
00138   state.mouse.im_mode = 0;          // wheel mouse mode
00139   for(i = 0; i < BX_KBD_CONTROLLER_QSIZE; i++)
00140     state.kbd_controller_Q[i] = 0;
00141   state.kbd_controller_Qsize = 0;
00142   state.kbd_controller_Qsource = 0;
00143 
00144   myThread = 0;
00145 
00146   printf("kbc: $Id: Keyboard.cpp,v 1.9 2008/03/16 11:22:08 iamcamiel Exp $\n");
00147 }
00148 
00149 void CKeyboard::start_threads()
00150 {
00151   if(!myThread)
00152   {
00153     myThread = new Poco::Thread("kbd");
00154     printf(" %s", myThread->getName().c_str());
00155     StopThread = false;
00156     myThread->start(*this);
00157   }
00158 }
00159 
00160 void CKeyboard::stop_threads()
00161 {
00162   StopThread = true;
00163   if(myThread)
00164   {
00165     printf(" %s", myThread->getName().c_str());
00166     myThread->join();
00167     delete myThread;
00168     myThread = 0;
00169   }
00170 }
00171 
00175 CKeyboard::~CKeyboard()
00176 {
00177   stop_threads();
00178 }
00179 
00180 u64 CKeyboard::ReadMem(int index, u64 address, int dsize)
00181 {
00182   switch(index)
00183   {
00184   case 0:   return read_60(); break;
00185   case 1:   return read_64(); break;
00186   default:  FAILURE(InvalidArgument, "kbc: ReadMem index out of range");
00187   }
00188 }
00189 
00190 void CKeyboard::WriteMem(int index, u64 address, int dsize, u64 data)
00191 {
00192   switch(index)
00193   {
00194   case 0:   write_60((u8) data); break;
00195   case 1:   write_64((u8) data); break;
00196   default:  FAILURE(InvalidArgument, "kbc: ReadMem index out of range");
00197   }
00198 }
00199 
00204 void CKeyboard::gen_scancode(u32 key)
00205 {
00206   unsigned char*  scancode;
00207   u8              i;
00208 
00209 #if defined(DEBUG_KBD)
00210   printf("gen_scancode(): %s %s  \n", bx_keymap->getBXKeyName(key),
00211          (key >> 31) ? "released" : "pressed");
00212   if(!state.scancodes_translate)
00213     BX_DEBUG(("keyboard: gen_scancode with scancode_translate cleared"));
00214 #endif
00215 
00216   // Ignore scancode if keyboard clock is driven low
00217   if(state.kbd_clock_enabled == 0)
00218     return;
00219 
00220   // Ignore scancode if scanning is disabled
00221   if(state.kbd_internal_buffer.scanning_enabled == 0)
00222     return;
00223 
00224   // Source: http://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html
00225   //
00226   // Three scancode sets
00227   //
00228   // The usual PC keyboards are capable of producing three sets
00229   // of scancodes. Writing 0xf0 followed by 1, 2 or 3 to port
00230   // 0x60 will put the keyboard in scancode mode 1, 2 or 3.
00231   // Writing 0xf0 followed by 0 queries the mode, resulting in
00232   // a scancode byte 43, 41 or 3f from the keyboard.
00233   //
00234   // Set 1 contains the values that the XT keyboard (with only
00235   // one set of scancodes) produced, with extensions for new
00236   // keys. Someone decided that another numbering was more
00237   // logical and invented scancode Set 2. However, it was
00238   // realized that new scancodes would break old programs, so
00239   // the keyboard output was fed to a 8042 microprocessor on
00240   // the motherboard that could translate Set 2 back into Set
00241   // 1. Indeed a smart construction. This is the default today.
00242   // Finally there is the PS/2 version, Set 3, more regular,
00243   // but used by almost nobody.
00244   //
00245   // Sets 2 and 3 are designed to be translated by the 8042.
00246   // Set 1 should not be translated.
00247   //
00248   // Make and Break Codes
00249   //
00250   // The key press / key release is coded as follows:
00251   //
00252   // For Set 1, if the make code of a key is c, the break
00253   // code will be c+0x80. If the make code is e0 c, the
00254   // break code will be e0 c+0x80. The Pause key has make
00255   // code e1 1d 45 e1 9d c5 and does not generate a break code.
00256   //
00257   // For Set 2, if the make code of a key is c, the break code
00258   // will be f0 c. If the make code is e0 c, the break code
00259   // will be e0 f0 c. The Pause key has the 8-byte make code
00260   // e1 14 77 e1 f0 14 f0 77.
00261   //
00262   // For Set 3, by default most keys do not generate a break
00263   // code - only CapsLock, LShift, RShift, LCtrl and LAlt do.
00264   // However, by default all non-traditional keys do generate
00265   // a break code - thus, LWin, RWin, Menu do, and for example
00266   // on the Microsoft Internet keyboard, so do Back, Forward,
00267   // Stop, Mail, Search, Favorites, Web/Home, MyComputer,
00268   // Calculator, Sleep. On my BTC keyboard, also the Macro key
00269   // does.
00270   //
00271   // In Scancode Mode 3 it is possible to enable or disable
00272   // key repeat and the production of break codes either on a
00273   // key-by-key basis or for all keys at once. And just like
00274   // for Set 2, key release is indicated by a f0 prefix in
00275   // those cases where it is indicated. There is nothing
00276   // special with the Pause key in scancode mode 3.
00277   if(key & BX_KEY_RELEASED)
00278     scancode = (unsigned char*) scancodes[(key & 0xFF)][state.current_scancodes_set].brek;
00279   else
00280     scancode = (unsigned char*) scancodes[(key & 0xFF)][state.current_scancodes_set].make;
00281 
00282   // Translation
00283   //
00284   // The 8042 microprocessor translates the incoming byte stream
00285   // produced by the keyboard, and turns an f0 prefix into an OR
00286   // with 80 for the next byte.
00287   //
00288   // Unless told not to translate, the keyboard controller translates
00289   // keyboard scancodes into the scancodes it returns to the CPU using
00290   // the following table (in hex):
00291   //
00292   // +----+-------------------------------------------------+
00293   // |    | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |
00294   // +----+-------------------------------------------------+
00295   // | 00 | ff 43 41 3f 3d 3b 3c 58 64 44 42 40 3e 0f 29 59 |
00296   // | 10 |     65 38 2a 70 1d 10 02 5a 66 71 2c 1f 1e 11 03 5b |
00297   // | 20 |     67 2e 2d 20 12 05 04 5c 68 39 2f 21 14 13 06 5d |
00298   // | 30 |     69 31 30 23 22 15 07 5e 6a 72 32 24 16 08 09 5f |
00299   // | 40 |     6b 33 25 17 18 0b 0a 60 6c 34 35 26 27 19 0c 61 |
00300   // | 50 |     6d 73 28 74 1a 0d 62 6e 3a 36 1c 1b 75 2b 63 76 |
00301   // | 60 |     55 56 77 78 79 7a 0e 7b 7c 4f 7d 4b 47 7e 7f 6f |
00302   // | 70 |     52 53 50 4c 4d 48 01 45 57 4e 51 4a 37 49 46 54 |
00303   // | 80 |     80 81 82 41 54 85 86 87 88 89 8a 8b 8c 8d 8e 8f |
00304   // | 90 |     90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f |
00305   // | a0 |     a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af |
00306   // | b0 |     b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf |
00307   // | c0 |     c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf |
00308   // | d0 |     d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df |
00309   // | e0 |     e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef |
00310   // | f0 |     -  f1 f2 f3     f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff |
00311   // +----+-------------------------------------------------+
00312   if(state.scancodes_translate)
00313   {
00314 
00315     // Translate before send
00316     u8  escaped = 0x00;
00317 
00318     for(i = 0; i < strlen((const char*) scancode); i++)
00319     {
00320       if(scancode[i] == 0xF0)
00321       {
00322         escaped = 0x80;
00323       }
00324       else
00325       {
00326 #if defined(DEBUG_KBD)
00327         printf("gen_scancode(): writing translated %02x   \n",
00328                translation8042[scancode[i]] | escaped);
00329 #endif
00330         enQ(translation8042[scancode[i]] | escaped);
00331         escaped = 0x00;
00332       }
00333     }
00334   }
00335   else
00336   {
00337 
00338     // Send raw data
00339     for(i = 0; i < strlen((const char*) scancode); i++)
00340     {
00341 #if defined(DEBUG_KBD)
00342       printf("gen_scancode(): writing raw %02x   \n", scancode[i]);
00343 #endif
00344       enQ(scancode[i]);
00345     }
00346   }
00347 }
00348 
00352 void CKeyboard::resetinternals(bool powerup)
00353 {
00354   state.kbd_internal_buffer.num_elements = 0;
00355   for(int i = 0; i < BX_KBD_ELEMENTS; i++)
00356     state.kbd_internal_buffer.buffer[i] = 0;
00357   state.kbd_internal_buffer.head = 0;
00358 
00359   state.kbd_internal_buffer.expecting_typematic = 0;
00360   state.kbd_internal_buffer.expecting_make_break = 0;
00361 
00362   // Default scancode set is mf2 (translation is controlled by the 8042)
00363   state.expecting_scancodes_set = 0;
00364 
00365   //state.current_scancodes_set = 1;
00366   state.current_scancodes_set = 2;
00367 
00368   //state.scancodes_translate = 1;
00369   if(powerup)
00370   {
00371     state.kbd_internal_buffer.expecting_led_write = 0;
00372     state.kbd_internal_buffer.delay = 1;  // 500 mS
00373     state.kbd_internal_buffer.repeat_rate = 0x0b; // 10.9 chars/sec
00374   }
00375 }
00376 
00380 void CKeyboard::enQ(u8 scancode)
00381 {
00382   int tail;
00383 
00384 #if defined(DEBUG_KBD)
00385   printf("enQ(0x%02x)", (unsigned) scancode);
00386 #endif
00387   if(state.kbd_internal_buffer.num_elements >= BX_KBD_ELEMENTS)
00388   {
00389     printf("internal keyboard buffer full, ignoring scancode.(%02x)  \n",
00390            (unsigned) scancode);
00391     return;
00392   }
00393 
00394   /* enqueue scancode in multibyte internal keyboard buffer */
00395 #if defined(DEBUG_KBD)
00396   BX_DEBUG(("enQ: putting scancode 0x%02x in internal buffer", (unsigned) scancode));
00397 #endif
00398   tail =
00399     (
00400       state.kbd_internal_buffer.head +
00401       state.kbd_internal_buffer.num_elements
00402     ) %
00403     BX_KBD_ELEMENTS;
00404   state.kbd_internal_buffer.buffer[tail] = scancode;
00405   state.kbd_internal_buffer.num_elements++;
00406 
00407   if(!state.status.outb && state.kbd_clock_enabled)
00408   {
00409     state.timer_pending = 1;
00410     return;
00411   }
00412 }
00413 
00417 u8 CKeyboard::read_60()
00418 {
00419   u8  val;
00420 
00421   /* output buffer */
00422   if(state.status.auxb)
00423   { /* mouse byte available */
00424     val = state.aux_output_buffer;
00425     state.aux_output_buffer = 0;
00426     state.status.outb = 0;
00427     state.status.auxb = 0;
00428     state.irq12_requested = 0;
00429 
00430     if(state.kbd_controller_Qsize)
00431     {
00432       unsigned  i;
00433       state.aux_output_buffer = state.kbd_controller_Q[0];
00434       state.status.outb = 1;
00435       state.status.auxb = 1;
00436       if(state.allow_irq12)
00437         state.irq12_requested = 1;
00438       for(i = 0; i < state.kbd_controller_Qsize - 1; i++)
00439       {
00440 
00441         // move Q elements towards head of queue by one
00442         state.kbd_controller_Q[i] = state.kbd_controller_Q[i + 1];
00443       }
00444 
00445       state.kbd_controller_Qsize--;
00446     }
00447 
00448     //DEV_pic_lower_irq(12);
00449     state.timer_pending = 1;
00450     execute();
00451 #if defined(DEBUG_KBD)
00452     BX_DEBUG(("[mouse] read from 0x60 returns 0x%02x", val));
00453 #endif
00454     return val;
00455   }
00456   else if(state.status.outb)
00457   { /* kbd byte available */
00458     val = state.kbd_output_buffer;
00459     state.status.outb = 0;
00460     state.status.auxb = 0;
00461     state.irq1_requested = 0;
00462     state.bat_in_progress = 0;
00463 
00464     if(state.kbd_controller_Qsize)
00465     {
00466       unsigned  i;
00467       state.aux_output_buffer = state.kbd_controller_Q[0];
00468       state.status.outb = 1;
00469       state.status.auxb = 1;
00470       if(state.allow_irq1)
00471         state.irq1_requested = 1;
00472       for(i = 0; i < state.kbd_controller_Qsize - 1; i++)
00473       {
00474 
00475         // move Q elements towards head of queue by one
00476         state.kbd_controller_Q[i] = state.kbd_controller_Q[i + 1];
00477       }
00478 
00479 #if defined(DEBUG_KBD)
00480       BX_DEBUG(("s.controller_Qsize: %02X", state.kbd_controller_Qsize));
00481 #endif
00482       state.kbd_controller_Qsize--;
00483     }
00484 
00485     //      DEV_pic_lower_irq(1);
00486     state.timer_pending = 1;
00487     execute();
00488 #if defined(DEBUG_KBD)
00489     BX_DEBUG(("READ(60) = %02x", (unsigned) val));
00490 #endif
00491     return val;
00492   }
00493   else
00494   {
00495 #if defined(DEBUG_KBD)
00496     BX_DEBUG(("num_elements = %d", state.kbd_internal_buffer.num_elements));
00497     BX_DEBUG(("read from port 60h with outb empty"));
00498     BX_DEBUG(("READ(60) = %02x", state.kbd_output_buffer));
00499 #endif
00500     return state.kbd_output_buffer;
00501   }
00502 }
00503 
00550 u8 CKeyboard::read_64()
00551 {
00552   u8  val;
00553 
00554   /* status register */
00555   val = (state.status.pare << 7) | (state.status.tim << 6) |
00556     (state.status.auxb << 5) | (state.status.keyl << 4) |
00557       (state.status.c_d << 3) | (state.status.sysf << 2) |
00558         (state.status.inpb << 1) | (state.status.outb << 0);
00559   state.status.tim = 0;
00560 #if defined(DEBUG_KBD)
00561   BX_DEBUG(("read from 0x64 returns 0x%02x", val));
00562 #endif
00563   return val;
00564 }
00565 
00569 void CKeyboard::write_60(u8 value)
00570 {
00571 #if defined(DEBUG_KBD)
00572   printf("kbd: port 60 write: %02x.   \n", value);
00573 #endif
00574 
00575   // data byte written last to 0x60
00576   state.status.c_d = 0;
00577 
00578   // if expecting data byte from command last sent to port 64h
00579   if(state.expecting_port60h)
00580   {
00581     state.expecting_port60h = 0;
00582 #if defined(DEBUG_KBD)
00583     if(state.status.inpb)
00584       printf("write to port 60h, not ready for write   \n");
00585 #endif
00586     switch(state.last_comm)
00587     {
00588     case 0x60:  // write command byte
00589       {
00590 
00591         //The keyboard controller is provided with some RAM, for example
00592         // 32 bytes, that can be accessed by the CPU. The most important
00593         // part of this RAM is byte 0, the Controller Command Byte (CCB).
00594         // It can be read/written by writing 0x20/0x60 to port 0x64 and
00595         // then reading/writing a data byte from/to port 0x60.
00596         //
00597         // This byte has the following layout.
00598         //
00599         // +---+-------+----+----+---+------+-----+-----+
00600         // | 0 | XLATE | ME | KE | 0 | SYSF | MIE | KIE |
00601         // +---+-------+----+----+---+------+-----+-----+
00602         //
00603         // Bit 6: Translate
00604         //    0: No translation.
00605         //    1: Translate keyboard scancodes, using the translation table
00606         //       given above. MCA type 2 controllers cannot set this bit
00607         //       to 1. In this case scan code conversion is set using
00608         //       keyboard command 0xf0 to port 0x60.
00609         //
00610         // Bit 5: Mouse enable
00611         //    0: Enable mouse.
00612         //    1: Disable mouse by driving the clock line low.
00613         //
00614         // Bit 4: Keyboard enable
00615         //    0: Enable keyboard.
00616         //    1: Disable keyboard by driving the clock line low.
00617         //
00618         // Bit 2: System flag
00619         //    This bit is shown in bit 2 of the status register. A
00620         //    "cold reboot" is one with this bit set to zero. A
00621         //    "warm reboot" is one with this bit set to one (BAT
00622         //    already completed). This will influence the tests and
00623         //    initializations done by the POST.
00624         //
00625         // Bit 1: Mouse interrupt enable
00626         //    0: Do not use mouse interrupts.
00627         //    1: Send interrupt request IRQ12 when the mouse output
00628         //       buffer is full.
00629         //
00630         // Bit 0: Keyboard interrupt enable
00631         //    0: Do not use keyboard interrupts.
00632         //    1: Send interrupt request IRQ1 when the keyboard output
00633         //       buffer is full.
00634         //
00635         //    When no interrupts are used, the CPU has to poll bits 0
00636         //    (and 5) of the status register.
00637         bool  scan_convert;
00638 
00639         //The keyboard controller is provided with some RAM, for example
00640         bool  disable_keyboard;
00641 
00642         //The keyboard controller is provided with some RAM, for example
00643         bool  disable_aux;
00644 
00645         scan_convert = (value >> 6) & 0x01;
00646         disable_aux = (value >> 5) & 0x01;
00647         disable_keyboard = (value >> 4) & 0x01;
00648         state.status.sysf = (value >> 2) & 0x01;
00649         state.allow_irq1 = (value >> 0) & 0x01;
00650         state.allow_irq12 = (value >> 1) & 0x01;
00651         set_kbd_clock_enable(!disable_keyboard);
00652         set_aux_clock_enable(!disable_aux);
00653         if(state.allow_irq12 && state.status.auxb)
00654           state.irq12_requested = 1;
00655         else if(state.allow_irq1 && state.status.outb)
00656           state.irq1_requested = 1;
00657 
00658 #if defined(DEBUG_KBD)
00659         BX_DEBUG((" allow_irq12 set to %u", (unsigned) state.allow_irq12));
00660         if(!scan_convert)
00661           BX_INFO(("keyboard: scan convert turned off"));
00662 #endif
00663 
00664         // (mch) NT needs this
00665         state.scancodes_translate = scan_convert;
00666       }
00667       break;
00668 
00669     case 0xd1:  // write output port
00670 #if defined(DEBUG_KBD)
00671       BX_DEBUG(("write output port with value %02xh", (unsigned) value));
00672 #endif
00673       break;
00674 
00675     case 0xd4:  // Write to mouse
00676       // I don't think this enables the AUX clock
00677       //set_aux_clock_enable(1); // enable aux clock line
00678       ctrl_to_mouse(value);
00679 
00680       // ??? should I reset to previous value of aux enable?
00681       break;
00682 
00683     case 0xd3:  // write mouse output buffer
00684       // Queue in mouse output buffer
00685       controller_enQ(value, 1);
00686       break;
00687 
00688     case 0xd2:
00689 
00690       // Queue in keyboard output buffer
00691       controller_enQ(value, 0);
00692       break;
00693 
00694     default:
00695       printf("=== unsupported write to port 60h(lastcomm=%02x): %02x   \n",
00696              (unsigned) state.last_comm, (unsigned) value);
00697     }
00698   }
00699   else
00700   {
00701 
00702     // data byte written last to 0x60
00703     state.status.c_d = 0;
00704     state.expecting_port60h = 0;
00705 
00706     /* pass byte to keyboard */
00707 
00708     /* ??? should conditionally pass to mouse device here ??? */
00709     if(state.kbd_clock_enabled == 0)
00710       set_kbd_clock_enable(1);
00711     ctrl_to_kbd(value);
00712   }
00713 
00714   execute();
00715 }
00716 
00720 void CKeyboard::write_64(u8 value)
00721 {
00722 #if defined(DEBUG_KBD)
00723   printf("kbd: port 64 write: %02x.   \n", value);
00724 #endif
00725 
00726   static int  kbd_initialized = 0;
00727   u8          command_byte;
00728 
00729   // command byte written last to 0x64
00730   state.status.c_d = 1;
00731   state.last_comm = value;
00732 
00733   // most commands NOT expecting port60 write next
00734   state.expecting_port60h = 0;
00735 
00736   switch(value)
00737   {
00738   case 0x20:  // get keyboard command byte
00739 #if defined(DEBUG_KBD)
00740     BX_DEBUG(("get keyboard command byte"));
00741 #endif
00742 
00743     // controller output buffer must be empty
00744     if(state.status.outb)
00745     {
00746 #if defined(DEBUG_KBD)
00747       BX_ERROR(("kbd: OUTB set and command 0x%02x encountered", value));
00748 #endif
00749       break;
00750     }
00751 
00752     command_byte = (state.scancodes_translate << 6) |
00753       ((!state.aux_clock_enabled) << 5) | ((!state.kbd_clock_enabled) << 4) |
00754         (0 << 3) | (state.status.sysf << 2) | (state.allow_irq12 << 1) |
00755           (state.allow_irq1 << 0);
00756     controller_enQ(command_byte, 0);
00757     break;
00758 
00759   case 0x60:  // write command byte
00760 #if defined(DEBUG_KBD)
00761     printf("kbd_ctrl: command 60: write command byte.   \n");
00762 #endif
00763 
00764     // following byte written to port 60h is command byte
00765     state.expecting_port60h = 1;
00766     break;
00767 
00768   case 0xa0:
00769 #if defined(DEBUG_KBD)
00770     printf("kbd_ctrl: command a0: BIOS name (not supported).   \n");
00771 #endif
00772     break;
00773 
00774   case 0xa1:
00775 #if defined(DEBUG_KBD)
00776     printf("kbd_ctrl: command a0: BIOS version (not supported).   \n");
00777 #endif
00778     break;
00779 
00780   case 0xa7:  // disable the aux device
00781     set_aux_clock_enable(0);
00782 #if defined(DEBUG_KBD)
00783     printf("kbd_ctrl: command a7: aux i/f disable.   \n");
00784 #endif
00785     break;
00786 
00787   case 0xa8:  // enable the aux device
00788     set_aux_clock_enable(1);
00789 #if defined(DEBUG_KBD)
00790     printf("kbd_ctrl: command a7: aux i/f enable.   \n");
00791 #endif
00792     break;
00793 
00794   case 0xa9:  // Test Mouse Port
00795     // controller output buffer must be empty
00796 #if defined(DEBUG_KBD)
00797     printf("kbd_ctrl: command a9: aux i/f test.   \n");
00798 #endif
00799     if(state.status.outb)
00800     {
00801       printf("kbd: OUTB set and command 0x%02x encountered", value);
00802       break;
00803     }
00804 
00805     controller_enQ(0x00, 0);  // no errors detected
00806     break;
00807 
00808   case 0xaa:  // motherboard controller self test
00809 #if defined(DEBUG_KBD)
00810     printf("kbd_ctrl: command aa: self test.   \n");
00811 #endif
00812     if(kbd_initialized == 0)
00813     {
00814       state.kbd_controller_Qsize = 0;
00815       state.status.outb = 0;
00816       kbd_initialized = 1;
00817     }
00818 
00819     // controller output buffer must be empty
00820     if(state.status.outb)
00821     {
00822       printf("kbd: OUTB set and command 0x%02x encountered", value);
00823 
00824       //break;
00825       // drain the queue?
00826       state.kbd_internal_buffer.head = 0;
00827       state.kbd_internal_buffer.num_elements = 0;
00828       state.status.outb = 0;
00829     }
00830 
00831     state.status.sysf = 1;    // self test complete
00832     controller_enQ(0x55, 0);  // controller OK
00833     break;
00834 
00835   case 0xab:  // Interface Test
00836 #if defined(DEBUG_KBD)
00837     printf("kbd_ctrl: command ab: kbd i/f test.   \n");
00838 #endif
00839 
00840     // controller output buffer must be empty
00841     if(state.status.outb)
00842     {
00843       printf("kbd: OUTB set and command 0x%02x encountered", value);
00844       break;
00845     }
00846 
00847     controller_enQ(0x00, 0);
00848     break;
00849 
00850   case 0xad:  // disable keyboard
00851     set_kbd_clock_enable(0);
00852 #if defined(DEBUG_KBD)
00853     printf("kbd_ctrl: command ad: kbd i/f disable.   \n");
00854 #endif
00855     break;
00856 
00857   case 0xae:  // enable keyboard
00858     set_kbd_clock_enable(1);
00859 #if defined(DEBUG_KBD)
00860     printf("kbd_ctrl: command ae: kbd i/f enable.   \n");
00861 #endif
00862     break;
00863 
00864   case 0xaf:  // get controller version
00865 #if defined(DEBUG_KBD)
00866     printf("kbd_ctrl: command af: controller version (not supported).   \n");
00867 #endif
00868     break;
00869 
00870   case 0xc0:  // read input port
00871 #if defined(DEBUG_KBD)
00872     printf("kbd_ctrl: command c0: read input port.   \n");
00873 #endif
00874 
00875     // controller output buffer must be empty
00876     if(state.status.outb)
00877     {
00878       BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value));
00879       break;
00880     }
00881 
00882     // keyboard not inhibited
00883     controller_enQ(0x80, 0);
00884     break;
00885 
00886   case 0xd0:  // read output port: next byte read from port 60h
00887 #if defined(DEBUG_KBD)
00888     printf("kbd_ctrl: command d0: read output port. (partial)   \n");
00889 #endif
00890 
00891     // controller output buffer must be empty
00892     if(state.status.outb)
00893     {
00894       BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value));
00895       break;
00896     }
00897 
00898     controller_enQ((state.irq12_requested << 5) | (state.irq1_requested << 4) |
00899                    //              (BX_GET_ENABLE_A20() << 1) |
00900                    0x01, 0);
00901     break;
00902 
00903   case 0xd1:  // write output port: next byte written to port 60h
00904 #if defined(DEBUG_KBD)
00905     printf("kbd_ctrl: command d1: write output port.   \n");
00906 #endif
00907 
00908     // following byte to port 60h written to output port
00909     state.expecting_port60h = 1;
00910     break;
00911 
00912   case 0xd3:  // write mouse output buffer
00913 #if defined(DEBUG_KBD)
00914     printf("kbd_ctrl: command d3: write aux output buffer.   \n");
00915 #endif
00916 
00917     // following byte to port 60h written to output port as mouse write.
00918     state.expecting_port60h = 1;
00919     break;
00920 
00921   case 0xd4:  // write to mouse
00922 #if defined(DEBUG_KBD)
00923     printf("kbd_ctrl: command d4: write to aux.   \n");
00924 #endif
00925 
00926     // following byte written to port 60h
00927     state.expecting_port60h = 1;
00928     break;
00929 
00930   case 0xd2:  // write keyboard output buffer
00931 #if defined(DEBUG_KBD)
00932     printf("kbd_ctrl: command d2: write kbd output buffer.   \n");
00933 #endif
00934     state.expecting_port60h = 1;
00935     break;
00936 
00937   case 0xc1:  // Continuous Input Port Poll, Low
00938   case 0xc2:  // Continuous Input Port Poll, High
00939   case 0xe0:  // Read Test Inputs
00940     BX_PANIC(("io write 0x64: command = %02xh", (unsigned) value));
00941     break;
00942 
00943   default:
00944     if(value == 0xff || (value >= 0xf0 && value <= 0xfd))
00945     {
00946 
00947       /* useless pulse output bit commands ??? */
00948 #if defined(DEBUG_KBD)
00949       BX_DEBUG(("io write to port 64h, useless command %02x", (unsigned) value));
00950 #endif
00951       return;
00952     }
00953 
00954     BX_ERROR(("unsupported io write to keyboard port 64, value = %x",
00955                (unsigned) value));
00956     break;
00957   }
00958 
00959   execute();
00960 }
00961 
00965 void CKeyboard::controller_enQ(u8 data, unsigned source)
00966 {
00967 
00968   // source is 0 for keyboard, 1 for mouse
00969 #if defined(DEBUG_KBD)
00970   BX_DEBUG(("controller_enQ(%02x) source=%02x", (unsigned) data, source));
00971 #endif
00972 
00973   // see if we need to Q this byte from the controller
00974   // remember this includes mouse bytes.
00975   if(state.status.outb)
00976   {
00977     if(state.kbd_controller_Qsize >= BX_KBD_CONTROLLER_QSIZE)
00978       FAILURE(Runtime, "controller_enq(): controller_Q full!");
00979     state.kbd_controller_Q[state.kbd_controller_Qsize++] = data;
00980     state.kbd_controller_Qsource = source;
00981     return;
00982   }
00983 
00984   // the Q is empty
00985   if(source == 0)
00986   { // keyboard
00987     state.kbd_output_buffer = data;
00988     state.status.outb = 1;
00989     state.status.auxb = 0;
00990     state.status.inpb = 0;
00991     if(state.allow_irq1)
00992       state.irq1_requested = 1;
00993   }
00994   else
00995   { // mouse
00996     state.aux_output_buffer = data;
00997     state.status.outb = 1;
00998     state.status.auxb = 1;
00999     state.status.inpb = 0;
01000     if(state.allow_irq12)
01001       state.irq12_requested = 1;
01002   }
01003 }
01004 
01008 void CKeyboard::set_kbd_clock_enable(u8 value)
01009 {
01010   bool  prev_kbd_clock_enabled;
01011 
01012   if(value == 0)
01013   {
01014     state.kbd_clock_enabled = 0;
01015   }
01016   else
01017   {
01018 
01019     /* is another byte waiting to be sent from the keyboard ? */
01020     prev_kbd_clock_enabled = state.kbd_clock_enabled;
01021     state.kbd_clock_enabled = 1;
01022 
01023     if(prev_kbd_clock_enabled == 0 && state.status.outb == 0)
01024       state.timer_pending = 1;
01025   }
01026 }
01027 
01031 void CKeyboard::set_aux_clock_enable(u8 value)
01032 {
01033   bool  prev_aux_clock_enabled;
01034 
01035 #if defined(DEBUG_KBD)
01036   BX_DEBUG(("set_aux_clock_enable(%u)", (unsigned) value));
01037 #endif
01038   if(value == 0)
01039   {
01040     state.aux_clock_enabled = 0;
01041   }
01042   else
01043   {
01044 
01045     /* is another byte waiting to be sent from the keyboard ? */
01046     prev_aux_clock_enabled = state.aux_clock_enabled;
01047     state.aux_clock_enabled = 1;
01048     if(prev_aux_clock_enabled == 0 && state.status.outb == 0)
01049       state.timer_pending = 1;
01050   }
01051 }
01052 
01056 void CKeyboard::ctrl_to_kbd(u8 value)
01057 {
01058 #if defined(DEBUG_KBD)
01059   BX_DEBUG(("controller passed byte %02xh to keyboard", value));
01060 #endif
01061   if(state.kbd_internal_buffer.expecting_make_break)
01062   {
01063     state.kbd_internal_buffer.expecting_make_break = 0;
01064 #if defined(DEBUG_KBD)
01065     printf("setting key %x to make/break mode (unused)   \n", value);
01066 #endif
01067     enQ(0xFA);      // send ACK
01068     return;
01069   }
01070 
01071   if(state.kbd_internal_buffer.expecting_typematic)
01072   {
01073     state.kbd_internal_buffer.expecting_typematic = 0;
01074     state.kbd_internal_buffer.delay = (value >> 5) & 0x03;
01075 #if defined(DEBUG_KBD)
01076     switch(state.kbd_internal_buffer.delay)
01077     {
01078     case 0: BX_INFO(("setting delay to 250 mS (unused)")); break;
01079     case 1: BX_INFO(("setting delay to 500 mS (unused)")); break;
01080     case 2: BX_INFO(("setting delay to 750 mS (unused)")); break;
01081     case 3: BX_INFO(("setting delay to 1000 mS (unused)")); break;
01082     }
01083 #endif
01084     state.kbd_internal_buffer.repeat_rate = value & 0x1f;
01085 #if defined(DEBUG_KBD)
01086     double  cps = 1 /
01087       ((double) (8 + (value & 0x07)) * (double) exp(log((double) 2) * (double) ((value >> 3) & 0x03)) * 0.00417);
01088     BX_INFO(("setting repeat rate to %.1f cps (unused)", cps));
01089 #endif
01090     enQ(0xFA);      // send ACK
01091     return;
01092   }
01093 
01094   if(state.kbd_internal_buffer.expecting_led_write)
01095   {
01096     state.kbd_internal_buffer.expecting_led_write = 0;
01097     state.kbd_internal_buffer.led_status = value;
01098 #if defined(DEBUG_KBD)
01099     BX_DEBUG(("LED status set to %02x",
01100                (unsigned) state.kbd_internal_buffer.led_status));
01101 #endif
01102     enQ(0xFA);      // send ACK %%%
01103     return;
01104   }
01105 
01106   if(state.expecting_scancodes_set)
01107   {
01108     state.expecting_scancodes_set = 0;
01109     if(value != 0)
01110     {
01111       if(value < 4)
01112       {
01113         state.current_scancodes_set = (value - 1);
01114 #if defined(DEBUG_KBD)
01115         BX_INFO(("Switched to scancode set %d",
01116                   (unsigned) state.current_scancodes_set + 1));
01117 #endif
01118         enQ(0xFA);
01119       }
01120       else
01121       {
01122         BX_ERROR(("Received scancodes set out of range: %d", value));
01123         enQ(0xFF);  // send ERROR
01124       }
01125     }
01126     else
01127     {
01128 
01129       // Send ACK (SF patch #1159626)
01130       enQ(0xFA);
01131 
01132       // Send current scancodes set to port 0x60
01133       if(state.scancodes_translate)
01134         enQ(translation8042[1 + state.current_scancodes_set]);
01135       else
01136         enQ(1 + state.current_scancodes_set);
01137     }
01138 
01139     return;
01140   }
01141 
01142   switch(value)
01143   {
01144 
01145   //    case 0x00: // ??? ignore and let OS timeout with no response
01146   //#if defined(DEBUG_KBD)
01147   //      printf("kbd: command 00: ignored.   \n");
01148   //#endif
01149   //      enQ(0xFA); // send ACK %%%
01150   //      break;
01151   //
01152   //    case 0x05: // ???
01153   //#if defined(DEBUG_KBD)
01154   //      printf("kbd: command 05:  unknown.   \n");
01155   //#endif
01156   //      // (mch) trying to get this to work...
01157   //      state.status.sysf = 1;
01158   //      enQ_imm(0xfe);
01159   //      break;
01160   case 0xed:        // LED Write
01161     state.kbd_internal_buffer.expecting_led_write = 1;
01162 #if defined(DEBUG_KBD)
01163     printf("kbd: Expecting led write info.   \n");
01164 #endif
01165     enQ_imm(0xFA);  // send ACK %%%
01166     break;
01167 
01168   case 0xee:        // echo
01169 #if defined(DEBUG_KBD)
01170     printf("kbd: command ee: echo.   \n");
01171 #endif
01172     enQ(0xEE);      // return same byte (EEh) as echo diagnostic
01173     break;
01174 
01175   case 0xf0:        // Select alternate scan code set
01176     state.expecting_scancodes_set = 1;
01177 #if defined(DEBUG_KBD)
01178     printf("kbd: Expecting scancode set info.   \n");
01179 #endif
01180     enQ(0xFA);      // send ACK
01181     break;
01182 
01183   case 0xf2:        // identify keyboard
01184 #if defined(DEBUG_KBD)
01185     printf("kbd: command f2: identify keyboard.   \n");
01186 #endif
01187 
01188     //  Keyboard IDs
01189     //
01190     // Keyboards do report an ID as a reply to the command f2. An MF2 AT keyboard
01191     // reports ID ab 83. Translation turns this into ab 41.
01192     enQ(0xFA);
01193     enQ(0xAB);
01194 
01195     if(state.scancodes_translate)
01196       enQ(0x41);
01197     else
01198       enQ(0x83);
01199     break;
01200 
01201   case 0xf3:        // typematic info
01202     state.kbd_internal_buffer.expecting_typematic = 1;
01203 #if defined(DEBUG_KBD)
01204     printf("kbd: Expecting typematic info.   \n");
01205 #endif
01206     enQ(0xFA);      // send ACK
01207     break;
01208 
01209   case 0xf4:        // enable keyboard
01210     state.kbd_internal_buffer.scanning_enabled = 1;
01211 #if defined(DEBUG_KBD)
01212     printf("kbd: command f4: enable keyboard.   \n");
01213 #endif
01214     enQ(0xFA);      // send ACK
01215     break;
01216 
01217   case 0xf5:        // reset keyboard to power-up settings and disable scanning
01218     resetinternals(1);
01219     enQ(0xFA);      // send ACK
01220     state.kbd_internal_buffer.scanning_enabled = 0;
01221 #if defined(DEBUG_KBD)
01222     printf("kbd: command f5: reset and disable keyboard.   \n");
01223 #endif
01224     break;
01225 
01226   case 0xf6:        // reset keyboard to power-up settings and enable scanning
01227     resetinternals(1);
01228     enQ(0xFA);      // send ACK
01229     state.kbd_internal_buffer.scanning_enabled = 1;
01230 #if defined(DEBUG_KBD)
01231     printf("kbd: command f6: reset and enable keyboard.   \n");
01232 #endif
01233     break;
01234 
01235   case 0xfc:        // PS/2 Set Key Type to Make/Break
01236     state.kbd_internal_buffer.expecting_make_break = 1;
01237 #if defined(DEBUG_KBD)
01238     printf("kbd: Expecting make/break info.   \n");
01239 #endif
01240     enQ(0xFA);      /* send ACK */
01241     break;
01242 
01243   case 0xfe:        // resend. aiiee.
01244     printf("kbd: resend command received.   \n");
01245     break;
01246 
01247   case 0xff:        // reset: internal keyboard reset and afterwards the BAT
01248 #if defined(DEBUG_KBD)
01249     printf("kbd: command ff: reset keyboard w/BAT.   \n");
01250 #endif
01251     resetinternals(1);
01252     enQ(0xFA);      // send ACK
01253     state.bat_in_progress = 1;
01254     enQ(0xAA);      // BAT test passed
01255     break;
01256 
01257   //case 0xd3:
01258   //  enQ(0xfa);
01259   //  break;
01260   case 0xf7:        // PS/2 Set All Keys To Typematic
01261   case 0xf8:        // PS/2 Set All Keys to Make/Break
01262   case 0xf9:        // PS/2 PS/2 Set All Keys to Make
01263   case 0xfa:        // PS/2 Set All Keys to Typematic Make/Break
01264   case 0xfb:        // PS/2 Set Key Type to Typematic
01265   case 0xfd:        // PS/2 Set Key Type to Make
01266     printf("kbd: unhandled command: %02x, ACKing     \n", value);
01267     enQ(0xFA);
01268     break;
01269 
01270   default:
01271     printf("kbd: command %02x: not recognized!   \n", value);
01272     enQ(0xFE);      /* send NACK */
01273     break;
01274   }
01275 }
01276 
01280 void CKeyboard::enQ_imm(u8 val)
01281 {
01282   int tail;
01283 
01284   if(state.kbd_internal_buffer.num_elements >= BX_KBD_ELEMENTS)
01285   {
01286     BX_PANIC(("internal keyboard buffer full (imm)"));
01287     return;
01288   }
01289 
01290   tail =
01291     (
01292       state.kbd_internal_buffer.head +
01293       state.kbd_internal_buffer.num_elements
01294     ) %
01295     BX_KBD_ELEMENTS;
01296 
01297   state.kbd_output_buffer = val;
01298   state.status.outb = 1;
01299 
01300   if(state.allow_irq1)
01301     state.irq1_requested = 1;
01302 }
01303 
01307 void CKeyboard::ctrl_to_mouse(u8 value)
01308 {
01309 #if defined(DEBUG_KBD)
01310   BX_DEBUG(("MOUSE: ctrl_to_mouse(%02xh)", (unsigned) value));
01311   BX_DEBUG(("  enable = %u", (unsigned) state.mouse.enable));
01312   BX_DEBUG(("  allow_irq12 = %u", (unsigned) state.allow_irq12));
01313   BX_DEBUG(("  aux_clock_enabled = %u", (unsigned) state.aux_clock_enabled));
01314 #endif
01315 
01316   // an ACK (0xFA) is always the first response to any valid input
01317   // received from the system other than Set-Wrap-Mode & Resend-Command
01318   if(state.expecting_mouse_parameter)
01319   {
01320     state.expecting_mouse_parameter = 0;
01321     switch(state.last_mouse_command)
01322     {
01323     case 0xf3:  // Set Mouse Sample Rate
01324       state.mouse.sample_rate = value;
01325 #if defined(DEBUG_KBD)
01326       BX_DEBUG(("[mouse] Sampling rate set: %d Hz", value));
01327 #endif
01328       if((value == 200) && (!state.mouse.im_request))
01329       {
01330         state.mouse.im_request = 1;
01331       }
01332       else if((value == 100) && (state.mouse.im_request == 1))
01333       {
01334         state.mouse.im_request = 2;
01335       }
01336       else if((value == 80) && (state.mouse.im_request == 2))
01337       {
01338 #if defined(DEBUG_KBD)
01339         BX_INFO(("wheel mouse mode enabled"));
01340 #endif
01341         state.mouse.im_mode = 1;
01342         state.mouse.im_request = 0;
01343       }
01344       else
01345       {
01346         state.mouse.im_request = 0;
01347       }
01348 
01349       controller_enQ(0xFA, 1);  // ack
01350       break;
01351 
01352     case 0xe8:  // Set Mouse Resolution
01353       switch(value)
01354       {
01355       case 0:   state.mouse.resolution_cpmm = 1; break;
01356       case 1:   state.mouse.resolution_cpmm = 2; break;
01357       case 2:   state.mouse.resolution_cpmm = 4; break;
01358       case 3:   state.mouse.resolution_cpmm = 8; break;
01359       default:  BX_PANIC(("[mouse] Unknown resolution %d", value)); break;
01360       }
01361 
01362 #if defined(DEBUG_KBD)
01363       BX_DEBUG(("[mouse] Resolution set to %d counts per mm", state.mouse.
01364                  resolution_cpmm));
01365 #endif
01366       controller_enQ(0xFA, 1);  // ack
01367       break;
01368 
01369     default:
01370       BX_PANIC(("MOUSE: unknown last command (%02xh)",
01371                  (unsigned) state.last_mouse_command));
01372     }
01373   }
01374   else
01375   {
01376     state.expecting_mouse_parameter = 0;
01377     state.last_mouse_command = value;
01378 
01379     // test for wrap mode first
01380     if(state.mouse.mode == MOUSE_MODE_WRAP)
01381     {
01382 
01383       // if not a reset command or reset wrap mode
01384       // then just echo the byte.
01385       if((value != 0xff) && (value != 0xec))
01386       {
01387 
01388         //        if (bx_dbg.mouse)
01389 #if defined(DEBUG_KBD)
01390         BX_INFO(("[mouse] wrap mode: Ignoring command %0X02.", value));
01391 #endif
01392         controller_enQ(value, 1);
01393 
01394         // bail out
01395         return;
01396       }
01397     }
01398 
01399     switch(value)
01400     {
01401     case 0xe6:  // Set Mouse Scaling to 1:1
01402       controller_enQ(0xFA, 1);  // ACK
01403       state.mouse.scaling = 2;
01404 #if defined(DEBUG_KBD)
01405       BX_DEBUG(("[mouse] Scaling set to 1:1"));
01406 #endif
01407       break;
01408 
01409     case 0xe7:  // Set Mouse Scaling to 2:1
01410       controller_enQ(0xFA, 1);  // ACK
01411       state.mouse.scaling = 2;
01412 #if defined(DEBUG_KBD)
01413       BX_DEBUG(("[mouse] Scaling set to 2:1"));
01414 #endif
01415       break;
01416 
01417     case 0xe8:  // Set Mouse Resolution
01418       controller_enQ(0xFA, 1);  // ACK
01419       state.expecting_mouse_parameter = 1;
01420       break;
01421 
01422     case 0xea:  // Set Stream Mode
01423       //        if (bx_dbg.mouse)
01424 #if defined(DEBUG_KBD)
01425       BX_INFO(("[mouse] Mouse stream mode on."));
01426 #endif
01427       state.mouse.mode = MOUSE_MODE_STREAM;
01428       controller_enQ(0xFA, 1);  // ACK
01429       break;
01430 
01431     case 0xec:  // Reset Wrap Mode
01432       // unless we are in wrap mode ignore the command
01433       if(state.mouse.mode == MOUSE_MODE_WRAP)
01434       {
01435 
01436         //          if (bx_dbg.mouse)
01437 #if defined(DEBUG_KBD)
01438         BX_INFO(("[mouse] Mouse wrap mode off."));
01439 #endif
01440 
01441         // restore previous mode except disable stream mode reporting.
01442         // ### TODO disabling reporting in stream mode
01443         state.mouse.mode = state.mouse.saved_mode;
01444         controller_enQ(0xFA, 1);  // ACK
01445       }
01446       break;
01447 
01448     case 0xee:  // Set Wrap Mode
01449       // ### TODO flush output queue.
01450       // ### TODO disable interrupts if in stream mode.
01451       //        if (bx_dbg.mouse)
01452 #if defined(DEBUG_KBD)
01453       BX_INFO(("[mouse] Mouse wrap mode on."));
01454 #endif
01455       state.mouse.saved_mode = state.mouse.mode;
01456       state.mouse.mode = MOUSE_MODE_WRAP;
01457       controller_enQ(0xFA, 1);  // ACK
01458       break;
01459 
01460     case 0xf0:  // Set Remote Mode (polling mode, i.e. not stream mode.)
01461       //        if (bx_dbg.mouse)
01462 #if defined(DEBUG_KBD)
01463       BX_INFO(("[mouse] Mouse remote mode on."));
01464 #endif
01465 
01466       // ### TODO should we flush/discard/ignore any already queued packets?
01467       state.mouse.mode = MOUSE_MODE_REMOTE;
01468       controller_enQ(0xFA, 1);  // ACK
01469       break;
01470 
01471     case 0xf2:  // Read Device Type
01472       controller_enQ(0xFA, 1);    // ACK
01473       if(state.mouse.im_mode)
01474         controller_enQ(0x03, 1);  // Device ID (wheel z-mouse)
01475       else
01476         controller_enQ(0x00, 1);  // Device ID (standard)
01477 #if defined(DEBUG_KBD)
01478       BX_DEBUG(("[mouse] Read mouse ID"));
01479 #endif
01480       break;
01481 
01482     case 0xf3:  // Set Mouse Sample Rate (sample rate written to port 60h)
01483       controller_enQ(0xFA, 1);  // ACK
01484       state.expecting_mouse_parameter = 1;
01485       break;
01486 
01487     case 0xf4:  // Enable (in stream mode)
01488       state.mouse.enable = 1;
01489       controller_enQ(0xFA, 1);  // ACK
01490 #if defined(DEBUG_KBD)
01491       BX_DEBUG(("[mouse] Mouse enabled (stream mode)"));
01492 #endif
01493       break;
01494 
01495     case 0xf5:  // Disable (in stream mode)
01496       state.mouse.enable = 0;
01497       controller_enQ(0xFA, 1);  // ACK
01498 #if defined(DEBUG_KBD)
01499       BX_DEBUG(("[mouse] Mouse disabled (stream mode)"));
01500 #endif
01501       break;
01502 
01503     case 0xf6:  // Set Defaults
01504       state.mouse.sample_rate = 100;    /* reports per second (default) */
01505       state.mouse.resolution_cpmm = 4;  /* 4 counts per millimeter (default) */
01506       state.mouse.scaling = 1;          /* 1:1 (default) */
01507       state.mouse.enable = 0;
01508       state.mouse.mode = MOUSE_MODE_STREAM;
01509       controller_enQ(0xFA, 1);          // ACK
01510 #if defined(DEBUG_KBD)
01511       BX_DEBUG(("[mouse] Set Defaults"));
01512 #endif
01513       break;
01514 
01515     case 0xff:  // Reset
01516       state.mouse.sample_rate = 100;    /* reports per second (default) */
01517       state.mouse.resolution_cpmm = 4;  /* 4 counts per millimeter (default) */
01518       state.mouse.scaling = 1;          /* 1:1 (default) */
01519       state.mouse.mode = MOUSE_MODE_RESET;
01520       state.mouse.enable = 0;
01521 #if defined(DEBUG_KBD)
01522       if(state.mouse.im_mode)
01523         BX_INFO(("wheel mouse mode disabled"));
01524 #endif
01525       state.mouse.im_mode = 0;
01526       controller_enQ(0xFA, 1);          // ACK
01527       controller_enQ(0xAA, 1);          // completion code
01528       controller_enQ(0x00, 1);          // ID code (standard after reset)
01529 #if defined(DEBUG_KBD)
01530       BX_DEBUG(("[mouse] Mouse reset"));
01531 #endif
01532       break;
01533 
01534     case 0xe9:  // Get mouse information
01535       // should we ack here? (mch): Yes
01536       controller_enQ(0xFA, 1);  // ACK
01537       controller_enQ(state.mouse.get_status_byte(), 1);     // status
01538       controller_enQ(state.mouse.get_resolution_byte(), 1); // resolution
01539       controller_enQ(state.mouse.sample_rate, 1);           // sample rate
01540 #if defined(DEBUG_KBD)
01541       BX_DEBUG(("[mouse] Get mouse information"));
01542 #endif
01543       break;
01544 
01545     case 0xeb:  // Read Data (send a packet when in Remote Mode)
01546       controller_enQ(0xFA, 1);  // ACK
01547 
01548       // perhaps we should be adding some movement here.
01549       mouse_enQ_packet(((state.mouse.button_status & 0x0f) | 0x08), 0x00, 0x00,
01550                        0x00);   // bit3 of first byte always set
01551 
01552       //assumed we really aren't in polling mode, a rather odd assumption.
01553 #if defined(DEBUG_KBD)
01554       BX_ERROR(("[mouse] Warning: Read Data command partially supported."));
01555 #endif
01556       break;
01557 
01558     case 0xbb:  // OS/2 Warp 3 uses this command
01559 #if defined(DEBUG_KBD)
01560       BX_ERROR(("[mouse] ignoring 0xbb command"));
01561 #endif
01562       break;
01563 
01564     default:
01565       BX_ERROR(("[mouse] ctrl_to_mouse(): got value of 0x%02x", value));
01566       controller_enQ(0xFE, 1);  /* send NACK */
01567     }
01568   }
01569 }
01570 
01574 bool CKeyboard::mouse_enQ_packet(u8 b1, u8 b2, u8 b3, u8 b4)
01575 {
01576   int bytes = 3;
01577   if(state.mouse.im_mode)
01578     bytes = 4;
01579 
01580   if((state.mouse_internal_buffer.num_elements + bytes) >= BX_MOUSE_BUFF_SIZE)
01581   {
01582     return(0);  /* buffer doesn't have the space */
01583   }
01584 
01585   mouse_enQ(b1);
01586   mouse_enQ(b2);
01587   mouse_enQ(b3);
01588   if(state.mouse.im_mode)
01589     mouse_enQ(b4);
01590 
01591   return(1);
01592 }
01593 
01597 void CKeyboard::mouse_enQ(u8 mouse_data)
01598 {
01599   int tail;
01600 
01601 #if defined(DEBUG_KBD)
01602   BX_DEBUG(("mouse_enQ(%02x)", (unsigned) mouse_data));
01603 #endif
01604   if(state.mouse_internal_buffer.num_elements >= BX_MOUSE_BUFF_SIZE)
01605   {
01606     BX_ERROR(("[mouse] internal mouse buffer full, ignoring mouse data.(%02x)",
01607                (unsigned) mouse_data));
01608     return;
01609   }
01610 
01611   /* enqueue mouse data in multibyte internal mouse buffer */
01612   tail =
01613     (
01614       state.mouse_internal_buffer.head +
01615       state.mouse_internal_buffer.num_elements
01616     ) %
01617     BX_MOUSE_BUFF_SIZE;
01618   state.mouse_internal_buffer.buffer[tail] = mouse_data;
01619   state.mouse_internal_buffer.num_elements++;
01620 
01621   if(!state.status.outb && state.aux_clock_enabled)
01622   {
01623     state.timer_pending = 1;
01624     return;
01625   }
01626 }
01627 
01631 unsigned CKeyboard::periodic()
01632 {
01633   u8  retval;
01634 
01635   retval = (state.irq1_requested << 0) | (state.irq12_requested << 1);
01636   state.irq1_requested = 0;
01637   state.irq12_requested = 0;
01638 
01639   if(state.timer_pending == 0)
01640   {
01641     return(retval);
01642   }
01643 
01644   if(1 >= state.timer_pending)
01645   {
01646     state.timer_pending = 0;
01647   }
01648   else
01649   {
01650     state.timer_pending--;
01651     return(retval);
01652   }
01653 
01654   if(state.status.outb)
01655   {
01656     return(retval);
01657   }
01658 
01659   /* nothing in outb, look for possible data xfer from keyboard or mouse */
01660   if(state.kbd_internal_buffer.num_elements
01661    && (state.kbd_clock_enabled || state.bat_in_progress))
01662   {
01663 #if defined(DEBUG_KBD)
01664     BX_DEBUG(("service_keyboard: key in internal buffer waiting"));
01665 #endif
01666     state.kbd_output_buffer = state.kbd_internal_buffer.buffer[state.kbd_internal_buffer.head];
01667     state.status.outb = 1;
01668 
01669     // commented out since this would override the current state of the
01670     // mouse buffer flag - no bug seen - just seems wrong (das)
01671     //    state.auxb = 0;
01672     state.kbd_internal_buffer.head = (state.kbd_internal_buffer.head + 1) % BX_KBD_ELEMENTS;
01673     state.kbd_internal_buffer.num_elements--;
01674     if(state.allow_irq1)
01675       state.irq1_requested = 1;
01676   }
01677   else
01678   {
01679     create_mouse_packet(0);
01680     if(state.aux_clock_enabled && state.mouse_internal_buffer.num_elements)
01681     {
01682 #if defined(DEBUG_KBD)
01683       BX_DEBUG(("service_keyboard: key(from mouse) in internal buffer waiting"));
01684 #endif
01685       state.aux_output_buffer = state.mouse_internal_buffer.buffer[state.mouse_internal_buffer.head];
01686 
01687       state.status.outb = 1;
01688       state.status.auxb = 1;
01689       state.mouse_internal_buffer.head =
01690           (
01691             state.mouse_internal_buffer.head +
01692             1
01693           ) %
01694           BX_MOUSE_BUFF_SIZE;
01695       state.mouse_internal_buffer.num_elements--;
01696       if(state.allow_irq12)
01697         state.irq12_requested = 1;
01698     }
01699 
01700 #if defined(DEBUG_KBD)
01701     else
01702     {
01703       BX_DEBUG(("service_keyboard(): no keys waiting"));
01704     }
01705 #endif
01706   }
01707 
01708   return(retval);
01709 }
01710 
01714 void CKeyboard::create_mouse_packet(bool force_enq)
01715 {
01716   u8  b1;
01717 
01718   u8  b2;
01719 
01720   u8  b3;
01721 
01722   u8  b4;
01723 
01724   if(state.mouse_internal_buffer.num_elements && !force_enq)
01725     return;
01726 
01727   s16 delta_x = state.mouse.delayed_dx;
01728   s16 delta_y = state.mouse.delayed_dy;
01729   u8  button_state = state.mouse.button_status | 0x08;
01730 
01731   if(!force_enq && !delta_x && !delta_y)
01732   {
01733     return;
01734   }
01735 
01736   if(delta_x > 254)
01737     delta_x = 254;
01738   if(delta_x < -254)
01739     delta_x = -254;
01740   if(delta_y > 254)
01741     delta_y = 254;
01742   if(delta_y < -254)
01743     delta_y = -254;
01744 
01745   b1 = (button_state & 0x0f) | 0x08;  // bit3 always set
01746   if((delta_x >= 0) && (delta_x <= 255))
01747   {
01748     b2 = (u8) delta_x;
01749     state.mouse.delayed_dx -= delta_x;
01750   }
01751   else if(delta_x > 255)
01752   {
01753     b2 = (u8) 0xff;
01754     state.mouse.delayed_dx -= 255;
01755   }
01756   else if(delta_x >= -256)
01757   {
01758     b2 = (u8) delta_x;
01759     b1 |= 0x10;
01760     state.mouse.delayed_dx -= delta_x;
01761   }
01762   else
01763   {
01764     b2 = (u8) 0x00;
01765     b1 |= 0x10;
01766     state.mouse.delayed_dx += 256;
01767   }
01768 
01769   if((delta_y >= 0) && (delta_y <= 255))
01770   {
01771     b3 = (u8) delta_y;
01772     state.mouse.delayed_dy -= delta_y;
01773   }
01774   else if(delta_y > 255)
01775   {
01776     b3 = (u8) 0xff;
01777     state.mouse.delayed_dy -= 255;
01778   }
01779   else if(delta_y >= -256)
01780   {
01781     b3 = (u8) delta_y;
01782     b1 |= 0x20;
01783     state.mouse.delayed_dy -= delta_y;
01784   }
01785   else
01786   {
01787     b3 = (u8) 0x00;
01788     b1 |= 0x20;
01789     state.mouse.delayed_dy += 256;
01790   }
01791 
01792   b4 = (u8) - state.mouse.delayed_dz;
01793 
01794   mouse_enQ_packet(b1, b2, b3, b4);
01795 }
01796 
01806 void CKeyboard::execute()
01807 {
01808   unsigned  retval;
01809 
01810 /* -- moved to VGA card --
01811   if(bx_gui)
01812   {
01813     bx_gui->lock();
01814     bx_gui->handle_events();
01815     bx_gui->unlock();
01816   }
01817 */
01818   retval = periodic();
01819 
01820   if(retval & 0x01)
01821     theAli->pic_interrupt(0, 1);
01822   if(retval & 0x02)
01823     theAli->pic_interrupt(1, 4);
01824 }
01825 
01829 void CKeyboard::check_state()
01830 {
01831   if(myThread && !myThread->isRunning())
01832     FAILURE(Thread, "KBD thread has died");
01833 }
01834 
01838 void CKeyboard::run()
01839 {
01840   try
01841   {
01842     for(;;)
01843     {
01844       if(StopThread)
01845         return;
01846       execute();
01847       Poco::Thread::sleep(20);
01848     }
01849   }
01850 
01851   catch(Poco::Exception & e)
01852   {
01853     printf("Exception in kbd thread: %s.\n", e.displayText().c_str());
01854 
01855     // Let the thread die...
01856   }
01857 }
01858 
01859 static u32  kb_magic1 = 0x65481687;
01860 static u32  kb_magic2 = 0x24895375;
01861 
01865 int CKeyboard::SaveState(FILE* f)
01866 {
01867   long  ss = sizeof(state);
01868 
01869   fwrite(&kb_magic1, sizeof(u32), 1, f);
01870   fwrite(&ss, sizeof(long), 1, f);
01871   fwrite(&state, sizeof(state), 1, f);
01872   fwrite(&kb_magic2, sizeof(u32), 1, f);
01873   printf("kbc: %d bytes saved.\n", (int) ss);
01874   return 0;
01875 }
01876 
01880 int CKeyboard::RestoreState(FILE* f)
01881 {
01882   long    ss;
01883   u32     m1;
01884   u32     m2;
01885   size_t  r;
01886 
01887   r = fread(&m1, sizeof(u32), 1, f);
01888   if(r != 1)
01889   {
01890     printf("kbc: unexpected end of file!\n");
01891     return -1;
01892   }
01893 
01894   if(m1 != kb_magic1)
01895   {
01896     printf("kbc: MAGIC 1 does not match!\n");
01897     return -1;
01898   }
01899 
01900   fread(&ss, sizeof(long), 1, f);
01901   if(r != 1)
01902   {
01903     printf("kbc: unexpected end of file!\n");
01904     return -1;
01905   }
01906 
01907   if(ss != sizeof(state))
01908   {
01909     printf("kbc: STRUCT SIZE does not match!\n");
01910     return -1;
01911   }
01912 
01913   fread(&state, sizeof(state), 1, f);
01914   if(r != 1)
01915   {
01916     printf("kbc: unexpected end of file!\n");
01917     return -1;
01918   }
01919 
01920   r = fread(&m2, sizeof(u32), 1, f);
01921   if(r != 1)
01922   {
01923     printf("kbc: unexpected end of file!\n");
01924     return -1;
01925   }
01926 
01927   if(m2 != kb_magic2)
01928   {
01929     printf("kbc: MAGIC 1 does not match!\n");
01930     return -1;
01931   }
01932 
01933   printf("kbc: %d bytes restored.\n", (int) ss);
01934   return 0;
01935 }
01936 
01937 CKeyboard*  theKeyboard = 0;

SourceForge.net Logo
Project space on SourceForge.net