Exemple #1
0
static inline unsigned char
uread(int uart, unsigned int reg)
{
  register unsigned char val;

  if (uart == 0) {
    inport_byte(COM1_BASE_IO+reg, val);
  } else {
    inport_byte(COM2_BASE_IO+reg, val);
  }

  return val;
}
uint32_t mc146818a_get_register(
    uint32_t  ulCtrlPort,
    uint8_t   ucRegNum
)
{
    uint8_t   val;
    uint8_t   tmp;

    outport_byte( ulCtrlPort, ucRegNum );
    inport_byte( 0x84, tmp );   /* Hack a delay to give chip time to settle */
    inport_byte( ulCtrlPort+1, val );
    inport_byte( 0x84, tmp );   /* Hack a delay to give chip time to settle */
    return val;
}
Exemple #3
0
void
DEFUN_VOID(_Console_Initialize)
{
  register unsigned8 ignored;

  /* FORCE technical support mentioned that it may be necessary to
     read the DUSCC RX_BUFFER port four times to remove all junk.
     This code is a little more paranoid.  */
 
  inport_byte( RX_BUFFER, ignored );
  inport_byte( RX_BUFFER, ignored );
  inport_byte( RX_BUFFER, ignored );
  inport_byte( RX_BUFFER, ignored );
  inport_byte( RX_BUFFER, ignored );
}
Exemple #4
0
uint8_t com_get_register(uint32_t addr,uint8_t i)
{
  register uint8_t val;
  
  inport_byte( (addr + i),val );
  return val;
}
static bool pc386_ide_status_busy (uint32_t          port,
                                   volatile uint32_t timeout,
                                   uint8_t*          status_val,
                                   pc386_ide_sleeper sleeper)
{
  volatile uint8_t status;
  int              polls;

  do
  {
    polls = 500;
    while (polls)
    {
      inport_byte (port + IDE_REGISTER_STATUS, status);
      if ((status & IDE_REGISTER_STATUS_BSY) == 0)
      {
        *status_val = status;
        return true;
      }
      polls--;
    }

    if (timeout)
    {
      timeout--;
      pc386_ide_sleep (sleeper);
    }
  }
  while (timeout);

  *status_val = status;
  return false;
}
int Timer_read()
{
  register uint32_t         clicks;
  register uint32_t         total;

/*  outport_byte( TBCR, 0x00 );  stop the timer -- not needed on intel */

  outport_byte ( TMRCON, 0x40 );   /* latch the count */
  inport_byte  ( TMR1,   clicks ); /* read the count */

  total = Ttimer_val + 250 - clicks;

/*  outport_byte( TBCR, 0x00 );   initial value */
/*  outport_byte( IERA, 0x40 );   disable interrupt */

  /* ??? Is "do not restore old vector" causing problems? */

  if ( Timer_driver_Find_average_overhead == 1 )
    return total;          /* in one microsecond units */

  else {
    if ( total < LEAST_VALID )
      return 0;            /* below timer resolution */
    return (total - AVG_OVERHEAD);
  }
}
Exemple #7
0
static inline uint8_t BSP_i8259a_irq_in_service_reg(uint32_t ioport)
{
  uint8_t isr;
  outport_byte(ioport, PIC_OCW3_SEL | PIC_OCW3_RR | PIC_OCW3_RIS);
  inport_byte(ioport, isr);
  outport_byte(ioport, PIC_OCW3_SEL | PIC_OCW3_RR);
  return isr;
}
Exemple #8
0
/*-------------------------------------------------------------------------+
|         Function: rtcin
|      Description: Perform action on RTC and return its result.
| Global Variables: None.
|        Arguments: what - what to write to RTC port (what to do).
|          Returns: result received from RTC port after action performed.
+--------------------------------------------------------------------------*/
static inline uint8_t
rtcin(uint8_t         what)
{
    uint8_t         r;

    outport_byte(IO_RTC,   what);
    inport_byte (IO_RTC+1, r);
    return r;
} /* rtcin */
Exemple #9
0
static inline int _Force386_is_tx_ready()
{
  register unsigned8 status;

  inport_byte( TX_STATUS, status );

  if ( Is_tx_ready( status ) ) return 1;
  else                         return 0;
}
Exemple #10
0
/**
 * The head is moving up. "Wait" until the head is really up.
 * Then set status READY to signal we are ready for next hole.
 */
