1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/sunddi.h>
32 #include <sys/esunddi.h>
33 #include <sys/ddi.h>
34
35 #include <sys/platform_module.h>
36 #include <sys/modctl.h>
37 #include <sys/lom_priv.h>
38 #include <sys/errno.h>
39 #include <sys/utsname.h>
40
41 #define TOD_DRIVER_NAME "todblade"
42 #define BSC_DRV SUNW_KERN_BSCV_MODULENAME
43 #define BSC_DRV_FUNC SUNW_KERN_BSCV_IDI_FN
44
45
46 /* local functions */
47 static void cpu_sgn_update(ushort_t, uchar_t, uchar_t, int);
48
49 /* Globals */
50 void (*bsc_drv_func_ptr)(struct bscv_idi_info *) = NULL;
51
52
53 void
startup_platform(void)54 startup_platform(void)
55 {
56 extern char *tod_module_name;
57 extern int watchdog_available;
58 extern int watchdog_enable;
59 extern int disable_watchdog_on_exit;
60
61 /* Set appropriate tod module for blade */
62 tod_module_name = TOD_DRIVER_NAME;
63
64 /* Set watchdog default configuration */
65 watchdog_available = 1;
66 watchdog_enable = 1;
67 disable_watchdog_on_exit = 1;
68 }
69
70 int
set_platform_tsb_spares()71 set_platform_tsb_spares()
72 {
73 return (0);
74 }
75
76 void
set_platform_defaults(void)77 set_platform_defaults(void)
78 {
79 /* Set the CPU signature function pointer */
80 cpu_sgn_func = cpu_sgn_update;
81 }
82
83 /*
84 * Definitions for accessing the pci config space of the isa node
85 * of Southbridge.
86 */
87 #define PLATFORM_ISA_PATHNAME "/pci@1f,0/isa@7"
88 #define PLATFORM_ISA_PATHNAME_WITH_SIMBA "/pci@1f,0/pci@1,1/isa@7"
89 static ddi_acc_handle_t platform_isa_handle; /* handle for isa pci space */
90
91 void
load_platform_drivers(void)92 load_platform_drivers(void)
93 {
94 extern int watchdog_available;
95 extern int watchdog_enable;
96 dev_info_t *dip; /* dip of the isa driver */
97 int simba_present = 0;
98 dev_info_t *root_child_node;
99 major_t major;
100
101 if (ddi_install_driver("power") != DDI_SUCCESS)
102 cmn_err(CE_WARN, "Failed to install \"power\" driver.");
103
104 /*
105 * Install Isa driver. This is required for the southbridge IDE
106 * workaround - to reset the IDE channel during IDE bus reset.
107 * Panic the system in case ISA driver could not be loaded or
108 * any problem in accessing its pci config space. Since the register
109 * to reset the channel for IDE is in ISA config space!.
110 */
111 root_child_node = ddi_get_child(ddi_root_node());
112
113 while (root_child_node != NULL) {
114 if (strcmp(ddi_node_name(root_child_node), "pci") == 0) {
115 root_child_node = ddi_get_child(root_child_node);
116 if (strcmp(ddi_node_name(root_child_node), "pci") == 0)
117 simba_present = 1;
118 break;
119 }
120 root_child_node = ddi_get_next_sibling(root_child_node);
121 }
122
123 if (simba_present)
124 dip = e_ddi_hold_devi_by_path(PLATFORM_ISA_PATHNAME_WITH_SIMBA,
125 0);
126 else
127 dip = e_ddi_hold_devi_by_path(PLATFORM_ISA_PATHNAME, 0);
128
129 if (dip == NULL) {
130 cmn_err(CE_PANIC, "Could not install the isa driver\n");
131 return;
132 }
133
134 if (pci_config_setup(dip, &platform_isa_handle) != DDI_SUCCESS) {
135 cmn_err(CE_PANIC, "Could not get the config space of isa\n");
136 return;
137 }
138
139 /*
140 * Load the blade support chip driver.
141 *
142 */
143
144 if (((major = ddi_name_to_major(BSC_DRV)) == -1) ||
145 (ddi_hold_installed_driver(major) == NULL)) {
146 cmn_err(CE_WARN, "%s: failed to load", BSC_DRV);
147 } else {
148
149 bsc_drv_func_ptr = (void (*)(struct bscv_idi_info *))
150 modgetsymvalue(BSC_DRV_FUNC, 0);
151
152 if (bsc_drv_func_ptr == NULL) {
153 cmn_err(CE_WARN, "load_platform_defaults: %s()"
154 " not found; signatures will not be updated\n",
155 BSC_DRV_FUNC);
156 watchdog_available = 0;
157 if (watchdog_enable) {
158 cmn_err(CE_WARN, "load_platform_defaults: %s()"
159 " not found; BSC OS watchdog service not available\n",
160 BSC_DRV_FUNC);
161 }
162 }
163 }
164 }
165
166 /*
167 * This routine provides a workaround for a bug in the SB chip which
168 * can cause data corruption. Will be invoked from the IDE HBA driver for
169 * Acer SouthBridge at the time of IDE bus reset.
170 */
171 /*ARGSUSED*/
172 int
plat_ide_chipreset(dev_info_t * dip,int chno)173 plat_ide_chipreset(dev_info_t *dip, int chno)
174 {
175 uint8_t val;
176 int ret = DDI_SUCCESS;
177
178 if (platform_isa_handle == NULL)
179 return (DDI_FAILURE);
180
181 val = pci_config_get8(platform_isa_handle, 0x58);
182 /*
183 * The dip passed as the argument is not used for platform.
184 * This will be needed for platforms which have multiple on-board SB,
185 * The dip passed will be used to match the corresponding ISA node.
186 */
187 switch (chno) {
188 case 0:
189 /*
190 * First disable the primary channel then re-enable it.
191 * As per ALI no wait should be required in between have
192 * given 1ms delay in between to be on safer side.
193 * bit 2 of register 0x58 when 0 disable the channel 0.
194 * bit 2 of register 0x58 when 1 enables the channel 0.
195 */
196 pci_config_put8(platform_isa_handle, 0x58, val & 0xFB);
197 drv_usecwait(1000);
198 pci_config_put8(platform_isa_handle, 0x58, val);
199 break;
200 case 1:
201 /*
202 * bit 3 of register 0x58 when 0 disable the channel 1.
203 * bit 3 of register 0x58 when 1 enables the channel 1.
204 */
205 pci_config_put8(platform_isa_handle, 0x58, val & 0xF7);
206 drv_usecwait(1000);
207 pci_config_put8(platform_isa_handle, 0x58, val);
208 break;
209 default:
210 /*
211 * Unknown channel number passed. Return failure.
212 */
213 ret = DDI_FAILURE;
214 }
215
216 return (ret);
217 }
218
219
220
221 /*ARGSUSED*/
222 int
plat_cpu_poweron(struct cpu * cp)223 plat_cpu_poweron(struct cpu *cp)
224 {
225 return (ENOTSUP); /* not supported on this platform */
226 }
227
228 /*ARGSUSED*/
229 int
plat_cpu_poweroff(struct cpu * cp)230 plat_cpu_poweroff(struct cpu *cp)
231 {
232 return (ENOTSUP); /* not supported on this platform */
233 }
234
235 /*ARGSUSED*/
236 void
plat_freelist_process(int mnode)237 plat_freelist_process(int mnode)
238 {
239 }
240
241 char *platform_module_list[] = {
242 (char *)0
243 };
244
245 /*ARGSUSED*/
246 void
plat_tod_fault(enum tod_fault_type tod_bad)247 plat_tod_fault(enum tod_fault_type tod_bad)
248 {
249 }
250
251 /*
252 * Our nodename has been set, pass it along to the BSC.
253 */
254 void
plat_nodename_set(void)255 plat_nodename_set(void)
256 {
257 struct bscv_idi_info bscv_info;
258
259 bscv_info.type = BSCV_IDI_NODENAME;
260 bscv_info.data = utsname.nodename;
261 bscv_info.size = strlen(utsname.nodename);
262
263 if (bsc_drv_func_ptr != NULL)
264 (bsc_drv_func_ptr)(&bscv_info);
265 }
266
267 /*
268 * Send an updated CPU signature to the BSC.
269 */
270
271 static void
cpu_sgn_update(ushort_t sig,uchar_t state,uchar_t sub_state,int cpuid)272 cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid)
273 {
274 struct bscv_idi_info bscv_info;
275 bscv_sig_t sc;
276
277 sc.sig_info.signature = CPU_SIG_BLD(sig, state, sub_state);
278 sc.cpu = cpuid;
279
280 bscv_info.type = BSCV_IDI_SIG;
281 bscv_info.data = ≻
282 bscv_info.size = sizeof (sc);
283
284
285 if (bsc_drv_func_ptr != NULL)
286 (*bsc_drv_func_ptr)(&bscv_info);
287 }
288