static void create_hard_drive_service (ata_drive_type *ata_drive) { /* Create the service. */ if (ipc_service_create ("block", &ipc_structure, &empty_tag) != IPC_RETURN_SUCCESS) { log_print (&log_structure, LOG_URGENCY_EMERGENCY, "Couldn't create block service."); return -1; } /* Main loop. */ system_thread_name_set ("Service handler"); 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"); hard_drive_handle_connection (ata_drive, reply_mailbox_id); } } }
int main (void) { ipc_structure_type ipc_structure; mailbox_id_type mailbox_id[10]; unsigned int services = 10; 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; } /* Create our service. */ if (ipc_service_create ("file_system", &ipc_structure, &empty_tag) != STORM_RETURN_SUCCESS) { log_print (&log_structure, LOG_URGENCY_EMERGENCY, "Couldn't create a file system service."); return -1; } system_call_process_parent_unblock (); if (ipc_service_resolve ("virtual_file_system", mailbox_id, &services, 0, &empty_tag) != IPC_RETURN_SUCCESS) { log_print (&log_structure, LOG_URGENCY_EMERGENCY, "Couldn't resolve VFS service."); return -1; } ipc_structure.output_mailbox_id = mailbox_id[0]; ipc_service_connection_request (&ipc_structure); handle_connection (&ipc_structure); return 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); } } }