Esempio n. 1
0
static void handle_irq (unsigned int port_number)
{
  uint8_t iir;
  uint8_t data;
  uint8_t tx_chars;
  uint16_t base;
  uint16_t tmp = 0;

  base = serial_port[port_number].port;
  iir = system_port_in_uint8_t (base + REGISTER_IIR);

  while ((iir & 0x01) == 0)
  {
    iir &= 0x06;
    iir >>= 1;
    
    if (iir == 0)
    {
      /* Modem status. */

      log_print (&log_structure, LOG_URGENCY_DEBUG, "Serial modem IRQ.");
      (void) system_port_in_uint8_t (base + REGISTER_MSR);
    }
    else if (iir == 1)
    {
      /* Ready to transmit. */

      tx_chars = 1;

      if (serial_port[port_number].use_fifo != FALSE)
      {
        tx_chars = serial_port[port_number].tx_fifo;
      }
      
      while (serial_port[port_number].lock_tx == TRUE)
      {
        system_call_dispatch_next ();
      }
      serial_port[port_number].lock_tx = TRUE;

      while (tx_chars != 0)
      {
        tx_chars--;
        
        if (serial_port[port_number].tx_current != serial_port[port_number].tx_end)
        {
          /* Send one more character. */

          data = serial_port[port_number].tx_buffer[serial_port[port_number].tx_current];
          serial_port[port_number].tx_current++;
          serial_port[port_number].tx_current %= BUFFER_SIZE;
          system_port_out_uint8_t (base + REGISTER_DATA, data);
        }
        else
        {
          /* No more data. Disable Tx interrupt. */

          data = system_port_in_uint8_t (base + REGISTER_IER);
          data &= 0xFD;
          system_port_out_uint8_t (base + REGISTER_IER, data);
          break;
        }
      }
      serial_port[port_number].lock_tx = FALSE;
    }
    else if (iir == 2)
    {
      /* Rx data available. */

      while (serial_port[port_number].lock_rx == TRUE)
      {
        system_call_dispatch_next ();
      }
      serial_port[port_number].lock_rx = TRUE;

      do
      {
        tmp++;
        data = system_port_in_uint8_t (base + REGISTER_DATA);
        serial_port[port_number].rx_buffer[serial_port[port_number].rx_end] =
          data;
        serial_port[port_number].rx_end++;
        serial_port[port_number].rx_end %= BUFFER_SIZE;

        if (serial_port[port_number].rx_end ==
            serial_port[port_number].rx_current)
        {
          log_print (&log_structure, LOG_URGENCY_ERROR,
                     "Rx buffer overflow.");
        }
      } while ((system_port_in_uint8_t (base + REGISTER_LSR) & 0x01) == 0x01);

      log_print_formatted (&log_structure, LOG_URGENCY_DEBUG,
                           "Received %d chars.", tmp);

      /* Check for pending messages to send. */
      
      if (serial_port[port_number].rx_pending != 0 &&
          unread_size (port_number) >= serial_port[port_number].rx_pending)
      {
        send_data (port_number);
        serial_port[port_number].rx_pending = 0;
      }

      serial_port[port_number].lock_rx = FALSE;

      /* FIXME: Prevent Tx lockup. */
  
    }
    else
    {
      /* Receiver line status. */

      log_print (&log_structure, LOG_URGENCY_DEBUG, "Serial line IRQ.");
      serial_port[port_number].line_error++;

      data = system_port_in_uint8_t (base + REGISTER_LSR);

      if ((data & 0x02) != 0)
      {
        serial_port[port_number].overrun_error++;
        log_print (&log_structure, LOG_URGENCY_DEBUG, "Overrun error.");
      }
      if ((data & 0x04) != 0)
      {
        serial_port[port_number].parity_error++;
        log_print (&log_structure, LOG_URGENCY_DEBUG, "Parity error.");
      }
      if ((data & 0x08) != 0)
      {
        log_print (&log_structure, LOG_URGENCY_DEBUG, "Framing error.");
        serial_port[port_number].framing_error++;
      }
      
      (void) system_port_in_uint8_t (base + REGISTER_DATA);
      serial_port[port_number].errors++;
    }
    
    iir = system_port_in_uint8_t (base + REGISTER_IIR);
  }
}
Esempio n. 2
0
int main (void)
{
  keyboard_packet_type keyboard_packet;
  int event_type;
  bool local_echo = FALSE;
  int baudrate_num = 4;

  log_init (&log_structure, PACKAGE_NAME, &empty_tag);
  
  system_call_process_name_set (PACKAGE_NAME);

  console_init (&console_structure, &empty_tag,
                IPC_CONSOLE_CONNECTION_CLASS_CLIENT);
  console_open (&console_structure, 80, 50, 4, VIDEO_MODE_TYPE_TEXT);
  console_use_keyboard (&console_structure, TRUE, CONSOLE_KEYBOARD_NORMAL);
  console_clear (&console_structure);
  console_print (&console_structure,
                 "Terminator 2000 - The final terminator.\n\n");
    
  if (system_call_thread_create () == STORM_RETURN_THREAD_NEW)
  {
    unsigned char buffer[100];
    int length = 1;
    
    while (TRUE)
    {
      if (config1 != FALSE)
      {
        while (lock == TRUE)
        {
          system_call_dispatch_next ();
        }
        lock = TRUE;

        if (serial_init (&ipc_structure1, &empty_tag) != SERIAL_RETURN_SUCCESS)
        {
          log_print (&log_structure, LOG_URGENCY_EMERGENCY,
                     "Could not establish connection to a serial service.");
          return -1;
        }
        config1 = FALSE;
        lock = FALSE;
        log_print_formatted (&log_structure, LOG_URGENCY_DEBUG, "COM %d opened rx.", port_num+1);
      }

      if (serial_read (&ipc_structure1, buffer, length) != SERIAL_RETURN_SUCCESS)
      {
        log_print (&log_structure, LOG_URGENCY_ERROR,
                   "Error reading from port.");
      }
      else
      {
        buffer[length] = 0;
        console_print (&console_structure, buffer);
      }
    }
  }

  while (TRUE)
  {
    bool send = TRUE;
    bool configure = FALSE;
    char key;

    if (config2 != FALSE)
    {
      if (serial_init (&ipc_structure2, &empty_tag) != SERIAL_RETURN_SUCCESS)
      {
        log_print (&log_structure, LOG_URGENCY_EMERGENCY,
                   "Could not establish connection to a serial service.");
        return -1;
      }
      config2 = FALSE;
      log_print_formatted (&log_structure, LOG_URGENCY_DEBUG, "COM %d opened tx.", port_num+1);
    }

    console_event_wait (&console_structure, &keyboard_packet,
                        &event_type, TRUE);

    if (keyboard_packet.key_pressed == TRUE)
    {
      if (keyboard_packet.has_character_code == 1)
      {
        key = keyboard_packet.character_code[0];
      }
      else if (keyboard_packet.has_special_key == 1)
      {
        switch (keyboard_packet.special_key)
        {
          case IPC_KEYBOARD_SPECIAL_KEY_ESCAPE:
          {
            log_print (&log_structure, LOG_URGENCY_DEBUG, "Local echo toggled.");
            local_echo = !local_echo;
            send = FALSE;
            break;
          }

          case IPC_KEYBOARD_SPECIAL_KEY_F10:
          {
            if (++port_num >= PORT_NUM)
            {
              port_num = 0;
            }

            send = FALSE;
            config2 = TRUE;

            while (lock == TRUE)
            {
              system_call_dispatch_next ();
            }
            lock = TRUE;
            config1 = TRUE;
            lock = FALSE;
            break;
          }

          case IPC_KEYBOARD_SPECIAL_KEY_F11:
          {
            if (--baudrate_num < 0)
            {
              baudrate_num = BAUDRATE_NUM - 1;
            }

            send = FALSE;
            configure = TRUE;
            break;
          }

          case IPC_KEYBOARD_SPECIAL_KEY_F12:
          {
            if (++baudrate_num >= BAUDRATE_NUM)
            {
              baudrate_num = 0;
            }

            send = FALSE;
            configure = TRUE;
            break;
          }

          case IPC_KEYBOARD_SPECIAL_KEY_TAB:
          {
            key = '\t';
            break;
          }

          case IPC_KEYBOARD_SPECIAL_KEY_BACK_SPACE:
          {
            key = 8;
            break;
          }
          
          case IPC_KEYBOARD_SPECIAL_KEY_ENTER:
          {
            key = '\n';
            break;
          }
        }
      }

      if (send)
      {
        if (serial_write (&ipc_structure2, &key, 1) != SERIAL_RETURN_SUCCESS)
        {
          log_print (&log_structure, LOG_URGENCY_ERROR, "Error writing to port.");
        }
        else
        {
          if (local_echo)
          {         
            char buffer[] = { key, 0 };
            console_print (&console_structure, buffer);
          }
        }
      }

      if (configure != FALSE)
      {
        if (serial_config_line (&ipc_structure2, baudrates[baudrate_num], 8, 
            0, SERIAL_PARITY_NONE) != SERIAL_RETURN_SUCCESS)
        {
          log_print (&log_structure, LOG_URGENCY_ERROR, "Error configuring port.");
        }
        else
        {
          log_print_formatted (&log_structure, LOG_URGENCY_DEBUG, "%d 8/N/1 selected.", baudrates[baudrate_num]);
        }
      }
    }
  }

  return 0;
}