[haiku-commits] r42822 - in haiku: branches/developer/siarzhuk trunk/src/add-ons/kernel/drivers/network trunk/src/add-ons/kernel/drivers/network/sis19x

  • From: zharik@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 11 Oct 2011 16:59:28 +0200 (CEST)

Author: siarzhuk
Date: 2011-10-11 16:59:28 +0200 (Tue, 11 Oct 2011)
New Revision: 42822
Changeset: https://dev.haiku-os.org/changeset/42822

Added:
   haiku/trunk/src/add-ons/kernel/drivers/network/sis19x/
   haiku/trunk/src/add-ons/kernel/drivers/network/sis19x/Device.cpp
Removed:
   haiku/branches/developer/siarzhuk/sis19x/
   haiku/trunk/src/add-ons/kernel/drivers/network/sis19x/Device.cpp
Modified:
   haiku/trunk/src/add-ons/kernel/drivers/network/Jamfile
Log:
SiS190/191 NIC driver moved from the development branch to the trunk
to be available for using during build. It was requested by Frederik Modeen.



Modified: haiku/trunk/src/add-ons/kernel/drivers/network/Jamfile
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/network/Jamfile      2011-10-11 
14:35:37 UTC (rev 42821)
+++ haiku/trunk/src/add-ons/kernel/drivers/network/Jamfile      2011-10-11 
14:59:28 UTC (rev 42822)
@@ -3,6 +3,7 @@
 SubInclude HAIKU_TOP src add-ons kernel drivers network etherpci ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network pegasus ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network rtl8169 ;
+SubInclude HAIKU_TOP src add-ons kernel drivers network sis19x ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network sis900 ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network usb_asix ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network usb_davicom ;

Copied: haiku/trunk/src/add-ons/kernel/drivers/network/sis19x/Device.cpp (from 
rev 42821, haiku/branches/developer/siarzhuk/sis19x/Device.cpp)
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/network/sis19x/Device.cpp            
                (rev 0)
