⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_mahwah.c

📁 Intel XScale PXA255 引导Linux的Redboot 版bootloader源代码!
💻 C
📖 第 1 页 / 共 5 页
字号:
    ioaddr = p_i82559->io_address;      // get device I/O address    if ( p_i82559->tx_queue_full ) {#ifdef KEEP_STATISTICS        statistics[p_i82559->index].tx_dropped++;#endif#ifdef DEBUG_82559        os_printf( "i82559_send: Queue full, device %x, key %x\n",                   p_i82559, key );#endif    }    else {        struct eth_drv_sg *last_sg;        volatile cyg_uint8 *to_p;        tx_descriptor_add = p_i82559->tx_descriptor_add;        p_i82559->tx_keys[tx_descriptor_add] = key;        p_txcb = p_i82559->tx_ring[tx_descriptor_add];        CYG_ASSERT( (cyg_uint8 *)p_txcb >= i82559_heap_base, "txcb under" );        CYG_ASSERT( (cyg_uint8 *)p_txcb <  i82559_heap_free, "txcb over" );        p_txcb->txstatus = 0;        p_txcb->command = TxCB_CMD_TRANSMIT | TxCB_CMD_S                                | TxCB_CMD_I | TxCB_CMD_EL;        p_txcb->link = VIRT_TO_BUS((cyg_uint32)p_txcb);        p_txcb->tbd_address = 0xFFFFFFFF;        p_txcb->tbd_number = 0;        p_txcb->tx_threshold = 16;        p_txcb->eof = 1;        p_txcb->count = total_len;        // Copy from the sglist into the txcb        to_p = &p_txcb->buffer[0];        CYG_ASSERT( 0 < sg_len, "sg_len underflow" );        CYG_ASSERT( MAX_ETH_DRV_SG >= sg_len, "sg_len overflow" );        for ( last_sg = &sg_list[sg_len]; sg_list < last_sg; sg_list++ ) {            cyg_uint8 *from_p;            int l;                        from_p = (cyg_uint8 *)(sg_list->buf);            l = sg_list->len;            if ( l > total_len )                l = total_len;            memcpy( (unsigned char *)to_p, from_p, l );            to_p += l;            total_len -= l;            if ( 0 > total_len )                 break; // Should exit via sg_last normally        }        CYG_ASSERT( 0 == total_len, "length mismatch in tx" );        CYG_ASSERT( last_sg == sg_list, "sg count mismatch in tx" );        CYG_ASSERT( &p_txcb->buffer[0] < to_p, "to_p wild in tx" );        CYG_ASSERT( &p_txcb->buffer[0] + MAX_TX_PACKET_SIZE >= to_p,                    "to_p overflow in tx" );          // Next descriptor        if ( ++tx_descriptor_add >= MAX_TX_DESCRIPTORS)            tx_descriptor_add = 0;        p_i82559->tx_descriptor_add = tx_descriptor_add;        // From this instant, interrupts can advance the world and start,        // even complete, this tx request...        if ( p_i82559->tx_descriptor_remove == tx_descriptor_add )            p_i82559->tx_queue_full = 1;    }    // Try advancing the Tx Machine regardless    // no more interrupts until started    ints = Mask82559Interrupt(p_i82559);    // Check that either:    //     tx is already active, there is other stuff queued,    // OR  this tx just added is the current active one    // OR  this tx just added is already complete    CYG_ASSERT(        // The machine is busy:        (p_i82559->tx_in_progress == 1) ||        // or: The machine is idle and this just added is the next one        (((p_i82559->tx_descriptor_add-1) == p_i82559->tx_descriptor_active)         || ((0 == p_i82559->tx_descriptor_add) &&             ((MAX_TX_DESCRIPTORS-1) == p_i82559->tx_descriptor_active))) ||        // or: This tx is already complete        (p_i82559->tx_descriptor_add == p_i82559->tx_descriptor_active),                "Active/add mismatch" );    // Advance TxMachine atomically    TxMachine(p_i82559);    Acknowledge82559Interrupt(p_i82559); // This can eat an Rx interrupt, so    PacketRxReady(p_i82559);    UnMask82559Interrupt(p_i82559, ints);}// ------------------------------------------------------------------------////  Function : i82559_reset//// ------------------------------------------------------------------------static void i82559_reset(struct i82559* p_i82559){    cyg_uint32 ioaddr;    int count;    ioaddr = p_i82559->io_address;    // make sure no command operating    wait_for_cmd_done(ioaddr);        OUTL(I82559_SELECTIVE_RESET, ioaddr + SCBPort);      for (count = 10 ; count-- ; ) {        udelay(1000);    }    OUTL(I82559_RESET, ioaddr + SCBPort);        for (count = 10 ; count-- ; ) {      udelay(1000);    }}// ------------------------------------------------------------------------////                       INTERRUPT HANDLERS//// ------------------------------------------------------------------------static cyg_uint32 eth_isr(cyg_vector_t vector, cyg_addrword_t data){    struct i82559* p_i82559 = (struct i82559 *)data;    cyg_uint16 status;    cyg_uint32 ioaddr;    IF_BAD_82559( p_i82559 ) {#ifdef DEBUG        os_printf( "i82559_isr: Bad device pointer %x\n", p_i82559 );#endif        return 0;    }    ioaddr = p_i82559->io_address;    status = INW(ioaddr + SCBStatus);    // Acknowledge all INT sources that were active    OUTW( status & SCB_INTACK_MASK, ioaddr + SCBStatus);    // (see pages 6-10 & 6-90)#ifdef KEEP_STATISTICS    statistics[p_i82559->index].interrupts++;    // receiver left ready state ?    if ( status & SCB_STATUS_RNR )        statistics[p_i82559->index].rx_resource++;    // frame receive interrupt ?    if ( status & SCB_STATUS_FR )        statistics[p_i82559->index].rx_count++;    // transmit interrupt ?    if ( status & SCB_STATUS_CX )        statistics[p_i82559->index].tx_complete++;#endif    // Advance the Tx Machine regardless    TxMachine(p_i82559);    // it should have settled down now...    Acknowledge82559Interrupt(p_i82559);    return CYG_ISR_CALL_DSR;        // schedule DSR}// ------------------------------------------------------------------------static int mux_device_index = 0;static cyg_uint32 eth_mux_isr(cyg_vector_t vector, cyg_addrword_t data){    int device_index = mux_device_index;    struct i82559* p_i82559;    mux_device_index ^= 1; // look at the other one first next time.    do {        p_i82559 = &i82559[device_index];        if ( p_i82559->active )            (void)eth_isr( vector, (cyg_addrword_t)p_i82559 );        device_index ^= 1;    } while ( device_index == mux_device_index );    return CYG_ISR_CALL_DSR;}// ------------------------------------------------------------------------static void eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){    struct i82559* p_i82559 = (struct i82559 *)data;    struct cyg_netdevtab_entry *ndp =        (struct cyg_netdevtab_entry *)(p_i82559->ndp);    struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance);    // but here, it must be a *sc:    eth_drv_dsr( vector, count, (cyg_addrword_t)sc );}// ------------------------------------------------------------------------// This is called from the function below (used to be uni-DSR)static inline voiduni_deliver(struct i82559* p_i82559){    // First pass any rx data up the stack    PacketRxReady(p_i82559);    // Then scan for completed Txen and inform the stack    TxDone(p_i82559);}// ------------------------------------------------------------------------void i82559_deliver(struct eth_drv_sc *sc){    struct i82559* p_i82559;    int device_index = mux_device_index;    // Since this must mux both devices, the incoming arg is ignored.    mux_device_index ^= 1; // look at the other one first next time.    do {        p_i82559 = &i82559[device_index];        if ( p_i82559->active )            uni_deliver( p_i82559 );        device_index ^= 1;    } while ( device_index == mux_device_index );}// ------------------------------------------------------------------------// Device table entry to operate the chip in a polled mode.// Only diddle the interface we were asked to!void i82559_poll(struct eth_drv_sc *sc){    struct i82559 *p_i82559;    int ints;    p_i82559 = (struct i82559 *)sc->driver_private;        IF_BAD_82559( p_i82559 ) {#ifdef DEBUG        os_printf( "i82559_poll: Bad device pointer %x\n", p_i82559 );#endif        return;    }    // Do these atomically    ints = Mask82559Interrupt(p_i82559);    // As it happens, this driver always requests the DSR to be called:    (void)eth_isr( CYGNUM_HAL_INTERRUPT_PCI_IRQ, (cyg_addrword_t)p_i82559 );    // (no harm in calling this ints-off also, when polled)    uni_deliver( p_i82559 );    Acknowledge82559Interrupt(p_i82559);    UnMask82559Interrupt(p_i82559, ints);}// ------------------------------------------------------------------------// Determine interrupt vector used by a device - for attaching GDB stubs// packet handler.inti82559_int_vector(struct eth_drv_sc *sc){    struct i82559 *p_i82559;    p_i82559 = (struct i82559 *)sc->driver_private;    return (p_i82559->vector);}#if 0inti82559_int_op( struct eth_drv_sc *sc, int mask){    struct i82559 *p_i82559;    p_i82559 = (struct i82559 *)sc->driver_private;    if ( 1 == mask )        return Mask82559Interrupt( p_i82559 );    if ( 0 == mask )        UnMask82559Interrupt( p_i82559, 0x0fffffff ); // enable all    return 0;}#endif    // ------------------------------------------------------------------------////  Function : pci_init_find_82559s//// This is called exactly once at the start of time to://  o scan the PCI bus for objects//  o record them in the device table//  o acquire all the info needed for the driver to access them//  o instantiate interrupts for them//  o attach those interrupts appropriately// ------------------------------------------------------------------------static intpci_init_find_82559s( void ){    cyg_pci_device_id devid;    cyg_pci_device dev_info;    cyg_uint16 cmd;    int device_index;    // MUX interrupt - special case when 2 cards share one intr.    static cyg_handle_t mux_interrupt_handle = 0;    static cyg_interrupt mux_interrupt_object;#ifdef DEBUG    db_printf("pci_init_find_82559s()\n");#endif    // allocate memory to be used in ioctls later    if (mem_reserved_ioctl != (void*)0) {#ifdef DEBUG        db_printf("pci_init_find_82559s() called > once\n");#endif        return 0;    }    CYG_ASSERT( CYGMEM_SECTION_pci_window ==                (char *)CYGHWR_HAL_ARM_PCI_MEM_MAP_BASE,      "PCI window configured does not match PCI memory section base" );    CYG_ASSERT( CYGMEM_SECTION_pci_window_SIZE ==                CYGHWR_HAL_ARM_PCI_MEM_MAP_SIZE,        "PCI window configured does not match PCI memory section size" );    if ( CYGMEM_SECTION_pci_window !=         (char *)CYGHWR_HAL_ARM_SA110_PCI_MEM_MAP_BASE         ||         CYGMEM_SECTION_pci_window_SIZE !=         CYGHWR_HAL_ARM_SA110_PCI_MEM_MAP_SIZE ) {#ifdef DEBUG        db_printf("pci_init_find_82559s(): PCI window misconfigured\n");#endif        return 0;    }    // First initialize the heap in PCI window'd memory    i82559_heap_size = CYGHWR_HAL_ARM_SA110_PCI_MEM_MAP_SIZE;    i82559_heap_base = (cyg_uint8 *)CYGHWR_HAL_ARM_SA110_PCI_MEM_MAP_BASE;    i82559_heap_free = i82559_heap_base;    mem_reserved_ioctl = pciwindow_mem_alloc(MAX_MEM_RESERVED_IOCTL);         cyg_pci_init();#ifdef DEBUG    db_printf("Finished cyg_pci_init();\n");#endif    devid = CYG_PCI_NULL_DEVID;    for (device_index = 0; device_index < MAX_82559; device_index++) {        struct i82559 *p_i82559 = &i82559[device_index];        p_i82559->index = device_index;        // Intel 82559 and 82557 are virtually identical, with different dev codes        if (cyg_pci_find_device(0x8086, 0x1030, &devid) ||            cyg_pci_find_device(0x8086, 0x1229, &devid) ) {#ifdef DEBUG            db_printf("eth%d = 82559\n", device_index);#endif            cyg_pci_get_device_info(devid, &dev_info);            if (cyg_pci_translate_interrupt(&dev_info, &p_i82559->vector)) {#ifdef DEBUG                db_printf(" Wired to HAL vector %d\n", p_i82559->vector);#endif		p_i82559->vector = CYGNUM_HAL_INTERRUPT_IRQ_IN_0;                diag_printf(" Wired to HAL vector %d\n", p_i82559->vector);                cyg_drv_interrupt_create(                    p_i82559->vector,                    0,                  // Priority - unused                    (CYG_ADDRWORD)p_i82559, //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -