1/* $NetBSD: arcbios.c,v 1.16 2005/12/24 23:23:59 perry 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/cdefs.h> 34__KERNEL_RCSID(0, "$NetBSD: arcbios.c,v 1.16 2005/12/24 23:23:59 perry Exp $"); 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/proc.h> 39#include <sys/kcore.h> 40#include <uvm/uvm_extern.h> 41#include <dev/cons.h> 42#include <machine/cpu.h> 43#include <arc/arc/arcbios.h> 44 45int Bios_Read(int, char *, int, int *); 46int Bios_Write(int, char *, int, int *); 47int Bios_Open(char *, int, u_int *); 48int Bios_Close(u_int); 49arc_mem_t *Bios_GetMemoryDescriptor(arc_mem_t *); 50arc_sid_t *Bios_GetSystemId(void); 51arc_config_t *Bios_GetChild(arc_config_t *); 52arc_config_t *Bios_GetPeer(arc_config_t *); 53arc_dsp_stat_t *Bios_GetDisplayStatus(int); 54 55static void bios_config_id_copy(arc_config_t *, char *, size_t); 56static void bios_config_component(arc_config_t *); 57static void bios_config_subtree(arc_config_t *); 58 59char arc_vendor_id[sizeof(((arc_sid_t *)0)->vendor) + 1]; 60unsigned char arc_product_id[sizeof(((arc_sid_t *)0)->prodid)]; 61 62char arc_id[64 + 1]; 63 64char arc_displayc_id[64 + 1]; /* DisplayController id */ 65arc_dsp_stat_t arc_displayinfo; /* Save area for display status info. */ 66 67int arc_cpu_l2cache_size = 0; 68 69/* 70 * ARC Bios trampoline code. 71 */ 72#define ARC_Call(Name,Offset) \ 73__asm("\n" \ 74" .text\n" \ 75" .ent " #Name "\n" \ 76" .align 3\n" \ 77" .set noreorder\n" \ 78" .globl " #Name "\n" \ 79#Name":\n" \ 80" lw $2, 0x80001020\n"\ 81" lw $2," #Offset "($2)\n"\ 82" jr $2\n" \ 83" nop\n" \ 84" .end " #Name "\n" ); 85 86ARC_Call(Bios_Load, 0x00); 87ARC_Call(Bios_Invoke, 0x04); 88ARC_Call(Bios_Execute, 0x08); 89ARC_Call(Bios_Halt, 0x0c); 90ARC_Call(Bios_PowerDown, 0x10); 91ARC_Call(Bios_Restart, 0x14); 92ARC_Call(Bios_Reboot, 0x18); 93ARC_Call(Bios_EnterInteractiveMode, 0x1c); 94ARC_Call(Bios_Unused1, 0x20); /* return_from_main? */ 95ARC_Call(Bios_GetPeer, 0x24); 96ARC_Call(Bios_GetChild, 0x28); 97ARC_Call(Bios_GetParent, 0x2c); 98ARC_Call(Bios_GetConfigurationData, 0x30); 99ARC_Call(Bios_AddChild, 0x34); 100ARC_Call(Bios_DeleteComponent, 0x38); 101ARC_Call(Bios_GetComponent, 0x3c); 102ARC_Call(Bios_SaveConfiguration, 0x40); 103ARC_Call(Bios_GetSystemId, 0x44); 104ARC_Call(Bios_GetMemoryDescriptor, 0x48); 105ARC_Call(Bios_Unused2, 0x4c); /* signal??? */ 106ARC_Call(Bios_GetTime, 0x50); 107ARC_Call(Bios_GetRelativeTime, 0x54); 108ARC_Call(Bios_GetDirectoryEntry, 0x58); 109ARC_Call(Bios_Open, 0x5c); 110ARC_Call(Bios_Close, 0x60); 111ARC_Call(Bios_Read, 0x64); 112ARC_Call(Bios_GetReadStatus, 0x68); 113ARC_Call(Bios_Write, 0x6c); 114ARC_Call(Bios_Seek, 0x70); 115ARC_Call(Bios_Mount, 0x74); 116ARC_Call(Bios_GetEnvironmentVariable, 0x78); 117ARC_Call(Bios_SetEnvironmentVariable, 0x7c); 118ARC_Call(Bios_GetFileInformation, 0x80); 119ARC_Call(Bios_SetFileInformation, 0x84); 120ARC_Call(Bios_FlushAllCaches, 0x88); 121/* note: the followings don't exist on SGI */ 122#ifdef arc 123ARC_Call(Bios_TestUnicodeCharacter, 0x8c); 124ARC_Call(Bios_GetDisplayStatus, 0x90); 125#endif 126 127/* 128 * BIOS based console, for early stage. 129 */ 130 131int biosgetc(dev_t); 132void biosputc(dev_t, int); 133 134/* this is to fake out the console routines, while booting. */ 135struct consdev bioscons = { 136 NULL, NULL, biosgetc, biosputc, nullcnpollc, NULL, NULL, 137 NULL, NODEV, CN_DEAD 138}; 139 140int 141biosgetc(dev_t dev) 142{ 143 int cnt; 144 char buf; 145 146 if (Bios_Read(0, &buf, 1, &cnt) != arc_ESUCCESS) 147 return -1; 148 return buf & 255; 149} 150 151void 152biosputc(dev_t dev, int ch) 153{ 154 int cnt; 155 char buf; 156 157 buf = ch; 158 Bios_Write(1, &buf, 1, &cnt); 159} 160 161void 162bios_init_console(void) 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 */ 180int 181bios_configure_memory(int *mem_reserved, phys_ram_seg_t *mem_clusters, 182 int *mem_cluster_cnt_return) 183{ 184 int bios_physmem = 0; /* Total physical memory size */ 185 int mem_cluster_cnt = 0; 186 187 arc_mem_t *descr = NULL; 188 paddr_t seg_start, seg_end; 189 int i, reserved; 190 191 while ((descr = Bios_GetMemoryDescriptor(descr)) != NULL) { 192 seg_start = descr->BasePage * 4096; 193 seg_end = seg_start + descr->PageCount * 4096; 194 195#ifdef BIOS_MEMORY_DEBUG 196 printf("memory type:%d, 0x%8lx..%8lx, size:%8ld bytes\n", 197 descr->Type, (u_long)seg_start, (u_long)seg_end, 198 (u_long)(seg_end - seg_start)); 199#endif 200 201 switch (descr->Type) { 202 case BadMemory: /* Have no use for these */ 203 break; 204 205 case ExeceptionBlock: 206 case SystemParameterBlock: 207 case FirmwarePermanent: 208 reserved = 1; 209 goto account_it; 210 211 case FreeMemory: 212 case LoadedProgram: /* This is the loaded kernel */ 213 case FirmwareTemporary: 214 case FreeContigous: 215 reserved = 0; 216account_it: 217 bios_physmem += descr->PageCount * 4096; 218 219 for (i = 0; i < mem_cluster_cnt; ) { 220 if (mem_reserved[i] == reserved && 221 mem_clusters[i].start == seg_end) 222 seg_end += mem_clusters[i].size; 223 else if (mem_reserved[i] == reserved && 224 mem_clusters[i].start + 225 mem_clusters[i].size == seg_start) 226 seg_start = mem_clusters[i].start; 227 else { /* do not merge the cluster */ 228 i++; 229 continue; 230 } 231 --mem_cluster_cnt; 232 mem_reserved[i] = mem_reserved[mem_cluster_cnt]; 233 mem_clusters[i] = mem_clusters[mem_cluster_cnt]; 234 } 235 /* assert(i == mem_cluster_cnt); */ 236 if (mem_cluster_cnt >= VM_PHYSSEG_MAX) { 237 printf("VM_PHYSSEG_MAX too small\n"); 238 for (;;) 239 ; 240 } 241 mem_reserved[i] = reserved; 242 mem_clusters[i].start = seg_start; 243 mem_clusters[i].size = seg_end - seg_start; 244 mem_cluster_cnt++; 245 break; 246 247 default: /* Unknown type, leave it alone... */ 248 break; 249 } 250 } 251 252#ifdef BIOS_MEMORY_DEBUG 253 for (i = 0; i < mem_cluster_cnt; i++) 254 printf("mem_clusters[%d] = %d:{ 0x%8lx, 0x%8lx }\n", i, 255 mem_reserved[i], 256 (long)mem_clusters[i].start, 257 (long)mem_clusters[i].size); 258 printf("physmem = %d\n", bios_physmem); 259#endif 260 261 *mem_cluster_cnt_return = mem_cluster_cnt; 262 return bios_physmem; 263} 264 265/* 266 * ARC Firmware present? 267 */ 268int 269bios_ident(void) 270{ 271 272 return (ArcBiosBase->magic == ARC_PARAM_BLK_MAGIC) || 273 (ArcBiosBase->magic == ARC_PARAM_BLK_MAGIC_BUG); 274} 275 276/* 277 * save various information of BIOS for future use. 278 */ 279 280static void 281bios_config_id_copy(arc_config_t *cf, char *string, size_t size) 282{ 283 284 size--; 285 if (size > cf->id_len) 286 size = cf->id_len; 287 memcpy(string, cf->id, size); 288 string[size] = '\0'; 289} 290 291static void 292bios_config_component(arc_config_t *cf) 293{ 294 295 switch (cf->class) { 296 case arc_SystemClass: 297 if (cf->type == arc_System) 298 bios_config_id_copy(cf, arc_id, sizeof(arc_id)); 299 break; 300 case arc_CacheClass: 301 if (cf->type == arc_SecondaryDcache) 302 arc_cpu_l2cache_size = 4096 << (cf->key & 0xffff); 303 break; 304 case arc_ControllerClass: 305 if (cf->type == arc_DisplayController && 306 arc_displayc_id[0] == '\0' /* first found one. XXX */) 307 bios_config_id_copy(cf, arc_displayc_id, 308 sizeof(arc_displayc_id)); 309 break; 310 default: 311 break; 312 } 313} 314 315static 316void bios_config_subtree(arc_config_t *cf) 317{ 318 319 for (cf = Bios_GetChild(cf); cf != NULL; cf = Bios_GetPeer(cf)) { 320 bios_config_component(cf); 321 bios_config_subtree(cf); 322 } 323} 324 325void 326bios_save_info(void) 327{ 328 arc_sid_t *sid; 329 330 sid = Bios_GetSystemId(); 331 if (sid) { 332 memcpy(arc_vendor_id, sid->vendor, sizeof(arc_vendor_id) - 1); 333 arc_vendor_id[sizeof(arc_vendor_id) - 1] = 0; 334 memcpy(arc_product_id, sid->prodid, sizeof(arc_product_id)); 335 } 336 337 bios_config_subtree(NULL); 338 339#ifdef arc 340 arc_displayinfo = *Bios_GetDisplayStatus(1); 341#endif 342} 343 344#ifdef arc 345/* 346 * Return geometry of the display. Used by pccons.c to set up the 347 * display configuration. 348 */ 349void 350bios_display_info(int *xpos, int *ypos, int *xsize, int *ysize) 351{ 352 353 *xpos = arc_displayinfo.CursorXPosition; 354 *ypos = arc_displayinfo.CursorYPosition; 355 *xsize = arc_displayinfo.CursorMaxXPosition; 356 *ysize = arc_displayinfo.CursorMaxYPosition; 357} 358#endif 359