📄 bcm570x.c
字号:
void eth_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;}int eth_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 */int eth_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 */void eth_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);LM_STATUSMM_ReadConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 * pValue32){ UM_DEVICE_BLOCK *pUmDevice; pUmDevice = (UM_DEVICE_BLOCK *) pDevice; pci_read_config_dword (pUmDevice->pdev, Offset, (u32 *) pValue32); return LM_STATUS_SUCCESS;}LM_STATUSMM_WriteConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 Value32){ UM_DEVICE_BLOCK *pUmDevice; pUmDevice = (UM_DEVICE_BLOCK *) pDevice; pci_write_config_dword (pUmDevice->pdev, Offset, Value32); return LM_STATUS_SUCCESS;}LM_STATUSMM_ReadConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT16 * pValue16){ UM_DEVICE_BLOCK *pUmDevice; pUmDevice = (UM_DEVICE_BLOCK *) pDevice; pci_read_config_word (pUmDevice->pdev, Offset, (u16 *) pValue16); return LM_STATUS_SUCCESS;}LM_STATUSMM_WriteConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT16 Value16){ UM_DEVICE_BLOCK *pUmDevice; pUmDevice = (UM_DEVICE_BLOCK *) pDevice; pci_write_config_word (pUmDevice->pdev, Offset, Value16); return LM_STATUS_SUCCESS;}LM_STATUSMM_AllocateSharedMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, PLM_VOID * pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, LM_BOOL Cached){ PLM_VOID pvirt; PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; dma_addr_t mapping; pvirt = malloc (BlockSize); mapping = (dma_addr_t) (pvirt); if (!pvirt) return LM_STATUS_FAILURE; pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt; pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping; pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize; memset (pvirt, 0, BlockSize); *pMemoryBlockVirt = (PLM_VOID) pvirt; MM_SetAddr (pMemoryBlockPhy, (dma_addr_t) mapping); return LM_STATUS_SUCCESS;}LM_STATUSMM_AllocateMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, PLM_VOID * pMemoryBlockVirt){ PLM_VOID pvirt; PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; pvirt = malloc (BlockSize); if (!pvirt) return LM_STATUS_FAILURE; pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt; pUmDevice->dma_list[pUmDevice->mem_list_num] = 0; pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize; memset (pvirt, 0, BlockSize); *pMemoryBlockVirt = pvirt; return LM_STATUS_SUCCESS;}LM_STATUS MM_MapMemBase (PLM_DEVICE_BLOCK pDevice){ printf ("BCM570x PCI Memory base address @0x%x\n", (unsigned int)pDevice->pMappedMemBase); return LM_STATUS_SUCCESS;}LM_STATUS MM_InitializeUmPackets (PLM_DEVICE_BLOCK pDevice){ int i; void *skb; PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; PUM_PACKET pUmPacket = NULL; PLM_PACKET pPacket = NULL; for (i = 0; i < pDevice->RxPacketDescCnt; i++) { pPacket = QQ_PopHead (&pDevice->RxPacketFreeQ.Container); pUmPacket = (PUM_PACKET) pPacket; if (pPacket == 0) { printf ("MM_InitializeUmPackets: Bad RxPacketFreeQ\n"); } skb = bcm570xPktAlloc (pUmDevice->index, pPacket->u.Rx.RxBufferSize + 2); if (skb == 0) { pUmPacket->skbuff = 0; QQ_PushTail (&pUmDevice->rx_out_of_buf_q.Container, pPacket); printf ("MM_InitializeUmPackets: out of buffer.\n"); continue; } pUmPacket->skbuff = skb; QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); } pUmDevice->rx_low_buf_thresh = pDevice->RxPacketDescCnt / 8; return LM_STATUS_SUCCESS;}LM_STATUS MM_GetConfig (PLM_DEVICE_BLOCK pDevice){ PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; int index = pDevice->index; if (auto_speed[index] == 0) pDevice->DisableAutoNeg = TRUE; else pDevice->DisableAutoNeg = FALSE; if (line_speed[index] == 0) { pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO; pDevice->DisableAutoNeg = FALSE; } else { if (line_speed[index] == 1000) { if (pDevice->EnableTbi) { pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX; } else if (full_duplex[index]) { pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX; } else { pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS; } if (!pDevice->EnableTbi) pDevice->DisableAutoNeg = FALSE; } else if (line_speed[index] == 100) { if (full_duplex[index]) { pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX; } else { pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS; } } else if (line_speed[index] == 10) { if (full_duplex[index]) { pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX; } else { pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS; } } else { pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO; pDevice->DisableAutoNeg = FALSE; } } pDevice->FlowControlCap = 0; if (rx_flow_control[index] != 0) { pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE; } if (tx_flow_control[index] != 0) { pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE; } if ((auto_flow_control[index] != 0) && (pDevice->DisableAutoNeg == FALSE)) { pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE; if ((tx_flow_control[index] == 0) && (rx_flow_control[index] == 0)) { pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE | LM_FLOW_CONTROL_RECEIVE_PAUSE; } } /* Default MTU for now */ pUmDevice->mtu = 1500;#if T3_JUMBO_RCV_RCB_ENTRY_COUNT if (pUmDevice->mtu > 1500) { pDevice->RxMtu = pUmDevice->mtu; pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT; } else { pDevice->RxJumboDescCnt = 0; } pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];#else pDevice->RxMtu = pUmDevice->mtu;#endif 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; } pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index]; pDevice->RxStdDescCnt = rx_std_desc_cnt[index]; /* Note: adaptive coalescence really isn't adaptive in this driver */ pUmDevice->rx_adaptive_coalesce = rx_adaptive_coalesce[index]; if (!pUmDevice->rx_adaptive_coalesce) { pDevice->RxCoalescingTicks = rx_coalesce_ticks[index]; if (pDevice->RxCoalescingTicks > MAX_RX_COALESCING_TICKS) pDevice->RxCoalescingTicks = MAX_RX_COALESCING_TICKS; pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks; pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index]; if (pDevice->RxMaxCoalescedFrames > MAX_RX_MAX_COALESCED_FRAMES) pDevice->RxMaxCoalescedFrames = MAX_RX_MAX_COALESCED_FRAMES;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -