"Fossies" - the Fresh Open Source Software Archive

Member "pcemu/hardware.c" (22 Jan 2001, 6878 Bytes) of package /linux/privat/old/pcemu-1.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "hardware.c" see the Fossies "Dox" file reference documentation.

    1 /****************************************************************************
    2 *                                                                           *
    3 *                            Third Year Project                             *
    4 *                                                                           *
    5 *                            An IBM PC Emulator                             *
    6 *                          For Unix and X Windows                           *
    7 *                                                                           *
    8 *                             By David Hedley                               *
    9 *                                                                           *
   10 *                                                                           *
   11 * This program is Copyrighted.  Consult the file COPYRIGHT for more details *
   12 *                                                                           *
   13 ****************************************************************************/
   14 
   15 /* This is HARDWARE.C It contains stuff about the PC hardware (chips etc) */
   16 
   17 #include "global.h"
   18 
   19 #include <stdio.h>
   20 #include <sys/time.h>
   21 #include <signal.h>
   22 
   23 #include "hardware.h"
   24 #include "cpu.h"
   25 #include "vgahard.h"
   26 
   27 #ifdef DEBUGGER
   28 #    include "debugger.h"
   29 #endif
   30 
   31 static struct itimerval timer;    
   32 
   33 static volatile int disable_int;
   34 static volatile int timer_blocked = 1;
   35 
   36 #define PORT60SIZE 5
   37 
   38 static BYTE port60buffer[PORT60SIZE];
   39 static int port60start, port60end;
   40 
   41 static unsigned PIC_inservice;
   42 static unsigned PIC_irq;
   43 static unsigned PIC_mask = ~(PIC_TIMER|PIC_KEYBOARD);
   44 
   45 static unsigned timer_tmp;
   46 
   47 static unsigned VGA_status;
   48 
   49 static void PIC_interrupt(void)
   50 {
   51     if (PIC_inservice)
   52     {
   53         D2(printf("PIC still blocked\n"););
   54         return;
   55     }
   56 
   57     if (PIC_irq & ~PIC_mask & PIC_TIMER)
   58     {
   59         D2(printf("INTR: timer\n"););
   60         PIC_inservice = PIC_TIMER;
   61         PIC_irq &= ~PIC_TIMER;
   62         if (IF)
   63             int_pending = 8;
   64         else
   65         {
   66             D2(printf("INTR blocked: IF disabled\n"););
   67             int_blocked = 8;
   68         }
   69     }
   70     else if (PIC_irq & ~PIC_mask & PIC_KEYBOARD)
   71     {
   72         D2(printf("INTR: keyboard\n"););
   73         PIC_inservice = PIC_KEYBOARD;
   74         PIC_irq &= ~PIC_KEYBOARD;
   75         if (IF)
   76             int_pending = 9;
   77         else
   78         {
   79             D2(printf("INTR blocked: IF disabled\n"););
   80             int_blocked = 9;
   81         }
   82     }
   83 }
   84 
   85 
   86 static void PIC_flagint(unsigned interrupt)
   87 {
   88     disable();
   89     D2(printf("IRQ %02X\n", interrupt););
   90     PIC_irq |= interrupt;
   91     enable();
   92 }
   93 
   94 
   95 void PIC_EOI(void)
   96 {
   97     disable();
   98 
   99     if (PIC_inservice & PIC_KEYBOARD)
  100     {
  101         if (++port60start >= PORT60SIZE)
  102             port60start = 0;
  103 
  104         if (port60start != port60end)
  105             PIC_irq |= PIC_KEYBOARD;
  106     }
  107 
  108 
  109     PIC_inservice = 0;
  110     PIC_interrupt();
  111     enable();
  112 }
  113 
  114 
  115 int port60_buffer_ok(int count)
  116 {
  117     int tmp = port60end;
  118 
  119     for (; count > 0; count--)
  120     {
  121         if (++tmp >= PORT60SIZE)
  122             tmp = 0;
  123 
  124         if (tmp == port60start)
  125             return FALSE;
  126     }
  127 
  128     return TRUE;
  129 }
  130 
  131 
  132 void put_scancode(BYTE *code, int count)
  133 {
  134     for (; count > 0; count--)
  135     {
  136         port60buffer[port60end] = *code++;
  137 
  138         if (++port60end >= PORT60SIZE)
  139             port60end = 0;
  140     }
  141 
  142     PIC_flagint(PIC_KEYBOARD);
  143 
  144     D2(
  145       {
  146           int tmp;
  147 
  148           printf("INT9 signalled\n");
  149           printf("Port60 buffer: ");
  150 
  151           tmp = port60start;
  152           while (tmp != port60end)
  153           {
  154               printf("%02X ", port60buffer[tmp]);
  155               if (++tmp >= PORT60SIZE)
  156                   tmp = 0;
  157           }
  158           printf("\n");
  159       }
  160     )
  161 }
  162 
  163 
  164 static BYTE read_port60(void)
  165 {
  166     BYTE ret;
  167     static BYTE lastread = 0;
  168 
  169     disable();
  170 
  171     if (port60start == port60end)
  172         ret = lastread;
  173     else
  174         lastread = ret = port60buffer[port60start];
  175         
  176     enable();
  177 
  178     return ret;
  179 }
  180 
  181 #define TIMER_MULT 4
  182 
  183 static volatile int int8_counter = TIMER_MULT;
  184 
  185 static int timer_handler(int sig)
  186 {
  187 
  188 #ifdef DEBUGGER
  189     if (in_debug)
  190         return 0;
  191 #endif
  192 
  193     if (disable_int)
  194     {
  195         D2(printf("Timer called when disabled\n"););
  196         timer_blocked++;
  197         return 0;
  198     }
  199 
  200     disable();
  201 
  202     vga_interrupt();
  203 
  204     timer_tmp++;
  205 
  206     if (--int8_counter == 0)
  207     {
  208         PIC_flagint(PIC_TIMER);
  209         int8_counter = TIMER_MULT;
  210     }
  211 
  212     PIC_interrupt();
  213 
  214     enable();
  215     return 0;
  216 }
  217 
  218 
  219 #ifndef SA_RESTART
  220 #define SA_RESTART 0
  221 #endif
  222 
  223 void init_timer(void)
  224 {
  225     struct sigaction sa;
  226 
  227     sa.sa_handler = (void *)timer_handler;
  228     sa.sa_flags = SA_RESTART;
  229     sigemptyset(&sa.sa_mask);
  230 
  231     sigaction(SIGALRM, &sa, NULL);
  232 
  233     timer.it_interval.tv_sec = timer.it_value.tv_sec = 0;
  234     timer.it_interval.tv_usec = timer.it_value.tv_usec =  
  235         (long)(1000000.0 /((float)TIMER_MULT*TICKSPERSEC));
  236 
  237     D2(printf("Set timer to %ld microseconds\n", timer.it_interval.tv_usec););
  238     setitimer(ITIMER_REAL, &timer, NULL);
  239 }
  240 
  241 
  242 void stoptimer(void)
  243 {
  244     timer.it_interval.tv_sec = timer.it_value.tv_sec = 
  245     timer.it_interval.tv_usec = timer.it_value.tv_usec =  0;
  246     setitimer(ITIMER_REAL, &timer, NULL);
  247     signal(SIGALRM, SIG_IGN);
  248 }
  249 
  250 
  251 void starttimer(void)
  252 {
  253     init_timer();
  254 }
  255 
  256 
  257 void disable(void)
  258 {
  259     if (disable_int == 0)
  260         timer_blocked = 0;
  261     disable_int++;
  262 }
  263 
  264 
  265 void enable(void)
  266 {
  267     if (disable_int > 0)
  268         disable_int--;
  269 
  270     if (disable_int == 0)
  271         while (timer_blocked > 0)
  272         {
  273             timer_blocked--;
  274             timer_handler(SIGALRM);
  275         }
  276 }
  277 
  278 
  279 static int PIT_toggle = 1;
  280 
  281 BYTE read_port(unsigned port)
  282 {
  283     BYTE val;
  284     static unsigned timer_tmp;
  285 
  286     switch(port)
  287     {
  288     case 0x21:
  289         val = PIC_mask;
  290         break;
  291     case 0x40:
  292     case 0x41:
  293     case 0x42:
  294         disable();
  295         if ((PIT_toggle = !PIT_toggle) == 0)
  296             val = timer_tmp & 0xff;
  297         else
  298         {
  299             val = (timer_tmp & 0xff00) >> 8;
  300             timer_tmp++;
  301         }
  302         enable();
  303         break;
  304     case 0x60:
  305         val = read_port60();
  306         break;
  307     case 0x61:
  308         val = 0xd0;
  309         break;
  310     case 0x3da:
  311         val = VGA_status;
  312         VGA_status ^= 0x9;
  313         break;
  314     case 0x2fd:
  315     val = 0xff;
  316     break;
  317     default:
  318         val = 0;
  319         break;
  320     }
  321     
  322     D(printf("Reading 0x%02X from port 0x%04X\n", val, port););
  323     return val;
  324 }
  325 
  326 
  327 void write_port(unsigned port, BYTE value)
  328 {
  329     switch(port)
  330     {
  331     case 0x20:
  332         if (value == 0x20)
  333         {
  334             PIC_EOI();
  335             return;
  336         }
  337         break;
  338     case 0x21:
  339         disable();
  340         PIC_mask = value;
  341         enable();
  342         break;
  343     case 0x43:
  344         PIT_toggle = 1;
  345         break;
  346     default:
  347         break;
  348     }
  349     D(printf("Writing 0x%02X to port 0x%04X\n", value, port););
  350 
  351 }
  352 
  353