📄 bcm570x.c
字号:
pDevice->NoTxPseudoHdrChksum = TRUE; } } /* Set Device PCI Memory base address */ pDevice->pMappedMemBase = (PLM_UINT8) ioBase; /* Pull down adapter info */ if ((rv = LM_GetAdapterInfo(pDevice)) != LM_STATUS_SUCCESS) { printf("bcm570xEnd: LM_GetAdapterInfo failed: rv=%d!\n", rv ); return -2; } /* Lock not needed */ pUmDevice->do_global_lock = 0; if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) { /* The 5700 chip works best without interleaved register */ /* accesses on certain machines. */ pUmDevice->do_global_lock = 1; } /* Setup timer delays */ if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) { pDevice->UseTaggedStatus = TRUE; pUmDevice->timer_interval = CFG_HZ; } else { pUmDevice->timer_interval = CFG_HZ / 50; } /* Grab name .... */ pUmDevice->name = (char*)malloc(strlen(board_info[bcm570xDevices[i].board_id].name)+1); strcpy(pUmDevice->name,board_info[bcm570xDevices[i].board_id].name); memcpy(pDevice->NodeAddress, bis->bi_enetaddr, 6); LM_SetMacAddress(pDevice, bis->bi_enetaddr); /* Init queues .. */ QQ_InitQueue(&pUmDevice->rx_out_of_buf_q.Container, MAX_RX_PACKET_DESC_COUNT); pUmDevice->rx_last_cnt = pUmDevice->tx_last_cnt = 0; /* delay for 4 seconds */ pUmDevice->delayed_link_ind = (4 * CFG_HZ) / pUmDevice->timer_interval; pUmDevice->adaptive_expiry = CFG_HZ / pUmDevice->timer_interval; /* Sometimes we get spurious ints. after reset when link is down. */ /* This field tells the isr to service the int. even if there is */ /* no status block update. */ pUmDevice->adapter_just_inited = (3 * CFG_HZ) / pUmDevice->timer_interval; /* Initialize 570x */ if (LM_InitializeAdapter(pDevice) != LM_STATUS_SUCCESS) { printf("ERROR: Adapter initialization failed.\n"); return ERROR; } /* Enable chip ISR */ LM_EnableInterrupt(pDevice); /* Clear MC table */ LM_MulticastClear(pDevice); /* Enable Multicast */ LM_SetReceiveMask(pDevice, pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST); pUmDevice->opened = 1; pUmDevice->tx_full = 0; pUmDevice->tx_pkt = 0; pUmDevice->rx_pkt = 0; printf("eth%d: %s @0x%lx,", pDevice->index, pUmDevice->name, (unsigned long)ioBase); printf( "node addr "); for (i = 0; i < 6; i++) { printf("%2.2x", pDevice->NodeAddress[i]); } printf("\n"); printf("eth%d: ", pDevice->index); printf("%s with ", chip_rev[bcm570xDevices[i].board_id].name); if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID) printf("Broadcom BCM5400 Copper "); else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) printf("Broadcom BCM5401 Copper "); else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID) printf("Broadcom BCM5411 Copper "); else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID) printf("Broadcom BCM5701 Integrated Copper "); else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID) printf("Broadcom BCM5703 Integrated Copper "); else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID) printf("Broadcom BCM8002 SerDes "); else if (pDevice->EnableTbi) printf("Agilent HDMP-1636 SerDes "); else printf("Unknown "); printf("transceiver found\n"); printf("eth%d: %s, MTU: %d,", pDevice->index, pDevice->BusSpeedStr, 1500); if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) && rx_checksum[i]) printf("Rx Checksum ON\n"); else printf("Rx Checksum OFF\n"); initialized++; return 0;}/* Ethernet Interrupt service routine */voideth_isr(void){ LM_UINT32 oldtag, newtag; int i; pUmDevice->interrupt = 1; if (pDevice->UseTaggedStatus) { if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) || pUmDevice->adapter_just_inited) { MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1); oldtag = pDevice->pStatusBlkVirt->StatusTag; for (i = 0; ; i++) { pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED; LM_ServiceInterrupts(pDevice); newtag = pDevice->pStatusBlkVirt->StatusTag; if ((newtag == oldtag) || (i > 50)) { MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, newtag << 24); if (pDevice->UndiFix) { REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | 0x2); } break; } oldtag = newtag; } } } else { while (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) { unsigned int dummy; pDevice->pMemView->Mailbox.Interrupt[0].Low = 1; pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED; LM_ServiceInterrupts(pDevice); pDevice->pMemView->Mailbox.Interrupt[0].Low = 0; dummy = pDevice->pMemView->Mailbox.Interrupt[0].Low; } } /* Allocate new RX buffers */ if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) { bcm570xReplenishRxBuffers(pUmDevice); } /* Queue packets */ if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container)) { LM_QueueRxPackets(pDevice); } if (pUmDevice->tx_queued) { pUmDevice->tx_queued = 0; } if(pUmDevice->tx_full){ if(pDevice->LinkStatus != LM_STATUS_LINK_DOWN){ printf("NOTICE: tx was previously blocked, restarting MUX\n"); pUmDevice->tx_full = 0; } } pUmDevice->interrupt = 0;}inteth_send(volatile void *packet, int length){ int status = 0;#if ET_DEBUG unsigned char* ptr = (unsigned char*)packet;#endif PLM_PACKET pPacket; PUM_PACKET pUmPacket; /* Link down, return */ while(pDevice->LinkStatus == LM_STATUS_LINK_DOWN) {#if 0 printf("eth%d: link down - check cable or link partner.\n", pUmDevice->index);#endif eth_isr(); /* Wait to see link for one-half a second before sending ... */ udelay(1500000); } /* Clear sent flag */ pUmDevice->tx_pkt = 0; /* Previously blocked */ if(pUmDevice->tx_full){ printf("eth%d: tx blocked.\n", pUmDevice->index); return 0; } pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->TxPacketFreeQ.Container); if (pPacket == 0) { pUmDevice->tx_full = 1; printf("bcm570xEndSend: TX full!\n"); return 0; } if (pDevice->SendBdLeft.counter == 0) { pUmDevice->tx_full = 1; printf("bcm570xEndSend: no more TX descriptors!\n"); QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket); return 0; } if (length <= 0){ printf("eth: bad packet size: %d\n", length); goto out; } /* Get packet buffers and fragment list */ pUmPacket = (PUM_PACKET) pPacket; /* Single DMA Descriptor transmit. * Fragments may be provided, but one DMA descriptor max is * used to send the packet. */ if (MM_CoalesceTxBuffer (pDevice, pPacket) != LM_STATUS_SUCCESS) { if (pUmPacket->skbuff == NULL){ /* Packet was discarded */ printf("TX: failed (1)\n"); status = 1; } else{ printf("TX: failed (2)\n"); status = 2; } QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket); return status; } /* Copy packet to DMA buffer */ memset(pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE); memcpy((void*)pUmPacket->skbuff, (void*)packet, length); pPacket->PacketSize = length; pPacket->Flags |= SND_BD_FLAG_END|SND_BD_FLAG_COAL_NOW; pPacket->u.Tx.FragCount = 1; /* We've already provided a frame ready for transmission */ pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM; if ( LM_SendPacket(pDevice, pPacket) == LM_STATUS_FAILURE){ /* * A lower level send failure will push the packet descriptor back * in the free queue, so just deal with the VxWorks clusters. */ if (pUmPacket->skbuff == NULL){ printf("TX failed (1)!\n"); /* Packet was discarded */ status = 3; } else { /* A resource problem ... */ printf("TX failed (2)!\n"); status = 4; } if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) == 0) { printf("TX: emptyQ!\n"); pUmDevice->tx_full = 1; } } while(pUmDevice->tx_pkt == 0){ /* Service TX */ eth_isr(); }#if ET_DEBUG printf("eth_send: 0x%x, %d bytes\n" "[%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x] ...\n", (int)pPacket, length, ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5], ptr[6],ptr[7],ptr[8],ptr[9],ptr[10],ptr[11],ptr[12], ptr[13],ptr[14],ptr[15]);#endif pUmDevice->tx_pkt = 0; QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket); /* Done with send */ out: return status;}/* Ethernet receive */inteth_rx(void){ PLM_PACKET pPacket = NULL; PUM_PACKET pUmPacket = NULL; void *skb; int size=0; while(TRUE) { bcm570x_service_isr: /* Pull down packet if it is there */ eth_isr(); /* Indicate RX packets called */ if(pUmDevice->rx_pkt){ /* printf("eth_rx: got a packet...\n"); */ pUmDevice->rx_pkt = 0; } else { /* printf("eth_rx: waiting for packet...\n"); */ goto bcm570x_service_isr; } pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketReceivedQ.Container); if (pPacket == 0){ printf("eth_rx: empty packet!\n"); goto bcm570x_service_isr; } pUmPacket = (PUM_PACKET) pPacket;#if ET_DEBUG printf("eth_rx: packet @0x%x\n", (int)pPacket);#endif /* If the packet generated an error, reuse buffer */ if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) || ((size = pPacket->PacketSize) > pDevice->RxMtu)) { /* reuse skb */ QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); printf("eth_rx: error in packet dma!\n"); goto bcm570x_service_isr; } /* Set size and address */ skb = pUmPacket->skbuff; size = pPacket->PacketSize; /* Pass the packet up to the protocol * layers. */ NetReceive(skb, size); /* Free packet buffer */ bcm570xPktFree (pUmDevice->index, skb); pUmPacket->skbuff = NULL; /* Reuse SKB */ QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); return 0; /* Got a packet, bail ... */ } return size;}/* Shut down device */voideth_halt(void){ int i; if ( initialized) if (pDevice && pUmDevice && pUmDevice->opened){ printf("\neth%d:%s,", pUmDevice->index, pUmDevice->name); printf("HALT,"); /* stop device */ LM_Halt(pDevice); printf("POWER DOWN,"); LM_SetPowerState(pDevice, LM_POWER_STATE_D3); /* Free the memory allocated by the device in tigon3 */ for (i = 0; i < pUmDevice->mem_list_num; i++) { if (pUmDevice->mem_list[i]) { /* sanity check */ if (pUmDevice->dma_list[i]) { /* cache-safe memory */ free(pUmDevice->mem_list[i]); } else { free(pUmDevice->mem_list[i]); /* normal memory */ } } } pUmDevice->opened = 0; free(pDevice); pDevice = NULL; pUmDevice = NULL; initialized = 0; printf("done - offline.\n"); }}/* * * Middle Module: Interface between the HW driver (tigon3 modules) and * the native (SENS) driver. These routines implement the system * interface for tigon3 on VxWorks. *//* Middle module dependency - size of a packet descriptor */int MM_Packet_Desc_Size = sizeof(UM_PACKET);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -