root/src/add-ons/kernel/drivers/network/ether/pcnet/glue.c
#include <sys/bus.h>
#include <sys/mutex.h>
#include <sys/rman.h>

#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_media.h>

#include <machine/bus.h>
#include <shared.h>

#include <dev/le/lancereg.h>
#include <dev/le/lancevar.h>
#include <dev/le/am79900var.h>

HAIKU_FBSD_DRIVERS_GLUE(pcnet);
HAIKU_DRIVER_REQUIREMENTS(0);

extern driver_t *DRIVER_MODULE_NAME(nsphy, miibus);
extern driver_t *DRIVER_MODULE_NAME(nsphyter, miibus);
extern driver_t *DRIVER_MODULE_NAME(ukphy, miibus);


driver_t *
__haiku_select_miibus_driver(device_t dev)
{
        driver_t *drivers[] = {
                DRIVER_MODULE_NAME(nsphy, miibus),
                DRIVER_MODULE_NAME(nsphyter, miibus),
                DRIVER_MODULE_NAME(ukphy, miibus),
                NULL
        };

        return __haiku_probe_drivers(dev, drivers);
}

int check_disable_interrupts_le(device_t dev);
void reenable_interrupts_le(device_t dev);

extern int check_disable_interrupts_pcn(device_t dev);
extern void reenable_interrupts_pcn(device_t dev);


extern driver_t *DRIVER_MODULE_NAME(le, pci);
extern driver_t *DRIVER_MODULE_NAME(pcn, pci);


void
__haiku_init_hardware()
{
        driver_t *drivers[] = {
                DRIVER_MODULE_NAME(le, pci),
                DRIVER_MODULE_NAME(pcn, pci),
                NULL
        };
        _fbsd_init_hardware_pci(drivers);
}


int
HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev)
{
        switch (dev->device_name[0]) {
                case 'l':
                        return check_disable_interrupts_le(dev);
                case 'p':
                        return check_disable_interrupts_pcn(dev);
                default:
                        break;
        }

        panic("Unsupported device: %#x (%s)!", dev->device_name[0],
                dev->device_name);
        return 0;
}


void
HAIKU_REENABLE_INTERRUPTS(device_t dev)
{
        switch (dev->device_name[0]) {
                case 'l':
                        break;
                case 'p':
                        reenable_interrupts_pcn(dev);
                        break;
                default:
                        panic("Unsupported device: %#x (%s)!", dev->device_name[0],
                                dev->device_name);
                        break;
        }
}



/* from if_le_pci.c */
#define PCNET_PCI_RDP   0x10
#define PCNET_PCI_RAP   0x12

struct le_pci_softc {
        struct am79900_softc    sc_am79900;     /* glue to MI code */

        struct resource         *sc_rres;

        struct resource         *sc_ires;
        void                            *sc_ih;

        bus_dma_tag_t           sc_pdmat;
        bus_dma_tag_t           sc_dmat;
        bus_dmamap_t            sc_dmam;
};

int
check_disable_interrupts_le(device_t dev)
{
        struct le_pci_softc *lesc = (struct le_pci_softc *)device_get_softc(dev);
        HAIKU_INTR_REGISTER_STATE;
        uint16_t isr;

        HAIKU_INTR_REGISTER_ENTER();

        /* get current flags */
        bus_write_2(lesc->sc_rres, PCNET_PCI_RAP, LE_CSR0);
        bus_barrier(lesc->sc_rres, PCNET_PCI_RAP, 2, BUS_SPACE_BARRIER_WRITE);
        isr = (bus_read_2(lesc->sc_rres, PCNET_PCI_RDP));

        /* is there a pending interrupt? */
        if ((isr & LE_C0_INTR) == 0) {
                HAIKU_INTR_REGISTER_LEAVE();
                return 0;
        }

        /* set the new flags, disable interrupts */
        bus_write_2(lesc->sc_rres, PCNET_PCI_RAP, LE_CSR0);
        bus_barrier(lesc->sc_rres, PCNET_PCI_RAP, 2, BUS_SPACE_BARRIER_WRITE);
        bus_write_2(lesc->sc_rres, PCNET_PCI_RDP, isr & ~(LE_C0_INEA));

        lesc->sc_am79900.lsc.sc_lastisr |= isr;

        HAIKU_INTR_REGISTER_LEAVE();

        return 1;
}