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