void control_retract()
{
	uint32_t input;
	inport_byte(0x7071, input);
	if ((input & 1) == 1) // is head already UP?
	{
		set_status(STATE_READY);
	}
}
Exemple #11
0
uint8_t rtd316_com_get_register(uint32_t addr, uint8_t reg)
{
  register uint8_t val = 0;

  outport_byte( addr, reg );
  /* It appears the no delay is needed between the accesses. */
  inport_byte( addr, val );

  return val;
}
/*
 * WD interrupt handler
 */
static void
wd8003Enet_interrupt_handler (void *unused)
{
  unsigned int tport;
  unsigned char status, status2;

  tport = wd_softc[0].port ;

  /*
   * Read status
   */
  inport_byte(tport+ISR, status);
  outport_byte(tport+IMR, 0x00);

  /*
   * Ring overwrite
   */

  if (status & MSK_OVW){
    outport_byte(tport+CMDR, MSK_STP + MSK_RD2);	/* stop 8390 */
    Wait_X_ms(2);
    outport_byte(tport+RBCR0, 0);			/* clear byte count */
    outport_byte(tport+RBCR1, 0);
    inport_byte(tport+ISR, status2);
    status |= (status2 & (MSK_PTX+MSK_TXE)) ;	/* TX status */
    outport_byte(tport+TCR, MSK_LOOP);		/* loopback mode */
    outport_byte(tport+CMDR, MSK_STA + MSK_RD2);	/* start */
    overrun = 1 ;
    if ((status & (MSK_PTX+MSK_TXE)) == 0)
	resend = 1;
  }

  /*
   * Frame received?
   */
  if (status & (MSK_PRX+MSK_RXE)) {
    outport_byte(tport+ISR, status & (MSK_PRX+MSK_RXE));
    wd_softc[0].rxInterrupts++;
    rtems_event_send (wd_softc[0].rxDaemonTid, INTERRUPT_EVENT);
  }

}
Exemple #13
0
/**
 * The head should be down or moves to this state. "wait" until
 * the HEAD_UP signal is false. don't literally wait, just
 * see if the head is down. If it is, begin retracting and set
 * RETRACT state.
 */
void control_punch(int * hole_to_punch)
{
	uint32_t input;
	inport_byte(0x7071, input);

	if ((input & 1) == 0){ // is head down?
		outport_byte(OUT_PUNCH_IRQ, 0b10); // begin retract
		set_status(STATE_RETRACT); // status "head is moving up"
		*hole_to_punch += 1; // loop to the next hole
		newdest = 1;
	}
}
static void
sendpacket (struct ifnet *ifp, struct mbuf *m)
{
	struct wd_softc *dp = ifp->if_softc;
	struct mbuf *n;
	unsigned int len, tport;
	uint8_t *shp, txReady;

	tport = dp->port;

  /*
   * Waiting for Transmitter ready
   */
  inport_byte(tport+CMDR, txReady);
  while(txReady & MSK_TXP)
    inport_byte(tport+CMDR, txReady);

  len = 0;
  shp = dp->base + (SHAPAGE * OUTPAGE);

  n = m;

  for (;;){
    len += m->m_len;
    memcpy(shp, (char *)m->m_data, m->m_len);
    shp += m->m_len ;
    if ((m = m->m_next) == NULL)
      break;
  }

  m_freem(n);

  if (len < ET_MINLEN) len = ET_MINLEN;
  outport_byte(tport+TBCR0, len);
  outport_byte(tport+TBCR1, (len >> 8) );
  outport_byte(tport+TPSR, OUTPAGE);
  outport_byte(tport+CMDR, MSK_TXP + MSK_RD2);
}
Exemple #15
0
static inline int _Force386_read_data()
{
  register unsigned8 ch;

#if ( PORTB == 1 )
    /* Force example code resets the Channel B Receiver here.
     * It appears to cause XON's to be lost.
     */  

     /* outport_byte( RX_STATUS, 0x10 );  */
#endif

  inport_byte( RX_BUFFER, ch );

  return ch;
}
/*
 * Stop the device
 */
