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; }
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; }
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); } }
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; } } } }
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); } }
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; } } } }
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; } } } }
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; }
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; }
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, ðernet_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 **) ðernet_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 *) ðernet_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; }
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); } } }
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; }