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