static void
wd_stop (struct wd_softc *sc)
{
  unsigned int tport;
  unsigned char temp;
  struct ifnet *ifp = &sc->arpcom.ac_if;

  ifp->if_flags &= ~IFF_RUNNING;

  /*
   * Stop the transmitter
   */
  tport=wd_softc[0].port ;
  inport_byte(tport+0x04,temp);
  outport_byte(tport+0x04, temp & 0x7f);
  outport_byte(tport + CMDR, MSK_STP + MSK_RD2);

}
Exemple #17
0
/*-------------------------------------------------------------------------+
|         Function: init_rtc
|      Description: Initialize real-time clock (RTC).
| Global Variables: None.
|        Arguments: None.
|          Returns: Nothing.
+--------------------------------------------------------------------------*/
void
init_rtc(void)
{
  uint8_t         s;

  /* initialize brain-dead battery powered clock */
  outport_byte(IO_RTC,   RTC_STATUSA);
  outport_byte(IO_RTC+1, 0x26);
  outport_byte(IO_RTC,   RTC_STATUSB);
  outport_byte(IO_RTC+1, 2);

  outport_byte(IO_RTC,   RTC_DIAG);
  inport_byte (IO_RTC+1, s);
  if (s)
    printk("RTC BIOS diagnostic error %b\n", s);

  /* FIXME: This was last line's original version. How was it supposed to work?
       printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); */
} /* init_rtc */
/*
 * Initialize the ethernet hardware
 */
static void
wd8003Enet_initialize_hardware (struct wd_softc *sc)
{
  int  i1, ultra;
  char cc1, cc2;
  unsigned char  temp;
  rtems_status_code st;
  unsigned int tport;
  unsigned char *hwaddr;

  tport = sc->port;

  /* address from board ROM */
  inport_byte(tport+0x04, temp);
  outport_byte(tport+0x04, temp & 0x7f);

  hwaddr = sc->arpcom.ac_enaddr;
  for (i1=cc2=0; i1<8; i1++) {
    inport_byte(tport + ADDROM + i1, cc1);
    cc2 += cc1;
    if (i1 < 6)
      hwaddr[i1] = cc1;
  }

  inport_byte(tport+0x04, temp);
  outport_byte(tport+0x04, temp | 0x80);	/* alternate registers */
  outport_byte(tport+W83CREG, MSK_RESET);	/* reset board, set buffer */
  outport_byte(tport+W83CREG, 0);
  outport_byte(tport+W83CREG, MSK_ENASH + (int)((sc->bpar>>13)&0x3f));

  outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2);
  cc1 = MSK_BMS + MSK_FT10; /* configure 8 or 16 bits */

  inport_byte(tport+0x07, temp) ;

  ultra = ((temp & 0xf0) == 0x20 || (temp & 0xf0) == 0x40);
  if (ultra)
    cc1 = MSK_WTS + MSK_BMS + MSK_FT10;
  outport_byte(tport+DCR, cc1);
  outport_byte(tport+RBCR0, 0);
  outport_byte(tport+RBCR1, 0);
  outport_byte(tport+RCR, MSK_MON);	       	/* disable the rxer */
  outport_byte(tport+TCR, 0);			/* normal operation */
  outport_byte(tport+PSTOP, OUTPAGE);		/* init PSTOP */
  outport_byte(tport+PSTART, 0);	       	/* init PSTART */
  outport_byte(tport+BNRY, -1);			/* init BNRY */
  outport_byte(tport+ISR, -1);			/* clear IR's */
  outport_byte(tport+IMR, 0x15);	       	/* enable interrupt */

  outport_byte(tport+CMDR, MSK_PG1 + MSK_RD2);

  for (i1=0; i1<6; i1++)			/* initial physical addr */
    outport_byte(tport+PAR+i1, hwaddr[i1]);

  for (i1=0; i1<MARsize; i1++)			/* clear multicast */
    outport_byte(tport+MAR+i1, 0);
  outport_byte(tport+CURR, 0);			/* init current packet */

  outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2);
  outport_byte(tport+CMDR, MSK_STA + MSK_RD2);	/* put 8390 on line */
  outport_byte(tport+RCR, MSK_AB);		/* MSK_AB accept broadcast */

  if (ultra) {
    inport_byte(tport+0x0c, temp);
    outport_byte(tport+0x0c, temp | 0x80);
    outport_byte(tport+0x05, 0x80);
    outport_byte(tport+0x06, 0x01);
  }

  /*
   * Set up interrupts
   */
  sc->irqInfo.hdl = wd8003Enet_interrupt_handler;
  sc->irqInfo.on  = nopOn;
  sc->irqInfo.off = nopOn;
  sc->irqInfo.isOn = wdIsOn;

  st = BSP_install_rtems_irq_handler (&sc->irqInfo);
  if (!st)
    rtems_panic ("Can't attach WD interrupt handler for irq %d\n",
		  sc->irqInfo.name);
}
/*=========================================================================*\
| Function:                                                                 |
\*-------------------------------------------------------------------------*/
void pc386_ide_initialize
(
/*-------------------------------------------------------------------------*\
  | Purpose:                                                                  |
  |  initialize IDE access                                                    |
  +---------------------------------------------------------------------------+
  | Input Parameters:                                                         |
  \*-------------------------------------------------------------------------*/
  int  minor                              /* controller minor number       */
 )
