1cbe0a0c4SAugustin Cavalier /*
2cbe0a0c4SAugustin Cavalier * Copyright 2009 S.Zharski <imker@gmx.li>
3cbe0a0c4SAugustin Cavalier * Copyright 2018, Haiku, Inc. All rights reserved.
4cbe0a0c4SAugustin Cavalier * Distributed under the terms of the MIT License.
5cbe0a0c4SAugustin Cavalier */
6cbe0a0c4SAugustin Cavalier
7cbe0a0c4SAugustin Cavalier
8cbe0a0c4SAugustin Cavalier #include <PCI.h>
9cbe0a0c4SAugustin Cavalier
10cbe0a0c4SAugustin Cavalier #include <sys/bus.h>
11cbe0a0c4SAugustin Cavalier #include <sys/rman.h>
12cbe0a0c4SAugustin Cavalier #include <sys/systm.h>
13cbe0a0c4SAugustin Cavalier
14cbe0a0c4SAugustin Cavalier #include <machine/bus.h>
15cbe0a0c4SAugustin Cavalier
16cbe0a0c4SAugustin Cavalier #include <net/if.h>
17cbe0a0c4SAugustin Cavalier #include <net/if_media.h>
18cbe0a0c4SAugustin Cavalier
19cbe0a0c4SAugustin Cavalier #include <dev/pci/pcivar.h>
20cbe0a0c4SAugustin Cavalier #include <dev/sge/if_sgereg.h>
21cbe0a0c4SAugustin Cavalier
22a5c0d1a8SPulkoMandy #include "glue.h"
23a5c0d1a8SPulkoMandy
24cbe0a0c4SAugustin Cavalier
25cbe0a0c4SAugustin Cavalier HAIKU_FBSD_DRIVER_GLUE(sis19x, sge, pci);
26*b0719130SAugustin Cavalier HAIKU_DRIVER_REQUIREMENTS(0);
27cbe0a0c4SAugustin Cavalier NO_HAIKU_REENABLE_INTERRUPTS();
28cbe0a0c4SAugustin Cavalier
29cbe0a0c4SAugustin Cavalier
30cbe0a0c4SAugustin Cavalier extern pci_module_info *gPci;
31cbe0a0c4SAugustin Cavalier extern driver_t* DRIVER_MODULE_NAME(ukphy, miibus);
32cbe0a0c4SAugustin Cavalier
33cbe0a0c4SAugustin Cavalier
34cbe0a0c4SAugustin Cavalier driver_t *
__haiku_select_miibus_driver(device_t dev)35cbe0a0c4SAugustin Cavalier __haiku_select_miibus_driver(device_t dev)
36cbe0a0c4SAugustin Cavalier {
37cbe0a0c4SAugustin Cavalier driver_t *drivers[] = {
38cbe0a0c4SAugustin Cavalier DRIVER_MODULE_NAME(ukphy, miibus),
39cbe0a0c4SAugustin Cavalier NULL
40cbe0a0c4SAugustin Cavalier };
41cbe0a0c4SAugustin Cavalier
42cbe0a0c4SAugustin Cavalier return __haiku_probe_miibus(dev, drivers);
43cbe0a0c4SAugustin Cavalier }
44cbe0a0c4SAugustin Cavalier
45cbe0a0c4SAugustin Cavalier
46cbe0a0c4SAugustin Cavalier int
HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev)47cbe0a0c4SAugustin Cavalier HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev)
48cbe0a0c4SAugustin Cavalier {
49cbe0a0c4SAugustin Cavalier struct sge_softc *sc = device_get_softc(dev);
50cbe0a0c4SAugustin Cavalier uint32_t status;
51cbe0a0c4SAugustin Cavalier
52cbe0a0c4SAugustin Cavalier status = CSR_READ_4(sc, IntrStatus);
53cbe0a0c4SAugustin Cavalier if (status == 0xFFFFFFFF || (status & SGE_INTRS) == 0) {
54cbe0a0c4SAugustin Cavalier /* Not ours. */
55cbe0a0c4SAugustin Cavalier return 0;
56cbe0a0c4SAugustin Cavalier }
57cbe0a0c4SAugustin Cavalier
58cbe0a0c4SAugustin Cavalier /* Acknowledge interrupts. */
59cbe0a0c4SAugustin Cavalier CSR_WRITE_4(sc, IntrStatus, status);
60cbe0a0c4SAugustin Cavalier /* Disable further interrupts. */
61cbe0a0c4SAugustin Cavalier CSR_WRITE_4(sc, IntrMask, 0);
62cbe0a0c4SAugustin Cavalier
63cbe0a0c4SAugustin Cavalier sc->haiku_interrupt_status = status;
64cbe0a0c4SAugustin Cavalier return 1;
65cbe0a0c4SAugustin Cavalier }
66cbe0a0c4SAugustin Cavalier
67cbe0a0c4SAugustin Cavalier
68cbe0a0c4SAugustin Cavalier int
haiku_sge_get_mac_addr_apc(device_t dev,uint8_t * dest,int * rgmii)69cbe0a0c4SAugustin Cavalier haiku_sge_get_mac_addr_apc(device_t dev, uint8_t* dest, int* rgmii)
70cbe0a0c4SAugustin Cavalier {
71cbe0a0c4SAugustin Cavalier // SiS96x can use APC CMOS RAM to store MAC address,
72cbe0a0c4SAugustin Cavalier // this is accessed through ISA bridge.
73cbe0a0c4SAugustin Cavalier
74cbe0a0c4SAugustin Cavalier // look for PCI-ISA bridge
75cbe0a0c4SAugustin Cavalier uint16 ids[] = { 0x0965, 0x0966, 0x0968 };
76cbe0a0c4SAugustin Cavalier
77cbe0a0c4SAugustin Cavalier pci_info pciInfo = {0};
78cbe0a0c4SAugustin Cavalier long i;
79cbe0a0c4SAugustin Cavalier for (i = 0; B_OK == (*gPci->get_nth_pci_info)(i, &pciInfo); i++) {
80cbe0a0c4SAugustin Cavalier size_t idx;
81cbe0a0c4SAugustin Cavalier if (pciInfo.vendor_id != 0x1039)
82cbe0a0c4SAugustin Cavalier continue;
83cbe0a0c4SAugustin Cavalier
84cbe0a0c4SAugustin Cavalier for (idx = 0; idx < B_COUNT_OF(ids); idx++) {
85cbe0a0c4SAugustin Cavalier if (pciInfo.device_id == ids[idx]) {
86cbe0a0c4SAugustin Cavalier size_t i;
87cbe0a0c4SAugustin Cavalier // enable ports 0x78 0x79 to access APC registers
88cbe0a0c4SAugustin Cavalier uint32 reg = gPci->read_pci_config(pciInfo.bus,
89cbe0a0c4SAugustin Cavalier pciInfo.device, pciInfo.function, 0x48, 1);
90cbe0a0c4SAugustin Cavalier reg &= ~0x02;
91cbe0a0c4SAugustin Cavalier gPci->write_pci_config(pciInfo.bus,
92cbe0a0c4SAugustin Cavalier pciInfo.device, pciInfo.function, 0x48, 1, reg);
93cbe0a0c4SAugustin Cavalier snooze(50);
94cbe0a0c4SAugustin Cavalier reg = gPci->read_pci_config(pciInfo.bus,
95cbe0a0c4SAugustin Cavalier pciInfo.device, pciInfo.function, 0x48, 1);
96cbe0a0c4SAugustin Cavalier
97cbe0a0c4SAugustin Cavalier // read factory MAC address
98cbe0a0c4SAugustin Cavalier for (i = 0; i < 6; i++) {
99cbe0a0c4SAugustin Cavalier gPci->write_io_8(0x78, 0x09 + i);
100cbe0a0c4SAugustin Cavalier dest[i] = gPci->read_io_8(0x79);
101cbe0a0c4SAugustin Cavalier }
102cbe0a0c4SAugustin Cavalier
103cbe0a0c4SAugustin Cavalier // check MII/RGMII
104cbe0a0c4SAugustin Cavalier gPci->write_io_8(0x78, 0x12);
105cbe0a0c4SAugustin Cavalier if ((gPci->read_io_8(0x79) & 0x80) != 0)
106cbe0a0c4SAugustin Cavalier *rgmii = 1;
107cbe0a0c4SAugustin Cavalier
108cbe0a0c4SAugustin Cavalier // close access to APC registers
109cbe0a0c4SAugustin Cavalier gPci->write_pci_config(pciInfo.bus,
110cbe0a0c4SAugustin Cavalier pciInfo.device, pciInfo.function, 0x48, 1, reg);
111cbe0a0c4SAugustin Cavalier
112cbe0a0c4SAugustin Cavalier return B_OK;
113cbe0a0c4SAugustin Cavalier }
114cbe0a0c4SAugustin Cavalier }
115cbe0a0c4SAugustin Cavalier }
116cbe0a0c4SAugustin Cavalier
117cbe0a0c4SAugustin Cavalier return B_ERROR;
118cbe0a0c4SAugustin Cavalier }
119