+++ haiku/trunk/src/add-ons/kernel/drivers/network/sis19x/Device.cpp    
2011-10-11 14:59:28 UTC (rev 42822)
@@ -0,0 +1,676 @@
+/*
+ *     SiS 190/191 NIC Driver.
+ *     Copyright (c) 2009 S.Zharski <imker@xxxxxx>
+ *     Distributed under the terms of the MIT license.
+ *
+ */
+
+
+#include "Device.h"
+
+#include <net/if_media.h>
+#include <lock.h>
+
+#include "Driver.h"
+#include "Settings.h"
+#include "Registers.h"
+
+
+Device::Device(Device::Info &DeviceInfo, pci_info &PCIInfo)
+               :       
+               fStatus(B_ERROR),
+               fPCIInfo(PCIInfo),
+               fInfo(DeviceInfo),
+               fIOBase(0),
+               fHWSpinlock(0),
+               fInterruptsNest(0),
+               fFrameSize(MaxFrameSize),
+               fMII(this),
+               fOpen(false),
+               fBlockFlag(0),          
+               fLinkStateChangeSem(-1),
+               fHasConnection(false),
+               fTxDataRing(this, true),
+               fRxDataRing(this, false)
+{
+       memset((struct timer*)this, 0, sizeof(struct timer));   
+
+       uint32 cmdRegister = gPCIModule->read_pci_config(PCIInfo.bus,
+                       PCIInfo.device, PCIInfo.function, PCI_command, 2);
+       TRACE_ALWAYS("cmdRegister:%#010x\n", cmdRegister);
+       cmdRegister |= PCI_command_io | PCI_command_memory | PCI_command_master;
+       gPCIModule->write_pci_config(PCIInfo.bus, PCIInfo.device,
+                       PCIInfo.function, PCI_command, 2, cmdRegister);
+
+       fIOBase = PCIInfo.u.h0.base_registers[1];
+       TRACE_ALWAYS("fIOBase:%#010x\n", fIOBase);
+
+       fStatus = B_OK;
+}
+
+
+Device::~Device()
+{
+}
+
+
+status_t
+Device::Open(uint32 flags)
+{
+       TRACE("flags:%x\n", flags);
+       if (fOpen) {
+               TRACE_ALWAYS("An attempt to re-open device ignored.\n");
+               return B_BUSY;
+       }
+
+       status_t result = fMII.Init();
+       if (result != B_OK) {
+               TRACE_ALWAYS("MII initialization failed: %#010x.\n", result);
+               return result;
+       }
+
+       _Reset();
+
+       if ((fMII.LinkState().media & IFM_ACTIVE) == 0/*fNegotiationComplete*/) 
{
+               fMII.UpdateLinkState();
+       }
+
+       fMII.SetMedia();
+
+       WritePCI32(RxMACAddress, 0);
+       _InitRxFilter();
+
+       fRxDataRing.Open();
+       fTxDataRing.Open();
+
+       if (atomic_add(&fInterruptsNest, 1) == 0) {
+               install_io_interrupt_handler(fPCIInfo.u.h0.interrupt_line,
+                               InterruptHandler, this, 0);
+               TRACE("Interrupt handler installed at line %d.\n",
+                               fPCIInfo.u.h0.interrupt_line);
+       }
+
+       _SetRxMode(false);
+
+       // enable al known interrupts
+       WritePCI32(IntMask, knownInterruptsMask);
+
+       // enable Rx and Tx
+       uint32 control = ReadPCI32(RxControl);
+       control |= RxControlEnable | RxControlPoll;
+       WritePCI32(RxControl, control);
+
+       control = ReadPCI32(TxControl);
+       control |= TxControlEnable /*| TxControlPoll*/;
+       WritePCI32(TxControl, control);
+
+       add_timer((timer*)this, _TimerHandler, 1000000LL, B_PERIODIC_TIMER);
+
+       //fNonBlocking = (flags & O_NONBLOCK) == O_NONBLOCK;
+       fOpen = true;
+       return B_OK;
+}
+
+
+status_t
+Device::Close()
+{
+       TRACE("closed!\n");
+
+       // disable interrupts
+       WritePCI32(IntMask, 0);
+       spin(2000);
+
+       // Stop Tx / Rx status machine
+       uint32 status = ReadPCI32(IntControl);
+       status |= 0x00008000;
+       WritePCI32(IntControl, status);
+       spin(50);
+       status &= ~0x00008000;
+       WritePCI32(IntControl, status);
+
+       if (atomic_add(&fInterruptsNest, -1) == 1) {
+               remove_io_interrupt_handler(fPCIInfo.u.h0.interrupt_line,
+                               InterruptHandler, this);
+               TRACE("Interrupt handler at line %d uninstalled.\n",
+                               fPCIInfo.u.h0.interrupt_line);
+       }
+
+       fRxDataRing.Close();
+       fTxDataRing.Close();
+
+       cancel_timer((timer*)this);
+
+       TRACE("timer cancelled\n");
+
+       fOpen = false;
+
+       return B_OK;
+}
+
+
+status_t
+Device::Free()
+{
+       //      fRxDataRing.Free();
+       //      fTxDataRing.Free();
+
+       TRACE("freed\n");
+       return B_OK;
+}
+
+
+status_t
+Device::Read(uint8 *buffer, size_t *numBytes)
+{
+       return fRxDataRing.Read(buffer, numBytes);
+}
+
+
+status_t
+Device::Write(const uint8 *buffer, size_t *numBytes)
+{
+       if ((fMII.LinkState().media & IFM_ACTIVE) == 0) {
+               TRACE_ALWAYS("Write failed. link is inactive!\n");
+               return B_OK; // return OK because of well-known DHCP 
"moustreap"!
+       }
+
+       return fTxDataRing.Write(buffer, numBytes);
+}
+
+
+status_t
+Device::Control(uint32 op, void *buffer, size_t length)
+{
+       switch (op) {
+               case ETHER_INIT:
+                       TRACE("ETHER_INIT\n");
+                       return B_OK;
+
+               case ETHER_GETADDR:
+                       memcpy(buffer, &fMACAddress, sizeof(fMACAddress));
+                       TRACE("ETHER_GETADDR 
%#02x:%#02x:%#02x:%#02x:%#02x:%#02x\n",
+                                       fMACAddress.ebyte[0], 
fMACAddress.ebyte[1],
+                                       fMACAddress.ebyte[2], 
fMACAddress.ebyte[3],
+                                       fMACAddress.ebyte[4], 
fMACAddress.ebyte[5]);
+                       return B_OK;
+
+               case ETHER_GETFRAMESIZE:
+                       *(uint32 *)buffer = fFrameSize;
+                       TRACE("ETHER_ETHER_GETFRAMESIZE:%d\n",fFrameSize);
+                       return B_OK;
+
+               case ETHER_NONBLOCK:
+                       TRACE("ETHER_NONBLOCK\n");
+                       fBlockFlag = *((uint32*)buffer) ? B_TIMEOUT : 0;
+                       return B_OK;
+
+               case ETHER_SETPROMISC:
+                       TRACE("ETHER_SETPROMISC\n");
+                       return _SetRxMode(*((uint8*)buffer));
+
+               case ETHER_ADDMULTI:
+               case ETHER_REMMULTI:
+                       TRACE_ALWAYS("Multicast operations are not 
implemented.\n");
+                       return B_ERROR;
+
+               case ETHER_SET_LINK_STATE_SEM:
+                       fLinkStateChangeSem = *(sem_id *)buffer;
+                       TRACE_ALWAYS("ETHER_SET_LINK_STATE_SEM\n");
+                       return B_OK;
+
+               case ETHER_GET_LINK_STATE:
+                       return GetLinkState((ether_link_state *)buffer);
+
+               default:
+                       TRACE_ALWAYS("Unhandled IOCTL catched: %#010x\n", op);
+       }
+
+       return B_DEV_INVALID_IOCTL;
+}
+
+
+status_t
+Device::SetupDevice()
+{
+       ether_address address;
+       status_t result = ReadMACAddress(address);
+       if (result != B_OK) {
+               TRACE_ALWAYS("Error of reading MAC address:%#010x\n", result);
+               return result;
+       }
+
+       TRACE("MAC address is:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                       address.ebyte[0], address.ebyte[1], address.ebyte[2],
+                       address.ebyte[3], address.ebyte[4], address.ebyte[5]);
+
+       fMACAddress = address;
+
+       uint16 info = _ReadEEPROM(EEPROMInfo);
+       fMII.SetRGMII((info & 0x0080) != 0);
+
+       TRACE("RGMII is '%s'. EEPROM info word:%#06x.\n",
+                       fMII.HasRGMII() ? "on" : "off", info);
+
+       fMII.SetGigagbitCapable(fInfo.Id() == SiS191);
+
+       return B_OK;
+}
+
+
+void
+Device::TeardownDevice()
+{
+
+}
+
+
+uint8
+Device::ReadPCI8(int offset)
+{
+       return gPCIModule->read_io_8(fIOBase + offset);
+}
+
+
+uint16
+Device::ReadPCI16(int offset)
+{
+       return gPCIModule->read_io_16(fIOBase + offset);
+}
+
+
+uint32
+Device::ReadPCI32(int offset)
+{
+       return gPCIModule->read_io_32(fIOBase + offset);
+}
+
+
+void
+Device::WritePCI8(int offset, uint8 value)
+{
+       gPCIModule->write_io_8(fIOBase + offset, value);
+}
+
+
+void
+Device::WritePCI16(int offset, uint16 value)
+{
+       gPCIModule->write_io_16(fIOBase + offset, value);
+}
+
+
+void
+Device::WritePCI32(int offset, uint32 value)
+{
+       gPCIModule->write_io_32(fIOBase + offset, value);
+}
+
+/*
+   cpu_status
+   Device::Lock() 
+   {
+   cpu_status st = disable_interrupts();
+   acquire_spinlock(&fHWSpinlock);
+   return st;
+   }
+
+
+   void
+   Device::Unlock(cpu_status st) 
+   {
+   release_spinlock(&fHWSpinlock);
+   restore_interrupts(st);
+   }
+   */
+
+int32
+Device::InterruptHandler(void *InterruptParam)
+{
+       Device *device = (Device*)InterruptParam;
+       if(device == 0) {
+               TRACE_ALWAYS("Invalid parameter in the interrupt handler.\n");
+               return B_HANDLED_INTERRUPT;
+       }
+
+       int32 result = B_UNHANDLED_INTERRUPT;
+
+       acquire_spinlock(&device->fHWSpinlock);
+
+       // disable interrupts...
+       device->WritePCI32(IntMask, 0);
+
+       //int maxWorks = 40;
+
+       //do {
+       uint32 status = device->ReadPCI32(IntSource);
+
+#if STATISTICS
+       device->fStatistics.PutStatus(status);
+#endif
+       device->WritePCI32(IntSource, status);
+
+       if ((status & knownInterruptsMask) != 0) {
+               //break;
+               //}
+
+               // XXX: ????
+               result = B_HANDLED_INTERRUPT;
+
+       if ((status & (/*INT_TXIDLE |*/ INT_TXDONE)) != 0 ) {
+               result = device->fTxDataRing.InterruptHandler();
+       }
+
+       if ((status & (/*INT_RXIDLE |*/ INT_RXDONE)) != 0 ) {
+               result = device->fRxDataRing.InterruptHandler();
+       }
+
+       /*if ((status & (INT_LINK)) != 0 ) {
+       //if (!device->fMII.isLinkUp()) {
+       device->fTxDataRing.CleanUp();
+       //}
+       }*/
+       }
+
+       //} while (--maxWorks > 0);
+
+       // enable interrupts...
+       device->WritePCI32(IntMask, knownInterruptsMask);
+
+       release_spinlock(&device->fHWSpinlock);
+
+       return result;
+}
+
+
+status_t
+Device::GetLinkState(ether_link_state *linkState)
+{
+       status_t result = user_memcpy(linkState, &fMII.LinkState(),
+                       sizeof(ether_link_state));
+
+#if STATISTICS
+       fStatistics.Trace();
+       fRxDataRing.Trace();
+       fTxDataRing.Trace();
+       uint32 rxControl = ReadPCI32(RxControl);
+       uint32 txControl = ReadPCI32(TxControl);
+       TRACE_ALWAYS("RxControl:%#010x;TxControl:%#010x\n", rxControl, 
txControl);
+#endif
+
+       TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n", 
+                       (linkState->media & IFM_ACTIVE) ? "active" : "inactive",
+                       linkState->speed / 1000,
+                       (linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
+
+       return result;
+}
+
+
+status_t
+Device::_SetRxMode(bool isPromiscuousModeOn)
+{
+       // clean the Rx MAC Control register
+       WritePCI16(RxMACControl, (ReadPCI16(RxMACControl) & ~RXM_Mask));
+
+       uint16 rxMode = RXM_Broadcast | RXM_Multicast | RXM_Physical;
+       if (isPromiscuousModeOn) {
+               rxMode |= RXM_AllPhysical;
+       }
+
+       // set multicast filters
+       WritePCI32(RxHashTable, 0xffffffff);
+       WritePCI32(RxHashTable + 4, 0xffffffff);
+
+       // update rx mode
+       WritePCI16(RxMACControl, ReadPCI16(RxMACControl) | rxMode);
+
+       return B_OK;
+}
+
+
+int32
+Device::_TimerHandler(struct timer* timer)
+{
+       Device* device = (Device*)timer;
+
+       bool linkChanged = false;
+       int32 result = device->fMII.TimerHandler(&linkChanged);
+
+       if (linkChanged) {
+               if (device->fMII.IsLinkUp()) {
+                       device->fTxDataRing.CleanUp();
+                       //device->WritePCI32(IntControl, 0x8000);
+                       //device->ReadPCI32(IntControl);
+                       //spin(100);
+                       //device->WritePCI32(IntControl, 0x0);
+               }
+       }
+
+       if (linkChanged && device->fLinkStateChangeSem > B_OK) {
+               release_sem_etc(device->fLinkStateChangeSem, 1, 
B_DO_NOT_RESCHEDULE);
+       }
+
+       return result;
+}
+
+
+status_t
+Device::_Reset()
+{
+       // disable interrupts
+       WritePCI32(IntMask, 0);
+       WritePCI32(IntSource, 0xffffffff);
+
+       // reset Rx & Tx
+       WritePCI32(TxControl, 0x00001c00);
+       WritePCI32(RxControl, 0x001e1c00);
+
+       WritePCI32(IntControl, 0x8000);
+       ReadPCI32(IntControl);
+       spin(100);
+       WritePCI32(IntControl, 0x0);
+
+       WritePCI32(IntMask, 0);
+       WritePCI32(IntSource, 0xffffffff);
+
+       // initial values for all MAC registers
+       WritePCI32(TxBase,                      0x0);
+       WritePCI32(TxReserved,          0x0);
+       WritePCI32(RxBase,                      0x0);
+       WritePCI32(RxReserved,          0x0);
+
+       WritePCI32(PowControl,          0xffc00000);
+       WritePCI32(Reserved0,           0x0);
+
+       WritePCI32(StationControl,      fMII.HasRGMII() ? 0x04008001 : 
0x04000001);
+       WritePCI32(GIoCR,                       0x0);
+       WritePCI32(GIoControl,          0x0);
+
+       WritePCI32(TxMACControl,        0x00002364);
+       WritePCI32(TxLimit,                     0x0000000f);
+
+       WritePCI32(RGDelay,                     0x0);
+       WritePCI32(Reserved1,           0x0);
+       WritePCI32(RxMACControl,        0x00000252);
+
+       WritePCI32(RxHashTable,         0x0);
+       WritePCI32(RxHashTable + 4,     0x0);
+
+       WritePCI32(RxWOLControl,        0x80ff0000);
+       WritePCI32(RxWOLData,           0x80ff0000);
+       WritePCI32(RxMPSControl,        0x0);
+       WritePCI32(Reserved2,           0x0);
+
+       return B_OK;
+}
+
+
+void
+Device::_InitRxFilter()
+{
+       // store filter value
+       uint16 filter = ReadPCI16(RxMACControl);
+
+       // disable disable packet filtering before address is set
+       WritePCI32(RxMACControl, (filter & ~RXM_Mask));
+
+       for (size_t i = 0; i < _countof(fMACAddress.ebyte); i++) {
+               WritePCI8(RxMACAddress + i, fMACAddress.ebyte[i]);
+       }
+
+       // enable packet filtering
+       WritePCI16(RxMACControl, filter);
+}
+
+
+uint16
+Device::_ReadEEPROM(uint32 address)
+{
+       if (address > EIOffset) {
+               TRACE_ALWAYS("EEPROM address %#08x is invalid.\n", address);
+               return EIInvalid;
+       }
+
+       WritePCI32(EEPROMInterface, EIReq | EIOpRead | (address << 
EIOffsetShift));
+
+       spin(500); // 500 ms?
+
+       for (size_t i = 0; i < 1000; i++) {
+               uint32 data = ReadPCI32(EEPROMInterface);
+               if ((data & EIReq) == 0) {
+                       return (data & EIData) >> EIDataShift;
+               }
+               spin(100); // 100 ms?
+       }
+
+       TRACE_ALWAYS("timeout reading EEPROM.\n");
+
+       return EIInvalid;
+}
+
+
+status_t
+Device::ReadMACAddress(ether_address_t& address)
+{
+       uint16 signature = _ReadEEPROM(EEPROMSignature);
+       TRACE("EEPROM Signature: %#06x\n", signature);
+
+       if (signature != 0x0000 && signature != EIInvalid) {
+               for (size_t i = 0; i < _countof(address.ebyte) / 2; i++) {
+                       uint16 addr = _ReadEEPROM(EEPROMAddress + i);
+                       address.ebyte[i * 2 + 0] = (uint8)addr;
+                       address.ebyte[i * 2 + 1] = (uint8)(addr >> 8);
+               }
+
+               return B_OK;
+       }
+
+       // SiS96x can use APC CMOS RAM to store MAC address,
+       // this is accessed through ISA bridge.
+       uint32 register73 = gPCIModule->read_pci_config(fPCIInfo.bus,
+                       fPCIInfo.device, fPCIInfo.function, 0x73, 1);
+       TRACE_ALWAYS("Config register x73:%#010x\n", register73);
+
+       if ((register73 & 0x00000001) == 0)
+               return B_ERROR;
+
+       // look for PCI-ISA bridge
+       uint16 ids[] = { 0x0965, 0x0966, 0x0968 };
+
+       pci_info pciInfo = {0};
+       for (long i = 0; B_OK == (*gPCIModule->get_nth_pci_info)(i, &pciInfo); 
i++) {
+               if (pciInfo.vendor_id != 0x1039)
+                       continue;
+
+               for (size_t idx = 0; idx < _countof(ids); idx++) {
+                       if (pciInfo.device_id == ids[idx]) {
+
+                               // enable ports 0x78 0x79 to access APC 
registers
+                               uint32 reg = 
gPCIModule->read_pci_config(pciInfo.bus,
+                                       pciInfo.device, pciInfo.function, 0x48, 
1);
+                               reg &= ~0x02;
+                               gPCIModule->write_pci_config(pciInfo.bus,
+                                       pciInfo.device, pciInfo.function, 0x48, 
1, reg);
+                               snooze(50);
+                               reg = gPCIModule->read_pci_config(pciInfo.bus,
+                                       pciInfo.device, pciInfo.function, 0x48, 
1);
+
+                               // read factory MAC address
+                               for (size_t i = 0; i < _countof(address.ebyte); 
i++) {
+                                       gPCIModule->write_io_8(0x78, 0x09 + i);
+                                       address.ebyte[i] = 
gPCIModule->read_io_8(0x79);
+                               }
+
+                               // check MII/RGMII
+                               gPCIModule->write_io_8(0x78, 0x12);
+                               uint8 u8 = gPCIModule->read_io_8(0x79);
+                       // TODO: set RGMII in fMII correctly!
+                       //      bool bRGMII = (u8 & 0x80) != 0;
+                               TRACE_ALWAYS("RGMII: %#04x\n", u8);
+
+                               // close access to APC registers
+                               gPCIModule->write_pci_config(pciInfo.bus,
+                                       pciInfo.device, pciInfo.function, 0x48, 
1, reg);
+
+                               return B_OK;
+                       }
+               }
+       }
+
+       TRACE_ALWAYS("ISA bridge was not found.\n");
+       return B_ERROR;
+}
+
+
+void
+Device::DumpRegisters()
+{
+       struct RegisterEntry {
+               uint32 Base;
+               const char* Name;
+               bool writeBack;
+       } RegisterEntries[] = {
+               { TxControl,            "TxControl",    false },
+               { TxBase,                       "TxBase\t",             false },
+               { TxStatus,                     "TxStatus",             false },
+               { TxReserved,           "TxReserved",   false },
+               { RxControl,            "RxControl",    false },
+               { RxBase,                       "RxBase\t",             false },
+               { RxStatus,                     "RxStatus",             false },
+               { RxReserved,           "RxReserved",   false },
+               { IntSource,            "IntSource",    true },
+               { IntMask,                      "IntMask",              false },
+               { IntControl,           "IntControl",   false },
+               { IntTimer,                     "IntTimer",             false },
+               { PowControl,           "PowControl",   false },
+               { Reserved0,            "Reserved0",    false },
+               { EEPROMControl,        "EEPROMCntl",   false },
+               { EEPROMInterface,      "EEPROMIface",  false },
+               { StationControl,       "StationCntl",  false },
+               { SMInterface,          "SMInterface",  false },
+               { GIoCR,                        "GIoCR\t",              false },
+               { GIoControl,           "GIoControl",   false },
+               { TxMACControl,         "TxMACCntl",    false },
+               { TxLimit,                      "TxLimit",              false },
+               { RGDelay,                      "RGDelay",              false },
+               { Reserved1,            "Reserved1",    false },
+               { RxMACControl,         "RxMACCntlEtc", false },
+               { RxMACAddress + 2,     "RxMACAddr2",   false },
+               { RxHashTable,          "RxHashTable1", false },
+               { RxHashTable + 4,      "RxHashTable2", false },
+               { RxWOLControl,         "RxWOLControl", false },
+               { RxWOLData,            "RxWOLData",    false },
+               { RxMPSControl,         "RxMPSControl", false },
+               { Reserved2,            "Reserved2",    false }
+       };
+
+       for (size_t i = 0; i < _countof(RegisterEntries); i++) {
+               uint32 registerContents = ReadPCI32(RegisterEntries[i].Base);
+               kprintf("%s:\t%08lx\n", RegisterEntries[i].Name, 
registerContents);
+               if (RegisterEntries[i].writeBack) {
+                       WritePCI32(RegisterEntries[i].Base, registerContents);
+               }
+       }
+}
+


Other related posts:

  • » [haiku-commits] r42822 - in haiku: branches/developer/siarzhuk trunk/src/add-ons/kernel/drivers/network trunk/src/add-ons/kernel/drivers/network/sis19x - zharik