/*-------------------------------------------------------------------------*\
  | Return Value:                                                             |
  |    <none>                                                                 |
  \*=========================================================================*/
{
  uint32_t port = IDE_Controller_Table[minor].port1;
  uint8_t  dev = 0;

  if (pc386_ide_show)
    printk("IDE%d: port base: %04x\n", minor, port);

  outport_byte(port+IDE_REGISTER_DEVICE_HEAD,
               (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | 0xE0);
  wait(10000);
  outport_byte(port+IDE_REGISTER_DEVICE_CONTROL,
               IDE_REGISTER_DEVICE_CONTROL_SRST | IDE_REGISTER_DEVICE_CONTROL_nIEN);
  wait(10000);
  outport_byte(port+IDE_REGISTER_DEVICE_CONTROL,
               IDE_REGISTER_DEVICE_CONTROL_nIEN);
  wait(10000);

  for (dev = 0; dev < 2; dev++)
  {
    uint16_t    capabilities = 0;
    uint32_t    byte;
    uint8_t     status;
    uint8_t     error;
    uint8_t     cyllsb;
    uint8_t     cylmsb;
    const char* label = dev ? " slave" : "master";
    int         max_multiple_sectors = 0;
    int         cur_multiple_sectors = 0;
    uint32_t    cylinders = 0;
    uint32_t    heads = 0;
    uint32_t    sectors = 0;
    uint32_t    lba_sectors = 0;
    char        model_number[41];
    char*       p = &model_number[0];
    bool        data_ready;

    memset(model_number, 0, sizeof(model_number));

    outport_byte(port+IDE_REGISTER_DEVICE_HEAD,
                 (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | 0xE0);
    /*
      outport_byte(port+IDE_REGISTER_SECTOR_NUMBER,
      (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | IDE_REGISTER_LBA3_L);
    */

    outport_byte(port+IDE_REGISTER_COMMAND, 0x00);

    if (!pc386_ide_status_busy (port, PC386_IDE_PROBE_TIMEOUT,
                                &status, pc386_ide_prestart_sleep))
      continue;

    inport_byte(port+IDE_REGISTER_STATUS,        status);
    inport_byte(port+IDE_REGISTER_ERROR,         error);
    inport_byte(port+IDE_REGISTER_CYLINDER_LOW,  cyllsb);
    inport_byte(port+IDE_REGISTER_CYLINDER_HIGH, cylmsb);

    if (pc386_ide_show)
    {
      printk("IDE%d:%s: status=%02x\n", minor, label, status);
      printk("IDE%d:%s: error=%02x\n", minor, label, error);
      printk("IDE%d:%s: cylinder-low=%02x\n", minor, label, cyllsb);
      printk("IDE%d:%s: cylinder-high=%02x\n", minor, label, cylmsb);
    }

    outport_byte(port+IDE_REGISTER_COMMAND, 0xec);

    if (!pc386_ide_status_busy (port, PC386_IDE_PRESTART_TIMEOUT,
                                &status, pc386_ide_prestart_sleep))
    {
      if (pc386_ide_show)
        printk("IDE%d:%s: device busy: %02x\n", minor, label, status);
      continue;
    }

    data_ready = pc386_ide_status_data_ready (port,
                                              250,
                                              &status,
                                              pc386_ide_prestart_sleep);

    if (status & IDE_REGISTER_STATUS_ERR)
    {
      inport_byte(port+IDE_REGISTER_ERROR, error);
      if (error != 4)
      {
        if (pc386_ide_show)
          printk("IDE%d:%s: error=%04x\n", minor, label, error);
        continue;
      }
      /*
       * The device is an ATAPI device.
       */
      outport_byte(port+IDE_REGISTER_COMMAND, 0xa1);
      data_ready = pc386_ide_status_data_ready (port,
                                                250,
                                                &status,
                                                pc386_ide_prestart_sleep);
    }

    if (!data_ready)
      continue;

    byte = 0;
    while (byte < 512)
    {
      uint16_t word;

      if (pc386_ide_show && ((byte % 16) == 0))
        printk("\n %04x : ", byte);

      inport_word(port+IDE_REGISTER_DATA, word);

      if (pc386_ide_show)
        printk ("%04x ", word);

      if (byte == 2)
        cylinders = word;
      if (byte == 6)
        heads = word;
      if (byte == 12)
        sectors = word;

      if (byte >= 54 && byte < (54 + 40))
      {
        *p = word >> 8;
        p++;
        *p = word;
        p++;
      }

      if (byte == (47 * 2))
        max_multiple_sectors = word & 0xff;

      if (byte == (49 * 2))
        capabilities = word;

      if (byte == (59 * 2))
      {
        if (word & (1 << 8))
          cur_multiple_sectors = word & 0xff;
      }

      if (byte == (60 * 2))
        lba_sectors = word;
      if (byte == (61 * 2))
        lba_sectors |= word << 16;

      byte += 2;
    }

    if (pc386_ide_show)
      printk("\nbytes read = %d\n", byte);

    if (p != &model_number[0])
    {
      uint32_t size;
      uint32_t left;
      uint32_t right;
      char     units;

      if (capabilities & (1 << 9))
        size = lba_sectors;
      else
        size = cylinders * heads * sectors;

      size /= 2;

      if (size > (1024 * 1024))
      {
        size = (size * 10) / (1000 * 1000);
        units = 'G';
      }
      else if (size > 1024)
      {
        size = (size * 10) / 1000;
        units = 'M';
      }
      else
      {
        size = size * 10;
        units = 'K';
      }

      left = size / 10;
      right = size % 10;

      p--;
      while (*p == ' ')
      {
        *p = '\0';
        p--;
      }

      printk("IDE%d:%s:%s, %u.%u%c (%u/%u/%u), max blk size:%d\n",
             minor, label, model_number, left, right, units,
             heads, cylinders, sectors, max_multiple_sectors * 512);
    }

#if IDE_CLEAR_MULTI_SECTOR_COUNT
    if (max_multiple_sectors)
    {
      outport_byte(port+IDE_REGISTER_SECTOR_COUNT, 0);
      outport_byte(port+IDE_REGISTER_COMMAND, 0xc6);

      if (!pc386_ide_status_busy (port, PC386_IDE_PRESTART_TIMEOUT,
                                  &status, pc386_ide_prestart_sleep))
      {
        if (pc386_ide_show)
          printk("IDE%d:%s: device busy: %02x\n", minor, label, status);
        continue;
      }

      inport_byte(port+IDE_REGISTER_STATUS, status);
      if (status & IDE_REGISTER_STATUS_ERR)
      {
        inport_byte(port+IDE_REGISTER_ERROR, error);
        if (error & IDE_REGISTER_ERROR_ABRT)
          printk("IDE%d:%s: disable multiple failed\n", minor, label);
        else
          printk("IDE%d:%s: unknown error on disable multiple: %02x\n",
                 minor, label, error);
      }
    }
#endif

    outport_byte(port+IDE_REGISTER_DEVICE_CONTROL,
                 IDE_REGISTER_DEVICE_CONTROL_nIEN);
    wait(10000);
  }
static void
wd_rxDaemon (void *arg)
{
  unsigned int tport;
  struct ether_header *eh;
  struct wd_softc *dp = (struct wd_softc *)&wd_softc[0];
  struct ifnet *ifp = &dp->arpcom.ac_if;
  struct mbuf *m;
  unsigned int i2;
  unsigned int len;
  volatile unsigned char start, next, current;
  unsigned char *shp, *temp;
  unsigned short *real_short_ptr;
  rtems_event_set events;

  tport = wd_softc[0].port ;

  for (;;){

    rtems_bsdnet_event_receive (INTERRUPT_EVENT,
				RTEMS_WAIT|RTEMS_EVENT_ANY,
				RTEMS_NO_TIMEOUT,
				&events);

    for (;;){
      inport_byte(tport+BNRY, start);

      outport_byte(tport+CMDR, MSK_PG1 + MSK_RD2);
      inport_byte(tport+CURR, current);
      outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2);

      start += 1;
      if (start >= OUTPAGE){
	start = 0;
      }

      if (current == start)
	break;

      /* real_short_ptr avoids cast on lvalue which gcc no longer allows */
      shp = dp->base + 1 + (SHAPAGE * start);
      next = *shp++;
      real_short_ptr = (unsigned short *)shp;
      len = *(real_short_ptr)++ - 4;

      if (next >= OUTPAGE){
	next = 0;
      }

      MGETHDR (m, M_WAIT, MT_DATA);
      MCLGET (m, M_WAIT);
      m->m_pkthdr.rcvif = ifp;

      temp = (unsigned char *) m->m_data;
      m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);

      if ((i2 = (OUTPAGE - start) * SHAPAGE - 4) < len){
	memcpy(temp, shp, i2);
	len -= i2;
	temp += i2;
	shp = dp->base;
      }
      memcpy(temp, shp, len);

      eh = mtod (m, struct ether_header *);
      m->m_data += sizeof(struct ether_header);
      ether_input (ifp, eh, m);

      outport_byte(tport+BNRY, next-1);
    }

  /*
   * Ring overwrite
   */
    if (overrun){
      outport_byte(tport+ISR, MSK_OVW);		/* reset IR */
      outport_byte(tport+TCR, 0);		/* out of loopback */
      if (resend  == 1)
	outport_byte(tport+CMDR, MSK_TXP + MSK_RD2);	/* resend */
      resend = 0;
      overrun = 0;
    }

    outport_byte(tport+IMR, 0x15);  /* re-enable IT rx */
  }
}
Exemple #21
0
/*-------------------------------------------------------------------------+
|         Function: _IBMPC_scankey
|      Description: This function can be called during a poll for input, or by
|                   an ISR. Basically any time you want to process a keypress.
| Global Variables: key_map, shift_map.
|        Arguments: outChar - character read in case of a valid reading,
|                   otherwise unchanged.
|          Returns: TRUE in case a valid character has been read,
|                   FALSE otherwise.
+--------------------------------------------------------------------------*/
static bool
_IBMPC_scankey(char *outChar)
{
  unsigned char inChar;
  static int alt_pressed   = 0;
  static int ctrl_pressed  = 0;
  static int shift_pressed = 0;
  static int caps_pressed  = 0;
  static int extended      = 0;

  *outChar = '\0'; /* default value if we return false */

  /* Read keyboard controller, toggle enable */
  inport_byte(KBD_CTL, inChar);
  outport_byte(KBD_CTL, inChar & ~0x80);
  outport_byte(KBD_CTL, inChar | 0x80);
  outport_byte(KBD_CTL, inChar & ~0x80);

  /* See if it has data */
  inport_byte(KBD_STATUS, inChar);
  if ((inChar & 0x01) == 0)
    return false;

  /* Read the data.  Handle nonsense with shift, control, etc. */
  inport_byte(KBD_DATA, inChar);

  if (extended)
    extended--;

  switch (inChar)
  {
    case 0xe0:
      extended = 2;
      return false;
      break;

    case 0x38:
      alt_pressed = 1;
      return false;
      break;
    case 0xb8:
      alt_pressed = 0;
      return false;
      break;

    case 0x1d:
      ctrl_pressed = 1;
      return false;
      break;
    case 0x9d:
      ctrl_pressed = 0;
      return false;
      break;

    case 0x2a:
      if (extended)
        return false;
    case 0x36:
      shift_pressed = 1;
      return false;
      break;
    case 0xaa:
      if (extended)
        return false;
    case 0xb6:
      shift_pressed = 0;
      return false;
      break;

    case 0x3a:
      caps_pressed = 1;
      return false;
      break;
    case 0xba:
      caps_pressed = 0;
      return false;
      break;

    case 0x53:
      if (ctrl_pressed && alt_pressed)
        bsp_reset(); /* ctrl+alt+del -> reboot */
      break;

    /*
     * Ignore unrecognized keys--usually arrow and such
     */
    default:
      if ((inChar & 0x80) || (inChar > 0x39))
      /* High-bit on means key is being released, not pressed */
        return false;
      break;
  } /* switch */

  /* Strip high bit, look up in our map */
  inChar &= 0x7f;
  if (ctrl_pressed)
  {
    *outChar = key_map[inChar];
    *outChar &= 037;
  }
  else
  {
    *outChar = shift_pressed ? shift_map[inChar] : key_map[inChar];
    if (caps_pressed)
    {
      if (*outChar >= 'A' && *outChar <= 'Z')
        *outChar += 'a' - 'A';
      else if (*outChar >= 'a' && *outChar <= 'z')
        *outChar -= 'a' - 'A';
    }
  }

  return true;
} /* _IBMPC_scankey */