1 /* $NetBSD: arcbios.c,v 1.10 2001/11/22 12:17:00 tsutsui Exp $ */ 2 /* $OpenBSD: arcbios.c,v 1.3 1998/06/06 06:33:33 mickey Exp $ */ 3 4 /*- 5 * Copyright (c) 1996 M. Warner Losh. All rights reserved. 6 * Copyright (c) 1996, 1997, 1998 Per Fogelstrom. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/proc.h> 36 #include <sys/user.h> 37 #include <sys/kcore.h> 38 #include <uvm/uvm_extern.h> 39 #include <dev/cons.h> 40 #include <machine/cpu.h> 41 #include <arc/arc/arcbios.h> 42 43 int Bios_Read __P((int, char *, int, int *)); 44 int Bios_Write __P((int, char *, int, int *)); 45 int Bios_Open __P((char *, int, u_int *)); 46 int Bios_Close __P((u_int)); 47 arc_mem_t *Bios_GetMemoryDescriptor __P((arc_mem_t *)); 48 arc_sid_t *Bios_GetSystemId __P((void)); 49 arc_config_t *Bios_GetChild __P((arc_config_t *)); 50 arc_config_t *Bios_GetPeer __P((arc_config_t *)); 51 arc_dsp_stat_t *Bios_GetDisplayStatus __P((int)); 52 53 static void bios_config_id_copy __P((arc_config_t *, char *, size_t)); 54 static void bios_config_component __P((arc_config_t *)); 55 static void bios_config_subtree __P((arc_config_t *)); 56 57 char arc_vendor_id[sizeof(((arc_sid_t *)0)->vendor) + 1]; 58 unsigned char arc_product_id[sizeof(((arc_sid_t *)0)->prodid)]; 59 60 char arc_id[64 + 1]; 61 62 char arc_displayc_id[64 + 1]; /* DisplayController id */ 63 arc_dsp_stat_t arc_displayinfo; /* Save area for display status info. */ 64 65 int arc_cpu_l2cache_size = 0; 66 67 /* 68 * ARC Bios trampoline code. 69 */ 70 #define ARC_Call(Name,Offset) \ 71 __asm__("\n" \ 72 " .text\n" \ 73 " .ent " #Name "\n" \ 74 " .align 3\n" \ 75 " .set noreorder\n" \ 76 " .globl " #Name "\n" \ 77 #Name":\n" \ 78 " lw $2, 0x80001020\n"\ 79 " lw $2," #Offset "($2)\n"\ 80 " jr $2\n" \ 81 " nop\n" \ 82 " .end " #Name "\n" ); 83 84 ARC_Call(Bios_Load, 0x00); 85 ARC_Call(Bios_Invoke, 0x04); 86 ARC_Call(Bios_Execute, 0x08); 87 ARC_Call(Bios_Halt, 0x0c); 88 ARC_Call(Bios_PowerDown, 0x10); 89 ARC_Call(Bios_Restart, 0x14); 90 ARC_Call(Bios_Reboot, 0x18); 91 ARC_Call(Bios_EnterInteractiveMode, 0x1c); 92 ARC_Call(Bios_Unused1, 0x20); /* return_from_main? */ 93 ARC_Call(Bios_GetPeer, 0x24); 94 ARC_Call(Bios_GetChild, 0x28); 95 ARC_Call(Bios_GetParent, 0x2c); 96 ARC_Call(Bios_GetConfigurationData, 0x30); 97 ARC_Call(Bios_AddChild, 0x34); 98 ARC_Call(Bios_DeleteComponent, 0x38); 99 ARC_Call(Bios_GetComponent, 0x3c); 100 ARC_Call(Bios_SaveConfiguration, 0x40); 101 ARC_Call(Bios_GetSystemId, 0x44); 102 ARC_Call(Bios_GetMemoryDescriptor, 0x48); 103 ARC_Call(Bios_Unused2, 0x4c); /* signal??? */ 104 ARC_Call(Bios_GetTime, 0x50); 105 ARC_Call(Bios_GetRelativeTime, 0x54); 106 ARC_Call(Bios_GetDirectoryEntry, 0x58); 107 ARC_Call(Bios_Open, 0x5c); 108 ARC_Call(Bios_Close, 0x60); 109 ARC_Call(Bios_Read, 0x64); 110 ARC_Call(Bios_GetReadStatus, 0x68); 111 ARC_Call(Bios_Write, 0x6c); 112 ARC_Call(Bios_Seek, 0x70); 113 ARC_Call(Bios_Mount, 0x74); 114 ARC_Call(Bios_GetEnvironmentVariable, 0x78); 115 ARC_Call(Bios_SetEnvironmentVariable, 0x7c); 116 ARC_Call(Bios_GetFileInformation, 0x80); 117 ARC_Call(Bios_SetFileInformation, 0x84); 118 ARC_Call(Bios_FlushAllCaches, 0x88); 119 /* note: the followings don't exist on SGI */ 120 #ifdef arc 121 ARC_Call(Bios_TestUnicodeCharacter, 0x8c); 122 ARC_Call(Bios_GetDisplayStatus, 0x90); 123 #endif 124 125 /* 126 * BIOS based console, for early stage. 127 */ 128 129 int biosgetc __P((dev_t)); 130 void biosputc __P((dev_t, int)); 131 132 /* this is to fake out the console routines, while booting. */ 133 struct consdev bioscons = { 134 NULL, NULL, biosgetc, biosputc, nullcnpollc, NULL, NODEV, CN_DEAD 135 }; 136 137 int 138 biosgetc(dev) 139 dev_t dev; 140 { 141 int cnt; 142 char buf; 143 144 if (Bios_Read(0, &buf, 1, &cnt) != arc_ESUCCESS) 145 return (-1); 146 return (buf & 255); 147 } 148 149 void 150 biosputc(dev, ch) 151 dev_t dev; 152 int ch; 153 { 154 int cnt; 155 char buf; 156 157 buf = ch; 158 Bios_Write(1, &buf, 1, &cnt); 159 } 160 161 void 162 bios_init_console() 163 { 164 static int initialized = 0; 165 166 if (!initialized) { 167 initialized = 1; 168 /* fake out the console routines, for now */ 169 cn_tab = &bioscons; 170 } 171 } 172 173 /* 174 * Get memory descriptor for the memory configuration and 175 * create a layout database used by pmap init to set up 176 * the memory system. 177 * 178 * Concatenate obvious adjecent segments. 179 */ 180 int 181 bios_configure_memory(mem_reserved, mem_clusters, mem_cluster_cnt_return) 182 int *mem_reserved; 183 phys_ram_seg_t *mem_clusters; 184 int *mem_cluster_cnt_return; 185 { 186 int physmem = 0; /* Total physical memory size */ 187 int mem_cluster_cnt = 0; 188 189 arc_mem_t *descr = NULL; 190 paddr_t seg_start, seg_end; 191 int i, reserved; 192 193 while ((descr = Bios_GetMemoryDescriptor(descr)) != NULL) { 194 seg_start = descr->BasePage * 4096; 195 seg_end = seg_start + descr->PageCount * 4096; 196 197 #ifdef BIOS_MEMORY_DEBUG 198 printf("memory type:%d, 0x%8lx..%8lx, size:%8ld bytes\n", 199 descr->Type, (u_long)seg_start, (u_long)seg_end, 200 (u_long)(seg_end - seg_start)); 201 #endif 202 203 switch (descr->Type) { 204 case BadMemory: /* Have no use for these */ 205 break; 206 207 case ExeceptionBlock: 208 case SystemParameterBlock: 209 case FirmwarePermanent: 210 reserved = 1; 211 goto account_it; 212 213 case FreeMemory: 214 case LoadedProgram: /* This is the loaded kernel */ 215 case FirmwareTemporary: 216 case FreeContigous: 217 reserved = 0; 218 account_it: 219 physmem += descr->PageCount * 4096; 220 221 for (i = 0; i < mem_cluster_cnt; ) { 222 if (mem_reserved[i] == reserved && 223 mem_clusters[i].start == seg_end) 224 seg_end += mem_clusters[i].size; 225 else if (mem_reserved[i] == reserved && 226 mem_clusters[i].start + 227 mem_clusters[i].size == seg_start) 228 seg_start = mem_clusters[i].start; 229 else { /* do not merge the cluster */ 230 i++; 231 continue; 232 } 233 --mem_cluster_cnt; 234 mem_reserved[i] = mem_reserved[mem_cluster_cnt]; 235 mem_clusters[i] = mem_clusters[mem_cluster_cnt]; 236 } 237 /* assert(i == mem_cluster_cnt); */ 238 if (mem_cluster_cnt >= VM_PHYSSEG_MAX) { 239 printf("VM_PHYSSEG_MAX too small\n"); 240 for (;;) 241 ; 242 } 243 mem_reserved[i] = reserved; 244 mem_clusters[i].start = seg_start; 245 mem_clusters[i].size = seg_end - seg_start; 246 mem_cluster_cnt++; 247 break; 248 249 default: /* Unknown type, leave it alone... */ 250 break; 251 } 252 } 253 254 #ifdef BIOS_MEMORY_DEBUG 255 for (i = 0; i < mem_cluster_cnt; i++) 256 printf("mem_clusters[%d] = %d:{ 0x%8lx, 0x%8lx }\n", i, 257 mem_reserved[i], 258 (long)mem_clusters[i].start, 259 (long)mem_clusters[i].size); 260 printf("physmem = %d\n", physmem); 261 #endif 262 263 *mem_cluster_cnt_return = mem_cluster_cnt; 264 return (physmem); 265 } 266 267 /* 268 * ARC Firmware present? 269 */ 270 int 271 bios_ident() 272 { 273 return ( 274 (ArcBiosBase->magic == ARC_PARAM_BLK_MAGIC) || 275 (ArcBiosBase->magic == ARC_PARAM_BLK_MAGIC_BUG)); 276 } 277 278 /* 279 * save various information of BIOS for future use. 280 */ 281 282 static void 283 bios_config_id_copy(cf, string, size) 284 arc_config_t *cf; 285 char *string; 286 size_t size; 287 { 288 size--; 289 if (size > cf->id_len) 290 size = cf->id_len; 291 memcpy(string, cf->id, size); 292 string[size] = '\0'; 293 } 294 295 static void 296 bios_config_component(cf) 297 arc_config_t *cf; 298 { 299 switch (cf->class) { 300 case arc_SystemClass: 301 if (cf->type == arc_System) 302 bios_config_id_copy(cf, arc_id, sizeof(arc_id)); 303 break; 304 case arc_CacheClass: 305 if (cf->type == arc_SecondaryDcache) 306 arc_cpu_l2cache_size = 4096 << (cf->key & 0xffff); 307 break; 308 case arc_ControllerClass: 309 if (cf->type == arc_DisplayController && 310 arc_displayc_id[0] == '\0' /* first found one. XXX */) 311 bios_config_id_copy(cf, arc_displayc_id, 312 sizeof(arc_displayc_id)); 313 break; 314 default: 315 break; 316 } 317 } 318 319 static 320 void bios_config_subtree(cf) 321 arc_config_t *cf; 322 { 323 for (cf = Bios_GetChild(cf); cf != NULL; cf = Bios_GetPeer(cf)) { 324 bios_config_component(cf); 325 bios_config_subtree(cf); 326 } 327 } 328 329 void 330 bios_save_info() 331 { 332 arc_sid_t *sid; 333 334 sid = Bios_GetSystemId(); 335 if (sid) { 336 memcpy(arc_vendor_id, sid->vendor, sizeof(arc_vendor_id) - 1); 337 arc_vendor_id[sizeof(arc_vendor_id) - 1] = 0; 338 memcpy(arc_product_id, sid->prodid, sizeof(arc_product_id)); 339 } 340 341 bios_config_subtree(NULL); 342 343 #ifdef arc 344 arc_displayinfo = *Bios_GetDisplayStatus(1); 345 #endif 346 } 347 348 #ifdef arc 349 /* 350 * Return geometry of the display. Used by pccons.c to set up the 351 * display configuration. 352 */ 353 void 354 bios_display_info(xpos, ypos, xsize, ysize) 355 int *xpos; 356 int *ypos; 357 int *xsize; 358 int *ysize; 359 { 360 *xpos = arc_displayinfo.CursorXPosition; 361 *ypos = arc_displayinfo.CursorYPosition; 362 *xsize = arc_displayinfo.CursorMaxXPosition; 363 *ysize = arc_displayinfo.CursorMaxYPosition; 364 } 365 #endif 366