Esempio n. 1
0
static bool register_ports (ata_drive_type *ata_drive)
{
  if (system_call_port_range_register (ata_drive->base_port, 8, "ATAPI") !=
       STORM_RETURN_SUCCESS)
  {
    log_print_formatted (&log_structure, LOG_URGENCY_EMERGENCY,
                         "Could not allocate port range %x-%x.",
                         ata_drive->base_port, ata_drive->base_port + 8);
    return FALSE;    
  }
  if (system_call_port_range_register (ata_drive->base_port + 0x206, 1, "ATAPI") 
     != STORM_RETURN_SUCCESS)
  {
    log_print_formatted (&log_structure, LOG_URGENCY_EMERGENCY,
                         "Could not allocate port range %x-%x.",
                         ata_drive->base_port + 0x206, ata_drive->base_port + 0x206);
    return FALSE;
  }

  return TRUE;
}
Esempio n. 2
0
static bool realtek_start_transmit (u8 *data, unsigned int length,
                                   realtek_device_type *device)
{
  long io_address = device->port_base;
  int entry;
  
  // netif_stop_queue(dev);
  
  /* Calculate the next Tx descriptor entry. */

  entry = device->current_tx % NUMBER_OF_TX_DESCRIPTORS;
  
  // tp->tx_info[entry].skb = skb;

  // tp->tx_info[entry].mapping = 0;
  
  memory_copy (device->tx_buffer[entry], data, length);
  system_port_out_u32 (io_address + TxAddress0 + entry * 4, 
                       (u32) (device->tx_buffers_dma + 
                              (device->tx_buffer[entry] -
                               device->tx_buffers)));
  
  /* Note: the chip doesn't have auto-pad! */
  
  system_port_out_u32 (io_address + TxStatus0 + entry * 4,
                       device->tx_flag | 
                       (length >= NETWORK_ETHERNET_MINIMUM_LENGTH ? 
                        length : NETWORK_ETHERNET_MINIMUM_LENGTH));
  
  /* Typical path */

  if (++device->current_tx - device->dirty_tx < NUMBER_OF_TX_DESCRIPTORS) 
  {
    // netif_start_queue(dev);
  }
  else 
  {
    device->tx_full = TRUE;
  }
  
  // dev->trans_start = jiffies;

  if (realtek_debug > 4)
  {
    log_print_formatted (&log_structure, LOG_URGENCY_DEBUG,
                         "Queued Tx packet at %p size %d to slot %d.\n",
                         data, length, entry);
  }
  
  return TRUE;
}
Esempio n. 3
0
void irq_handler (unsigned int port_number)
{
  system_call_thread_name_set ("IRQ handler");

  if (system_call_irq_register (serial_port[port_number].irq, "Serial (UART)")
      != STORM_RETURN_SUCCESS)
  {
    log_print_formatted (&log_structure, LOG_URGENCY_EMERGENCY,
               "Could not allocate IRQ %d.", serial_port[port_number].irq);
    return;
  }

  while (TRUE)
  {
    system_call_irq_wait (serial_port[port_number].irq);
    handle_irq (port_number);
    system_call_irq_acknowledge (serial_port[port_number].irq);
  }
}
Esempio n. 4
0
void handle_connection(mailbox_id_type *reply_mailbox_id)
{
    system_thread_name_set("Handling connection");

    message_parameter_type message_parameter;
    bool done = FALSE;
    bool mounted = FALSE;
    fat_info_type fat_info;
    ipc_structure_type ipc_structure;
    uint8_t *data;
    uint8_t **data_pointer = &data;
    unsigned int data_size = 16384;

    memory_allocate((void **) data_pointer, data_size);

    // Accept the connection.
    ipc_structure.output_mailbox_id = *reply_mailbox_id;
    if (ipc_connection_establish(&ipc_structure) != IPC_RETURN_SUCCESS)
    {
        return;
    }

    message_parameter.block = TRUE;

    while (!done)
    {
        message_parameter.data = data;
        message_parameter.protocol = IPC_PROTOCOL_FILE;
        message_parameter.message_class = IPC_CLASS_NONE;
        message_parameter.length = data_size;

        if (ipc_receive(ipc_structure.input_mailbox_id, &message_parameter, &data_size) != IPC_RETURN_SUCCESS)
        {
            continue;
        }

        switch (message_parameter.message_class)
        {
            // Read one or more directory entries.
            case IPC_FILE_DIRECTORY_ENTRY_READ:
            {
                if (mounted)
                {
                    file_directory_entry_read_type *directory_entry_read = (file_directory_entry_read_type *) data;

                    if (!fat_directory_entry_read(directory_entry_read, &fat_info))
                    {
                        directory_entry_read->entries = 0;
                    }
                    message_parameter.length =
                        sizeof(file_directory_entry_read_type) +
                        sizeof(file_directory_entry_type) *
                        directory_entry_read->entries ;
                    //          log_print_formatted (0, PACKAGE, "Successfully read %u entries",
                    //                               directory_entry_read->entries);
                    //          log_print_formatted (0, PACKAGE, "max: %u\n", directory_entry_read->entries);
                    ipc_send(ipc_structure.output_mailbox_id, &message_parameter);
                }
                break;
            }

            case IPC_FILE_GET_INFO:
            {
                if (mounted)
                {
                    file_verbose_directory_entry_type *directory_entry = (file_verbose_directory_entry_type *) data;

                    if (!fat_file_get_info(&fat_info, directory_entry))
                    {
                        return_type return_value = FILE_RETURN_FILE_ABSENT;

                        log_print_formatted(&log_structure, LOG_URGENCY_ERROR, "IPC_FILE_GET_INFO failed");
                        message_parameter.message_class = IPC_FILE_RETURN_VALUE;
                        message_parameter.data = &return_value;
                        message_parameter.length = sizeof(return_type);
                    }

                    ipc_send(ipc_structure.output_mailbox_id, &message_parameter);
                }
                break;
            }

            case IPC_FILE_MOUNT_VOLUME:
            {
                mailbox_id_type *mailbox = (mailbox_id_type *) data;

                fat_info.block_structure.output_mailbox_id = *mailbox;
                if (ipc_service_connection_request(&fat_info.block_structure) != IPC_RETURN_SUCCESS)
                {
                    break;
                }

                // Check if we have a FAT file system at this location.
                if (!detect_fat(&fat_info))
                {
                    log_print(&log_structure, LOG_URGENCY_ERROR, "No FAT filesystem detected.");
                    break;
                }

                mounted = TRUE;

                break;
            }

            case IPC_FILE_OPEN:
            {
                ipc_file_open_type *open = (ipc_file_open_type *) data;

                if (!fat_file_open(&fat_info, open))
                {
                    log_print(&log_structure, LOG_URGENCY_ERROR, "Failed to open file.");
                }

                ipc_send(ipc_structure.output_mailbox_id, &message_parameter);

                break;
            }

            case IPC_FILE_READ:
            {
                file_read_type *read = (file_read_type *) data;
                uint8_t *read_buffer;
                uint8_t **read_buffer_pointer = &read_buffer;

                memory_allocate((void **) read_buffer_pointer, read->bytes);

                if (!fat_file_read(&fat_info, read->file_handle, read_buffer, read->bytes))
                {
                    log_print(&log_structure, LOG_URGENCY_ERROR, "Failed to read from file.");
                }

                message_parameter.data = read_buffer;
                message_parameter.length = read->bytes;
#ifdef DEBUG
                log_print_formatted(&log_structure, LOG_URGENCY_DEBUG, "Sending %lu", read->bytes);
#endif
                ipc_send(ipc_structure.output_mailbox_id, &message_parameter);
                memory_deallocate((void **) read_buffer_pointer);
                break;
            }

            // Unsupported functions.
            case IPC_FILE_CLOSE:
            case IPC_FILE_SEEK:
            case IPC_FILE_WRITE:
            case IPC_FILE_ACL_READ:
            case IPC_FILE_ACL_WRITE:
            case IPC_FILE_UNMOUNT_VOLUME:
            default:
            {
                return_type return_value = IPC_RETURN_FILE_FUNCTION_UNSUPPORTED;

                message_parameter.data = &return_value;
                message_parameter.length = sizeof(return_type);

                ipc_send(ipc_structure.output_mailbox_id, &message_parameter);
                break;
            }
        }
    }
}
Esempio n. 5
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. 6
0
static void hard_drive_handle_connection (ata_drive_type *ata_drive, 
                                          mailbox_id_type reply_mailbox_id)
{
  message_parameter_type message_parameter;
  ipc_structure_type ipc_structure;
  bool done = FALSE;
  u32 *data;
  unsigned int data_size = 1024;

  memory_allocate ((void **) &data, data_size);

  /* Accept the connection. */ 

  ipc_structure.output_mailbox_id = reply_mailbox_id;
  ipc_connection_establish (&ipc_structure);

  message_parameter.block = TRUE;

  while (!done)
  {
    message_parameter.protocol = IPC_PROTOCOL_BLOCK;
    message_parameter.message_class = IPC_CLASS_NONE;
    message_parameter.length = data_size;
    message_parameter.data = data;
  
    if (ipc_receive (ipc_structure.input_mailbox_id, &message_parameter,
                     &data_size) != IPC_RETURN_SUCCESS)
    {
      continue;
    }
    
    switch (message_parameter.message_class)
    {
      case IPC_BLOCK_READ:
      {
        ipc_block_read_type *ipc_block_read = (ipc_block_read_type *) data;

        /* FIXME: Do some boundary checking. */
#ifdef DEBUG
        log_print_formatted (&log_structure, LOG_URGENCY_DEBUG,
                               "Reading blocks %u-%u data.", 
                               ipc_block_read->start_block_number,
                               ipc_block_read->start_block_number +
                               ipc_block_read->number_of_blocks);
#endif
        ata_read_block (ata_drive, ipc_block_read->start_block_number,
            message_parameter.data, ipc_block_read->number_of_blocks);
        message_parameter.length = ipc_block_read->number_of_blocks;
        message_parameter.block = TRUE;
        
        ipc_send (ipc_structure.output_mailbox_id, &message_parameter);
	
        break;
      }
      
      case IPC_BLOCK_WRITE:
      {
        break;
      }
      
      case IPC_BLOCK_GET_INFO:
      {
	break;
      }
    }
  }
}
Esempio n. 7
0
static void handle_connection (ipc_structure_type *ipc_structure)
{
  message_parameter_type message_parameter;
  bool done = FALSE;
  uint8_t *data;
  unsigned int data_size = 16384;
  file_mount_type mount = { "servicefs" };

  memory_allocate ((void **) &data, data_size);

  /* Mount ourselves. */

  message_parameter.block = TRUE;
  message_parameter.data = &mount;
  message_parameter.protocol = IPC_PROTOCOL_FILE;
  message_parameter.message_class = IPC_FILE_MOUNT_VOLUME;
  message_parameter.length = sizeof (file_mount_type);
  ipc_send (ipc_structure->output_mailbox_id, &message_parameter);

  message_parameter.block = TRUE;

  while (!done)
  {
    message_parameter.data = data;
    message_parameter.protocol = IPC_PROTOCOL_FILE;
    message_parameter.message_class = IPC_CLASS_NONE;
    message_parameter.length = data_size;
    
    if (ipc_receive (ipc_structure->input_mailbox_id, &message_parameter, 
                     &data_size) != IPC_RETURN_SUCCESS)
    {
      continue;
    }
    
    switch (message_parameter.message_class)
    {
      /* Read one or more directory entries. */

      case IPC_FILE_DIRECTORY_ENTRY_READ:
      {
        file_directory_entry_read_type *directory_entry_read = 
          (file_directory_entry_read_type *) data;
        service_protocol_type *protocol_info;
        unsigned int protocols = 50;
        unsigned int output_index = 0;
        unsigned int max_entries = directory_entry_read->entries;
        unsigned int input_index;
        char *path[10];
        unsigned int elements = 10;

        path_split (directory_entry_read->path_name, path, 
                    &elements);
        
        log_print_formatted (&log_structure, LOG_URGENCY_DEBUG,
                             "%u", elements);
        
        /* TODO: Do something more with the path array here. */

        directory_entry_read->entries = 0;

        memory_allocate ((void **) &protocol_info, 
                         protocols * sizeof (service_protocol_type));
        system_call_service_protocol_get (&protocols, protocol_info);

        for (input_index = directory_entry_read->start_entry;
             input_index < (directory_entry_read->start_entry + max_entries) &&
               input_index < protocols; input_index++)
        {
          string_copy 
            (directory_entry_read->entry[output_index].name,
             protocol_info[input_index].name);
          directory_entry_read->entry[output_index].type = 
            FILE_ENTRY_TYPE_DIRECTORY;
          directory_entry_read->entries++;
          output_index++;
        }
        
        if (input_index == protocols)
        {
          directory_entry_read->end_reached = TRUE;
        }
        else
        {
          directory_entry_read->end_reached = FALSE;
        }
        
        message_parameter.length = (sizeof (file_directory_entry_read_type) +
                                    sizeof (file_directory_entry_type) *
                                    directory_entry_read->entries);
        ipc_send (ipc_structure->output_mailbox_id, &message_parameter);
        break;
      }

      /* Get verbose information about the given file entry. */

      case IPC_FILE_GET_INFO:
      {
        file_verbose_directory_entry_type *verbose_directory_entry =
          (file_verbose_directory_entry_type *) data;
        unsigned int protocols = 50;
        unsigned int index;
        service_protocol_type *protocol_info;

        memory_allocate ((void **) &protocol_info, 
                         protocols * sizeof (service_protocol_type));
        system_call_service_protocol_get (&protocols, protocol_info);

        verbose_directory_entry->success = FALSE;
            
        for (index = 0; index < protocols; index++)
        {
          if (string_length (verbose_directory_entry->path_name) > 1 &&
              string_compare (protocol_info[index].name, 
                              verbose_directory_entry->path_name + 1) == 0)
          {
            verbose_directory_entry->success = TRUE;
            verbose_directory_entry->type = FILE_ENTRY_TYPE_DIRECTORY;
            verbose_directory_entry->time = time_get ();
            verbose_directory_entry->size = 
              protocol_info[index].number_of_services;
            break;
          }
        }

        message_parameter.length = sizeof (file_verbose_directory_entry_type);
        ipc_send (ipc_structure->output_mailbox_id, &message_parameter);

        break;
      }

      /* Unsupported functions. */

      case IPC_FILE_OPEN:
        
        /* FIXME: For READ, we first create a buffer, fills it with
           the content of the 'file' and then pass the requested part
           of the file to the caller. */

      case IPC_FILE_READ:
      case IPC_FILE_CLOSE:
      case IPC_FILE_SEEK:
      case IPC_FILE_WRITE:
      case IPC_FILE_ACL_READ:
      case IPC_FILE_ACL_WRITE:
      case IPC_FILE_MOUNT_VOLUME:
      case IPC_FILE_UNMOUNT_VOLUME:
      default:
      {
        return_type return_value = IPC_RETURN_FILE_FUNCTION_UNSUPPORTED;

        message_parameter.data = &return_value;
        message_parameter.length = sizeof (return_type);

        ipc_send (ipc_structure->output_mailbox_id, &message_parameter);
        break;
      }
    }
  }
}
Esempio n. 8
0
File: boot.c Progetto: vladsor/chaos
int main (void)
{
#if FALSE
  virtual_file_system_mount_type mount;
  mailbox_id_type mailbox_id[10];
  ipc_structure_type vfs_structure;
  message_parameter_type message_parameter;
  file_read_type read;
  file_handle_type handle;
  file_verbose_directory_entry_type directory_entry;
  u8 *buffer;
  u8 *server_name_buffer;
  char *server[MAX_SERVERS];
  unsigned int where, number_of_servers = 0, server_number;
  process_id_type process_id;
  unsigned int bytes_read;
  unsigned int services = 10;
#endif

  /* Set our name. */

  system_process_name_set (PACKAGE_NAME);
  system_thread_name_set ("Initialising");

  if (log_init (&log_structure, PACKAGE_NAME, &empty_tag) !=
      LOG_RETURN_SUCCESS)
  {
    return -1;
  }

#if FALSE

  /* Mount the initial ramdisk as //ramdisk. To do this, we must first
     hook up a connection to the VFS service and resolve the first
     block service. */
    
  if (ipc_service_resolve ("virtual_file_system", mailbox_id, &services, 5, 
                           &empty_tag) != IPC_RETURN_SUCCESS)
  {
    log_print (&log_structure, LOG_URGENCY_EMERGENCY,
               "Couldn't resolve the VFS service.");
    return -1;
  }

  vfs_structure.output_mailbox_id = mailbox_id[0];

  if (ipc_service_connection_request (&vfs_structure) != IPC_RETURN_SUCCESS)
  {
    log_print (&log_structure, LOG_URGENCY_EMERGENCY,
               "Couldn't connect to the VFS service.");
    return -1;
  }

  services = 1;

  if (ipc_service_resolve ("block", mailbox_id, &services, 5, &empty_tag) !=
      IPC_RETURN_SUCCESS)
  {
    log_print (&log_structure, LOG_URGENCY_EMERGENCY, 
               "No block services found.");
    return -1;
  }

  mount.mailbox_id = mailbox_id[0];
  string_copy (mount.location, "ramdisk");

  /* That's it. Send the message. */

  message_parameter.protocol = IPC_PROTOCOL_VIRTUAL_FILE_SYSTEM;
  message_parameter.message_class = IPC_VIRTUAL_FILE_SYSTEM_MOUNT;
  message_parameter.data = &mount;
  message_parameter.length = sizeof (virtual_file_system_mount_type);
  message_parameter.block = TRUE;
  ipc_send (vfs_structure.output_mailbox_id, &message_parameter);

  log_print (&log_structure, LOG_URGENCY_DEBUG,
             "Mounted the first available block service as //ramdisk.");

  /* Now, read the list of servers to start from here. */

  log_print (&log_structure, LOG_URGENCY_DEBUG, "Reading startup script...");
  string_copy (directory_entry.path_name, STARTUP_FILE);
  if (file_get_info (&vfs_structure, &directory_entry) != FILE_RETURN_SUCCESS)
  {
    log_print (&log_structure, LOG_URGENCY_ERROR,
               STARTUP_FILE " not found.");
    return -1;
  }

  memory_allocate ((void **) &server_name_buffer, directory_entry.size);

  file_open (&vfs_structure, STARTUP_FILE, FILE_MODE_READ, &handle);
  file_read (&vfs_structure, handle, directory_entry.size,
             &server_name_buffer);

  /* Parse the file. */

  server[0] = &server_name_buffer[0];
  number_of_servers++;

  for (where = 1; where < directory_entry.size; where++)
  {

    if (server_name_buffer[where] == '\n')
    {
      server_name_buffer[where] = '\0';
      if (where + 1 < directory_entry.size)
      {
        server[number_of_servers] = &server_name_buffer[where + 1];
        number_of_servers++;
      }
    }
  }

  log_print_formatted (&log_structure, LOG_URGENCY_DEBUG,
                       "Starting %u servers.", number_of_servers);

  for (server_number = 0; server_number < number_of_servers; server_number++)
  {
    log_print_formatted (&log_structure, LOG_URGENCY_INFORMATIVE, 
                         "Starting %s.", server[server_number]);

    string_copy (directory_entry.path_name, server[server_number]);
    if (file_get_info (&vfs_structure, &directory_entry) !=
        FILE_RETURN_SUCCESS)
    {
      log_print_formatted (&log_structure, LOG_URGENCY_ERROR,
                           "'%s' could not be accessed!",
                           server[server_number]);
      continue;
    }

    /* Open the file. */

    file_open (&vfs_structure, server[server_number], FILE_MODE_READ, &handle);
    read.file_handle = handle;
    
    bytes_read = 0;

    log_print_formatted (&log_structure, LOG_URGENCY_DEBUG,
                         "Allocating %lu bytes for %s.",
                         directory_entry.size, server[server_number]);

    memory_allocate ((void **) &buffer, directory_entry.size);

    log_print_formatted (&log_structure, LOG_URGENCY_DEBUG,
                         "Buffer is at %p.", buffer);
    
    while (bytes_read < directory_entry.size)
    {
      unsigned int bytes;

      /* Read the file. */
    
      bytes = directory_entry.size - bytes_read;
      if (bytes > 32 * KB)
      {
        bytes = 32 * KB;
      }
      file_read (&vfs_structure, handle, bytes, &buffer[bytes_read]);
      bytes_read += bytes;
    }
    
    switch (execute_elf ((elf_header_type *) buffer, "", &process_id))
    {
      case EXECUTE_ELF_RETURN_SUCCESS:
      {
        log_print_formatted (&log_structure, LOG_URGENCY_INFORMATIVE,
                             "New process ID %lu.",
                              process_id);
        break;
      }
      
      case EXECUTE_ELF_RETURN_IMAGE_INVALID:
      {
        log_print (&log_structure, LOG_URGENCY_ERROR,
                   "Invalid ELF image.");
        break;
      }
      
      case EXECUTE_ELF_RETURN_ELF_UNSUPPORTED:
      {
        log_print (&log_structure, LOG_URGENCY_ERROR,
                   "Unsupported ELF.");
        break;
      }
      
      case EXECUTE_ELF_RETURN_FAILED:
      {
        log_print (&log_structure, LOG_URGENCY_ERROR,
                   "system_process_create failed.");
        break;
      }
    }

    memory_deallocate ((void **) &buffer);
  }

#endif

  system_call_process_parent_unblock ();

  log_print (&log_structure, LOG_URGENCY_DEBUG, "surf");

  return 0;
}
Esempio n. 9
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;
}
Esempio n. 10
0
File: udp.c Progetto: vladsor/chaos
return_type udp_send 
  (void *data, unsigned int length, socket_type *socket)
{
  u8 ethernet_address[NETWORK_ETHERNET_ADDRESS_LENGTH];
  ipc_structure_type *ethernet_structure;
  bool direct;
  network_ethernet_header_type *ethernet_header;
  ipv4_interface_type *interface;
  ipv4_header_type *ipv4_header;
  udp_header_type *udp_header;
  message_parameter_type message_parameter;

  log_print (&log_structure, LOG_URGENCY_DEBUG, "Sending UDP packet...");

  if (socket->protocol_type != IPC_IPV4_PROTOCOL_UDP)
  {
    return UDP_RETURN_INVALID_ARGUMENT;
  }

  /* First, find out how we should route this packet. */

  if (!route_find (socket->destination_address, &interface, 
                   &direct, &ethernet_structure))
  {
    return UDP_RETURN_DESTINATION_UNREACHABLE;
  }

  /* Get the ethernet address of the recipient. */

  while (!arp_ip_to_ethernet_address (socket->destination_address,
                                      ethernet_address))
  {
    log_print_formatted (&log_structure, LOG_URGENCY_DEBUG, 
                         "Sending ARP who-has for %lX on %s.", 
                         socket->destination_address,
                         interface->identification);
    arp_who_has (socket->destination_address, interface, ethernet_structure);
    system_sleep (500);
  }

  /* Now, construct the package, and send it. */

  memory_allocate ((void **) &ethernet_header, 
                   sizeof (network_ethernet_header_type) +
                   sizeof (ipv4_header_type) + sizeof (udp_header_type) +
                   length);

  ipv4_ethernet_header_create 
    (ethernet_address, interface->hardware_address,
     NETWORK_ETHERNET_PROTOCOL_IPV4, ethernet_header);

  ipv4_header = (ipv4_header_type *) &ethernet_header->data;

  ipv4_header_create (socket->destination_address, interface->ip_address,
                      IP_PROTOCOL_UDP, sizeof (udp_header_type) + length,
                      ipv4_header);

  udp_header = (udp_header_type *) &ipv4_header->data;
  udp_header_create (socket->destination_port, socket->source_port,
                     length, udp_header);
  memory_copy (&udp_header->data, data, length);

  message_parameter.protocol = IPC_PROTOCOL_ETHERNET;
  message_parameter.message_class = IPC_ETHERNET_PACKET_SEND;
  message_parameter.data = ethernet_header;
  message_parameter.length = (sizeof (network_ethernet_header_type) + 
                              sizeof (ipv4_header_type) + 
                              sizeof (udp_header_type) + length);

  ipc_send (ethernet_structure->output_mailbox_id, &message_parameter);
  
  return UDP_RETURN_SUCCESS;
}
Esempio n. 11
0
static void handle_8139 (pci_device_info_type *device_info)
{
  unsigned int counter;
  u16 port_base = MAX_U16;
  u16 ports = 0;
  realtek_device_type *device;
  unsigned int physical, physical_index;
  ipc_structure_type ipc_structure;

  system_thread_name_set ("Initialising");
  
  for (counter = 0; counter < PCI_NUMBER_OF_RESOURCES; counter++)
  {
    if ((device_info->resource[counter].flags & PCI_RESOURCE_IO) != 0)
    {
      port_base = device_info->resource[counter].start;
      ports = (device_info->resource[counter].end -
               device_info->resource[counter].start + 1);
    }
  }

  if (port_base == MAX_U16)
  {
    log_print_formatted (&log_structure, LOG_URGENCY_ERROR, 
                         "No port range found -- hardware possibly broken or incompatible?");
    return;
  }

  system_call_port_range_register (port_base, ports, "Realtek 8139");

  memory_allocate ((void **) &device, sizeof (realtek_device_type));

  device->port_base = port_base;
  device->irq = device_info->irq;

  /* Initialise the adapter. */

  system_port_out_u8 (port_base + Config1, 0x00);
  
  if (read_eeprom (port_base, 0) != 0xFFFF) 
  {
    for (counter = 0; counter < 3; counter++) 
    {
      ((u16 *)(device->ethernet_address))[counter] =
        system_little_endian_to_native_u16 (read_eeprom (port_base, 
                                                        counter + 7));
    }
  }
  else 
  {
    for (counter = 0; counter < 6; counter++)
    {
      device->ethernet_address[counter] = 
        system_port_in_u8 (port_base + MAC0 + counter);
    }
  }

  log_print_formatted 
    (&log_structure, LOG_URGENCY_INFORMATIVE,
     "Realtek 8139 at 0x%X, IRQ %d, ethernet address: %02X:%02X:%02X:%02X:%02X:%02X",
     port_base, device_info->irq, device->ethernet_address[0], 
     device->ethernet_address[1], device->ethernet_address[2], 
     device->ethernet_address[3], device->ethernet_address[4],
     device->ethernet_address[5]);

  /* Find the connected MII transceivers. */

  for (physical = 0, physical_index = 0; physical < 32 &&
         physical_index < sizeof (device->mii_address); physical++)
  {
    int mii_status = mdio_read (port_base, physical, 1);

    if (mii_status != 0xFFFF && mii_status != 0x0000) 
    {
      device->mii_address[physical_index] = physical;
      physical_index++;

      log_print_formatted (&log_structure, LOG_URGENCY_INFORMATIVE,
                           "MII transceiver found at address %d.",
                           physical);
    }
  }

  if (physical_index == 0) 
  {
    if (realtek_debug > 1)
    {
      log_print_formatted (&log_structure, LOG_URGENCY_INFORMATIVE,
                           "No MII transceivers found! Assuming SYM "
                           "transceiver.");
    }

    device->mii_address[0] = -1;
  }

  /* Soft reset the chip. */

  system_port_out_u8 (port_base + ChipCommand, CommandReset);

  pci_allocate_buffer ((void **) &device->tx_buffers_dma,
                       (void **) &device->tx_buffers,
                       TX_BUFFER_SIZE * NUMBER_OF_TX_DESCRIPTORS);
  pci_allocate_buffer ((void **) &device->rx_ring_dma,
                       (void **) &device->rx_ring,
                       RX_BUFFER_LENGTH + 16);

  device->tx_full = FALSE;
  device->current_rx = 0;
  device->dirty_tx = device->current_tx = 0;

  for (counter = 0; counter < NUMBER_OF_TX_DESCRIPTORS; counter++) 
  {
    device->tx_buffer[counter] = &device->tx_buffers[counter * TX_BUFFER_SIZE];
  }
  
  /* Check that the chip has finished the reset. */

  for (counter = 0; counter < 1000; counter++)
  {
    if ((system_port_in_u8 (port_base + ChipCommand) & CommandReset) == 0)
    {
      break;
    }
  }

  /* Must enable Tx/Rx before setting transfer thresholds! */

  system_port_out_u8 (port_base + ChipCommand, 
                      CommandRxEnable | CommandTxEnable);
  system_port_out_u32 (port_base + RxConfig, 
                       (RX_FIFO_THRESHOLD << 13) | 
                       (RX_BUFFER_LENGTH_INDEX << 11) | 
                       (RX_DMA_BURST << 8));

  system_port_out_u32 (port_base + TxConfig, (TX_DMA_BURST << 8) | 0x03000000);

  if (device->mii_address[0] >= 0) 
  {
    u16 mii_reg5 = mdio_read (port_base, device->mii_address[0], 5);

    if (mii_reg5 == 0xffff)
    {
    }
    else if ((mii_reg5 & 0x0100) == 0x0100 || (mii_reg5 & 0x00C0) == 0x0040)
    {
      device->full_duplex = TRUE;
    }

    log_print_formatted (&log_structure, LOG_URGENCY_INFORMATIVE,
                         "Setting %s%s-duplex based on"
                         " auto-negotiated partner ability %4.4x.\n",
                         mii_reg5 == 0 ? "" :
                         ((mii_reg5 & 0x0180) != 0) ? "100 Mbps " : 
                         "10 Mbps ",
                         device->full_duplex ? "full" : "half", mii_reg5);
  }
  
  system_port_out_u8 (port_base + Config9346, 0xC0);
  system_port_out_u8 (port_base + Config1, device->full_duplex ? 0x60 : 0x20);
  system_port_out_u8 (port_base + Config9346, 0x00);

  system_port_out_u32 (port_base + RxBuffer, (u32) device->rx_ring_dma);
  
  /* Start the chip's Tx and Rx process. */
  
  system_port_out_u32 (port_base + RxMissed, 0);
  set_rx_mode (device);
  
  system_port_out_u8 (port_base + ChipCommand,
                      CommandRxEnable | CommandTxEnable);
  
  /* Enable all known interrupts by setting the interrupt mask. */
  
  system_port_out_u16 (port_base + InterruptMask,
                       PCIError | PCSTimeout | RxUnderrun | RxOverflow | 
                       RxFIFOOverrun | TxError | TxOK | RxError | RxOK);


  if (system_thread_create () == SYSTEM_RETURN_THREAD_NEW)
  {
    system_thread_name_set ("IRQ handler");

    if (system_call_irq_register (device_info->irq, "Realtek 8139") != 
        SYSTEM_RETURN_SUCCESS)
    {
      log_print_formatted (&log_structure, LOG_URGENCY_EMERGENCY, 
                           "Couldn't set up IRQ handler");
      return;
    }

    /* Loop and handle interrupts. */
    
    while (TRUE)
    {
      int bogus_count = max_interrupt_work;
      unsigned status, link_changed = 0;
      
      system_call_irq_wait (device->irq);
      
      do 
      {
        status = system_port_in_u16 (port_base + InterruptStatus);
        
        /* Acknowledge all of the current interrupt sources ASAP, but
           an first get an additional status bit from CSCR. */
        
        if ((status & RxUnderrun) && 
            system_port_in_u16 (port_base + CSCR) & CSCR_LinkChangeBit)
        {
          link_changed = 1;
        }
        
        system_port_out_u16 (port_base + InterruptStatus, status);
        
        if ((status & (PCIError | PCSTimeout | RxUnderrun | RxOverflow | 
                       RxFIFOOverrun | TxError | TxOK | RxError | RxOK)) == 0)
        {
          break;
        }
        
        /* Rx interrupt. */
        
        if ((status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOverrun)) != 0)
        {
          realtek_receive (device);
        }
        
        if ((status & (TxOK | TxError)) != 0) 
        {
          unsigned int dirty_tx = device->dirty_tx;
          
          while (device->current_tx - dirty_tx > 0) 
          {
            int entry = dirty_tx % NUMBER_OF_TX_DESCRIPTORS;
            int txstatus = system_port_in_u32 (port_base + TxStatus0 +
                                               entry * 4);
            
            if ((txstatus & (TxStatusOK | TxUnderrun | TxAborted)) == 0)
            {
              /* It still hasn't been transmitted. */
              
              break;
            }
            
            /* Note: TxCarrierLost is always asserted at 100 Mbps. */
            
            if ((txstatus & (TxOutOfWindow | TxAborted)) != 0)
            {
              /* There was an major error, log it. */
              
              // device->stats.tx_errors++;

              if ((txstatus & TxAborted) != 0)
              {
                // tp->stats.tx_aborted_errors++;

                system_port_out_u32 (port_base + TxConfig, 
                                     (TX_DMA_BURST << 8) | 0x03000001);
              }
              
              if ((txstatus & TxCarrierLost) != 0)
              {
                // tp->stats.tx_carrier_errors++;
              }
              
              if ((txstatus & TxOutOfWindow) != 0)
              {
                // tp->stats.tx_window_errors++;
              }
            }
            else 
            {
              if ((txstatus & TxUnderrun) != 0)
              {
                /* Add 64 to the Tx FIFO threshold. */
                
                if (device->tx_flag < 0x00300000)
                {
                  device->tx_flag += 0x00020000;
                }
                
                // tp->stats.tx_fifo_errors++;
              }
              
              // tp->stats.collisions += (txstatus >> 24) & 15;
              // tp->stats.tx_bytes += txstatus & 0x7ff;
              // tp->stats.tx_packets++;
            }
            
            // if (tp->tx_info[entry].mapping != 0)
            // {
            //   pci_unmap_single (tp->pdev,
            //                     tp->tx_info[entry].mapping,
            //                     tp->tx_info[entry].skb->len,
            //                     PCI_DMA_TODEVICE);
            // tp->tx_info[entry].mapping = 0;
            // }
          
            /* Free the original skb. */
            
            // dev_kfree_skb_irq (tp->tx_info[entry].skb);
            //          tp->tx_info[entry].skb = NULL;
            
            if (device->tx_full) 
            {
              /* The ring is no longer full, wake the queue. */
              
              device->tx_full = FALSE;
              
              // netif_wake_queue(dev);
            }
            
            dirty_tx++;
          }
          
          device->dirty_tx = dirty_tx;
        }
        
        /* Check uncommon events with one test. */
        
        if ((status & (PCIError | PCSTimeout | RxUnderrun | RxOverflow | 
                       RxFIFOOverrun | TxError | RxError)) != 0)
        {
          if (realtek_debug > 2)
          {
            log_print_formatted (&log_structure, LOG_URGENCY_WARNING,
                                 "Abnormal interrupt, status %8.8x.\n",
                                 status);
          }
          
          if (status == 0xFFFFFFFF)
          {
            break;
          }
          
          /* Update the error count. */
          
          // tp->stats.rx_missed_errors += inl(port_base + RxMissed);
          system_port_out_u32 (port_base + RxMissed, 0);
          
          if ((status & RxUnderrun) != 0 && link_changed)
          {
            /* Really link-change on new chips. */
            
            int lpar = system_port_in_u16 (port_base + NWayLPAR);
            int duplex = (lpar & 0x0100) || (lpar & 0x01C0) == 0x0040; 
            
            if (device->full_duplex != duplex) 
            {
              device->full_duplex = duplex;
              
              system_port_out_u8 (port_base + Config9346, 0xC0);
              system_port_out_u8 (port_base + Config1, 
                                  device->full_duplex ? 0x60 : 0x20);
              system_port_out_u8 (port_base + Config9346, 0x00);
            }
            status &= ~RxUnderrun;
          }
          
          if ((status & (RxUnderrun | RxOverflow | RxError |
                         RxFIFOOverrun)) != 0)
          {
            // tp->stats.rx_errors++;
          }
          
          if ((status & (PCSTimeout)) != 0)
          {
            // tp->stats.rx_length_errors++;
          }
          
          if ((status & (RxUnderrun | RxFIFOOverrun)) != 0)
          {
            //  tp->stats.rx_fifo_errors++;
          }
          
          if ((status & RxOverflow) != 0)
          {
            // tp->stats.rx_over_errors++;
            device->current_rx =
              (system_port_in_u16 (port_base + RxBufferAddress) % 
               RX_BUFFER_LENGTH);
            system_port_out_u16 (port_base + RxBufferPointer, device->current_rx - 16);
          }
          
          if ((status & PCIError) != 0) 
          {
            log_print (&log_structure, LOG_URGENCY_WARNING, "PCI Bus error.");
          }
        }
        
        if (--bogus_count < 0) 
        {
          log_print_formatted (&log_structure, LOG_URGENCY_WARNING,
                               "Too much work at interrupt, "
                               "InterruptStatus = 0x%4.4x.",
                               status);
          
          /* Clear all interrupt sources. */
          
          system_port_out_u16 (port_base + InterruptStatus, 0xFFFF);
          break;
        }
      } while (TRUE);
      
      system_call_irq_acknowledge (device->irq);
    }
  }

  /* Now, use the remaining thread for the service handler. */

  system_thread_name_set ("Service handler");

  /* Create the service. */

  if (ipc_service_create ("ethernet", &ipc_structure, &empty_tag) !=
      IPC_RETURN_SUCCESS)
  {
    log_print (&log_structure, LOG_URGENCY_EMERGENCY,
               "Couldn't create ethernet service.");
    return;
  }

  while (TRUE)
  {
    mailbox_id_type reply_mailbox_id;

    ipc_service_connection_wait (&ipc_structure);
    reply_mailbox_id = ipc_structure.output_mailbox_id;

    if (system_thread_create () == SYSTEM_RETURN_THREAD_NEW)
    {
      system_call_thread_name_set ("Handling connection");
      handle_connection (reply_mailbox_id, device);
    }
  }    
}
Esempio n. 12
0
static int realtek_receive (realtek_device_type *device)
{
  long io_address = device->port_base;
  unsigned char *rx_ring = device->rx_ring;
  u16 current_rx = device->current_rx;
  unsigned int counter;
  
  if (realtek_debug > 4)
  {
    log_print_formatted (&log_structure, LOG_URGENCY_DEBUG, 
                         "In %s (), current %4.4x BufAddr %4.4x,"
                         " free to %4.4x, Command %2.2x.",
                         __FUNCTION__, current_rx, 
                         system_port_in_u16 (io_address + RxBufferAddress),
                         system_port_in_u16 (io_address + RxBufferPointer),
                         system_port_in_u8 (io_address + ChipCommand));
  }
  
  while ((system_port_in_u8 (io_address + ChipCommand) & 1) == 0) 
  {
    int ring_offset = current_rx % RX_BUFFER_LENGTH;
    u32 rx_status = system_little_endian_to_native_u32 
      (* (u32 *) (rx_ring + ring_offset));
    int rx_size = rx_status >> 16;
    
    if (realtek_debug > 4) 
    {
      // int i;
      log_print_formatted (&log_structure, LOG_URGENCY_DEBUG, 
                           "%s () status %lx, size %x, current %x.",
                           __FUNCTION__, rx_status, rx_size, current_rx);

      //      printk(KERN_DEBUG"%s: Frame contents ", device->name);
      //      for (i = 0; i < 70; i++)
      //      {
      //        printk(" %2.2x", le32_to_cpu(rx_ring[ring_offset + i]));
      //      printk(".\n");
    }

    if ((rx_status & RxTooLong) != 0)
    {
      if (realtek_debug > 0)
      {
        log_print_formatted (&log_structure, LOG_URGENCY_WARNING,
                             "Oversized Ethernet frame, status %lx!",
                             rx_status);
      }

      // tp->stats.rx_length_errors++;
    }
    else if ((rx_status & (RxBadSymbol | RxRunt | RxTooLong | RxCRCError | 
                           RxBadAlign)) != 0)
    {
      if (realtek_debug > 1)
      {
        log_print_formatted (&log_structure, LOG_URGENCY_WARNING, 
                             "Ethernet frame had errors,"
                             " status %lx.", rx_status);
      }

      // tp->stats.rx_errors++;

      if ((rx_status & (RxBadSymbol | RxBadAlign)) != 0)
      {
        // tp->stats.rx_frame_errors++;
      }

      if ((rx_status & (RxRunt | RxTooLong)) != 0)
      {
        // tp->stats.rx_length_errors++;
      }

      if (rx_status & RxCRCError) 
      {
        // tp->stats.rx_crc_errors++;
      }

      /* Reset the receiver, based on RealTek recommendation. (Bug?) */

      device->current_rx = 0;
      system_port_out_u8 (io_address + ChipCommand, CommandTxEnable);
      system_port_out_u8 (io_address + ChipCommand, CommandRxEnable |
                          CommandTxEnable);
      system_port_out_u32 (io_address + RxConfig, (RX_FIFO_THRESHOLD << 13) |
                           (RX_BUFFER_LENGTH_INDEX << 11) | (RX_DMA_BURST << 8));
    }
    else 
    {
      u8 *data;
      
      memory_allocate ((void **) &data, rx_size);

      if (ring_offset + rx_size + 4 > RX_BUFFER_LENGTH)
      {
        int semi_count = RX_BUFFER_LENGTH - ring_offset - 4;
       
        memory_copy (data, &rx_ring[ring_offset + 4],
                     semi_count);
        memory_copy (&data[semi_count], rx_ring,
                     rx_size - semi_count);

        if (realtek_debug > 4) 
        {
          log_print_formatted (&log_structure, LOG_URGENCY_DEBUG,
                               "Frame wrap @%d.", semi_count);
          memory_set_u8 (rx_ring, 0xCC, 16);
        }
      } 
      else 
      {
        memory_copy (data, &rx_ring[ring_offset + 4], rx_size);
      }

      /* Check if this packet should be delivered somewhere. */
      
      for (counter = 0; counter < device->number_of_targets; counter++)
      {          
        if (device->target[counter].protocol_type ==
            ((network_ethernet_header_type *) data)->protocol_type)
        {
          message_parameter_type message_parameter;
          
          message_parameter.protocol = IPC_PROTOCOL_ETHERNET;
          message_parameter.message_class = IPC_ETHERNET_PACKET_RECEIVED;
          message_parameter.length = rx_size;
          message_parameter.block = FALSE;
          message_parameter.data = data;
          
          if (realtek_debug > 2)
          {
            log_print_formatted (&log_structure, LOG_URGENCY_DEBUG, 
                                 "Sending to mailbox ID %u", 
                                 device->target[counter].mailbox_id);
          }
          
          ipc_send (device->target[counter].mailbox_id, &message_parameter);
          break;
        }
      }

      // memory_deallocate ((void **) &data);

#if LINUX_VERSION_CODE > 0x20119
      // tp->stats.rx_bytes += rx_size;
#endif
      // tp->stats.rx_packets++;
    }
    
    current_rx = (current_rx + rx_size + 4 + 3) & ~3;
    system_port_out_u16 (io_address + RxBufferPointer, current_rx - 16);
  }

  if (realtek_debug > 4)
  {
    log_print_formatted (&log_structure, LOG_URGENCY_DEBUG, 
                         "Done %s (), current %4.4x BufferAddress %4.4x,"
                         " free to %4.4x, Command %2.2x.\n",
                         __FUNCTION__, current_rx,
                         system_port_in_u16 (io_address + RxBufferAddress),
                         system_port_in_u16 (io_address + RxBufferPointer), 
                         system_port_in_u8 (io_address + ChipCommand));
  }

  device->current_rx = current_rx;

  return 0;
}