status_t ASIXDevice::SetPromiscuousMode(bool on) { uint16 rxcontrol = 0; status_t result = ReadRXControlRegister(&rxcontrol); if (result != B_OK) { TRACE_ALWAYS("Error of reading RX Control:%#010x\n", result); return result; } if (on) rxcontrol |= RXCTL_PROMISCUOUS; else rxcontrol &= ~RXCTL_PROMISCUOUS; result = WriteRXControlRegister(rxcontrol); if (result != B_OK ) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", rxcontrol, result); } TRACE_RET(result); return result; }
status_t AX88772Device::_SetupAX88772B() { // Reload EEPROM size_t actualLength = 0; status_t result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_GPIOS, GPIO_RSE, 0, 0, 0, &actualLength); if (result != B_OK) { TRACE_ALWAYS("Error of reloading EEPROM: %#010x\n", result); return result; } result = _WakeupPHY(); if (result != B_OK) return result; result = WriteRXControlRegister(0); if (result != B_OK) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result); return result; } fIPG[0] = 0x15; fIPG[1] = 0x16; fIPG[2] = 0x1A; return B_OK; }
status_t AX88772Device::StartDevice() { size_t actualLength = 0; status_t result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_IPGS, 0, 0, sizeof(fIPG), fIPG, &actualLength); if(result != B_OK) { TRACE_ALWAYS("Error of writing IPGs:%#010x\n", result); return result; } if(actualLength != sizeof(fIPG)) { TRACE_ALWAYS("Mismatch of written IPGs data. " "%d bytes of %d written.\n", actualLength, sizeof(fIPG)); } uint16 rxcontrol = RXCTL_START | RXCTL_MULTICAST | RXCTL_BROADCAST; result = WriteRXControlRegister(rxcontrol); if(result != B_OK) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", rxcontrol, result); } TRACE_RET(result); return result; }
status_t ASIXDevice::StopDevice() { status_t result = WriteRXControlRegister(0); if (result != B_OK) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result); } TRACE_RET(result); return result; }
status_t AX88772Device::StartDevice() { size_t actualLength = 0; status_t result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_IPGS, 0, 0, sizeof(fIPG), fIPG, &actualLength); if (result != B_OK) { TRACE_ALWAYS("Error of writing IPGs:%#010x\n", result); return result; } if (actualLength != sizeof(fIPG)) { TRACE_ALWAYS("Mismatch of written IPGs data. " "%d bytes of %d written.\n", actualLength, sizeof(fIPG)); } // AX88772B uses different maximum frame burst configuration. if (fDeviceInfo.fType == DeviceInfo::AX88772B) { result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_RXCONTROL_CFG, AX88772B_MFBTable[AX88772B_MFB_2K].ByteCount, AX88772B_MFBTable[AX88772B_MFB_2K].Threshold, 0, 0, &actualLength); if (result != B_OK) { TRACE_ALWAYS("Error of writing frame burst:%#010x\n", result); return result; } } uint16 rxcontrol = RXCTL_START | RXCTL_BROADCAST; result = WriteRXControlRegister(rxcontrol); if (result != B_OK) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", rxcontrol, result); } TRACE_RET(result); return result; }
status_t ASIXDevice::ModifyMulticastTable(bool join, ether_address_t* group) { char groupName[6 * 3 + 1] = { 0 }; sprintf(groupName, "%02x:%02x:%02x:%02x:%02x:%02x", group->ebyte[0], group->ebyte[1], group->ebyte[2], group->ebyte[3], group->ebyte[4], group->ebyte[5]); TRACE("%s multicast group %s\n", join ? "Joining" : "Leaving", groupName); uint32 hash = EthernetCRC32(group->ebyte, 6); bool isInTable = fMulticastHashes.Find(hash) != fMulticastHashes.End(); if (isInTable && join) return B_OK; // already listed - nothing to do if (!isInTable && !join) { TRACE_ALWAYS("Cannot leave unlisted multicast group %s!\n", groupName); return B_ERROR; } const size_t hashLength = 8; uint8 hashTable[hashLength] = { 0 }; if (join) fMulticastHashes.PushBack(hash); else fMulticastHashes.Remove(hash); for (int32 i = 0; i < fMulticastHashes.Count(); i++) { uint32 hash = fMulticastHashes[i] >> 26; hashTable[hash / 8] |= 1 << (hash % 8); } uint16 rxcontrol = 0; status_t result = ReadRXControlRegister(&rxcontrol); if (result != B_OK) { TRACE_ALWAYS("Error of reading RX Control:%#010x\n", result); return result; } if (fMulticastHashes.Count() > 0) rxcontrol |= RXCTL_MULTICAST; else rxcontrol &= ~RXCTL_MULTICAST; // write multicast hash table size_t actualLength = 0; result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_MF_ARRAY, 0, 0, hashLength, hashTable, &actualLength); if (result != B_OK) { TRACE_ALWAYS("Error writing hash table in MAR: %#010x.\n", result); return result; } if (actualLength != hashLength) TRACE_ALWAYS("Incomplete writing of hash table: %d bytes of %d\n", actualLength, hashLength); result = WriteRXControlRegister(rxcontrol); if (result != B_OK) TRACE_ALWAYS("Error writing %#02X to RXC:%#010x.\n", rxcontrol, result); return result; }
status_t AX88772Device::_SetupAX88772() { size_t actualLength = 0; // enable GPIO2 - magic from FreeBSD's if_axe uint16 GPIOs = GPIO_OO_2EN | GPIO_IO_2 | GPIO_RSE; status_t result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_GPIOS, GPIOs, 0, 0, 0, &actualLength); if (result != B_OK) { TRACE_ALWAYS("Error of wrinting GPIOs: %#010x\n", result); return result; } // select PHY bool useEmbeddedPHY = fMII.PHYID() == PHYIDEmbedded; uint16 selectPHY = useEmbeddedPHY ? SW_PHY_SEL_STATUS_INT : SW_PHY_SEL_STATUS_EXT; result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_PHY_SEL, selectPHY, 0, 0, 0, &actualLength); snooze(10000); TRACE("Selecting %s PHY[%#02x].\n", useEmbeddedPHY ? "embedded" : "external", selectPHY); if (result != B_OK) { TRACE_ALWAYS("Error of selecting PHY:%#010x\n", result); return result; } struct SWReset { uint16 reset; bigtime_t delay; } resetCommands[] = { // EMBEDDED PHY // power down and reset state, pin reset state { SW_RESET_CLR, 60000 }, // power down/reset state, pin operating state { SW_RESET_PRL | SW_RESET_IPPD, 150000 }, // power up, reset { SW_RESET_PRL, 0 }, // power up, operating { SW_RESET_PRL | SW_RESET_IPRL, 0 }, // EXTERNAL PHY // power down/reset state, pin operating state { SW_RESET_PRL | SW_RESET_IPPD, 0 } }; size_t from = useEmbeddedPHY ? 0 : 4; size_t to = useEmbeddedPHY ? 3 : 4; for (size_t i = from; i <= to; i++) { result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_SOFT_RESET, resetCommands[i].reset, 0, 0, 0, &actualLength); snooze(resetCommands[i].delay); if (result != B_OK) { TRACE_ALWAYS("Error of SW reset command %d:[%#04x]: %#010x\n", i, resetCommands[i].reset, result); return result; } } snooze(150000); result = WriteRXControlRegister(0); if (result != B_OK) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result); return result; } return B_OK; }