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 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 71 set_platform_tsb_spares() 72 { 73 return (0); 74 } 75 76 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 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 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 223 plat_cpu_poweron(struct cpu *cp) 224 { 225 return (ENOTSUP); /* not supported on this platform */ 226 } 227 228 /*ARGSUSED*/ 229 int 230 plat_cpu_poweroff(struct cpu *cp) 231 { 232 return (ENOTSUP); /* not supported on this platform */ 233 } 234 235 /*ARGSUSED*/ 236 void 237 plat_freelist_process(int mnode) 238 { 239 } 240 241 char *platform_module_list[] = { 242 (char *)0 243 }; 244 245 /*ARGSUSED*/ 246 void 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 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 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