1 /* $NetBSD: arcbios.c,v 1.19 2020/08/14 16:53:06 skrll 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.19 2020/08/14 16:53:06 skrll 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 <machine/regdef.h> 44 #include <arc/arc/arcbios.h> 45 46 int Bios_Read(int, char *, int, int *); 47 int Bios_Write(int, char *, int, int *); 48 int Bios_Open(char *, int, u_int *); 49 int Bios_Close(u_int); 50 arc_mem_t *Bios_GetMemoryDescriptor(arc_mem_t *); 51 arc_sid_t *Bios_GetSystemId(void); 52 arc_config_t *Bios_GetChild(arc_config_t *); 53 arc_config_t *Bios_GetPeer(arc_config_t *); 54 arc_dsp_stat_t *Bios_GetDisplayStatus(int); 55 56 static void bios_config_id_copy(arc_config_t *, char *, size_t); 57 static void bios_config_component(arc_config_t *); 58 static void bios_config_subtree(arc_config_t *); 59 60 char arc_vendor_id[sizeof(((arc_sid_t *)0)->vendor) + 1]; 61 unsigned char arc_product_id[sizeof(((arc_sid_t *)0)->prodid)]; 62 63 char arc_id[64 + 1]; 64 65 char arc_displayc_id[64 + 1]; /* DisplayController id */ 66 arc_dsp_stat_t arc_displayinfo; /* Save area for display status info. */ 67 68 int arc_cpu_l2cache_size = 0; 69 70 /* 71 * BIOS based console, for early stage. 72 */ 73 74 int biosgetc(dev_t); 75 void biosputc(dev_t, int); 76 77 /* this is to fake out the console routines, while booting. */ 78 struct consdev bioscons = { 79 NULL, NULL, biosgetc, biosputc, nullcnpollc, NULL, NULL, 80 NULL, NODEV, CN_DEAD 81 }; 82 83 int 84 biosgetc(dev_t dev) 85 { 86 int cnt; 87 char buf; 88 89 if (Bios_Read(0, &buf, 1, &cnt) != arc_ESUCCESS) 90 return -1; 91 return buf & 255; 92 } 93 94 void 95 biosputc(dev_t dev, int ch) 96 { 97 int cnt; 98 char buf; 99 100 buf = ch; 101 Bios_Write(1, &buf, 1, &cnt); 102 } 103 104 void 105 bios_init_console(void) 106 { 107 static int initialized = 0; 108 109 if (!initialized) { 110 initialized = 1; 111 /* fake out the console routines, for now */ 112 cn_tab = &bioscons; 113 } 114 } 115 116 /* 117 * Get memory descriptor for the memory configuration and 118 * create a layout database used by pmap init to set up 119 * the memory system. 120 * 121 * Concatenate obvious adjecent segments. 122 */ 123 int 124 bios_configure_memory(int *mem_reserved, phys_ram_seg_t *mem_clusters, 125 int *mem_cluster_cnt_return) 126 { 127 int bios_physmem = 0; /* Total physical memory size */ 128 int mem_cluster_cnt = 0; 129 130 arc_mem_t *descr = NULL; 131 paddr_t seg_start, seg_end; 132 int i, reserved; 133 134 while ((descr = Bios_GetMemoryDescriptor(descr)) != NULL) { 135 seg_start = descr->BasePage * 4096; 136 seg_end = seg_start + descr->PageCount * 4096; 137 138 #ifdef BIOS_MEMORY_DEBUG 139 printf("memory type:%d, 0x%8lx..%8lx, size:%8ld bytes\n", 140 descr->Type, (u_long)seg_start, (u_long)seg_end, 141 (u_long)(seg_end - seg_start)); 142 #endif 143 144 switch (descr->Type) { 145 case BadMemory: /* Have no use for these */ 146 break; 147 148 case ExeceptionBlock: 149 case SystemParameterBlock: 150 case FirmwarePermanent: 151 reserved = 1; 152 goto account_it; 153 154 case FreeMemory: 155 case LoadedProgram: /* This is the loaded kernel */ 156 case FirmwareTemporary: 157 case FreeContigous: 158 reserved = 0; 159 account_it: 160 bios_physmem += descr->PageCount * 4096; 161 162 for (i = 0; i < mem_cluster_cnt; ) { 163 if (mem_reserved[i] == reserved && 164 mem_clusters[i].start == seg_end) 165 seg_end += mem_clusters[i].size; 166 else if (mem_reserved[i] == reserved && 167 mem_clusters[i].start + 168 mem_clusters[i].size == seg_start) 169 seg_start = mem_clusters[i].start; 170 else { /* do not merge the cluster */ 171 i++; 172 continue; 173 } 174 --mem_cluster_cnt; 175 mem_reserved[i] = mem_reserved[mem_cluster_cnt]; 176 mem_clusters[i] = mem_clusters[mem_cluster_cnt]; 177 } 178 /* assert(i == mem_cluster_cnt); */ 179 if (mem_cluster_cnt >= VM_PHYSSEG_MAX) { 180 printf("VM_PHYSSEG_MAX too small\n"); 181 for (;;) 182 ; 183 } 184 mem_reserved[i] = reserved; 185 mem_clusters[i].start = seg_start; 186 mem_clusters[i].size = seg_end - seg_start; 187 mem_cluster_cnt++; 188 break; 189 190 default: /* Unknown type, leave it alone... */ 191 break; 192 } 193 } 194 195 #ifdef BIOS_MEMORY_DEBUG 196 for (i = 0; i < mem_cluster_cnt; i++) 197 printf("mem_clusters[%d] = %d:{ 0x%8lx, 0x%8lx }\n", i, 198 mem_reserved[i], 199 (long)mem_clusters[i].start, 200 (long)mem_clusters[i].size); 201 printf("physmem = %d\n", bios_physmem); 202 #endif 203 204 *mem_cluster_cnt_return = mem_cluster_cnt; 205 return bios_physmem; 206 } 207 208 /* 209 * ARC Firmware present? 210 */ 211 int 212 bios_ident(void) 213 { 214 215 return (ArcBiosBase->magic == ARC_PARAM_BLK_MAGIC) || 216 (ArcBiosBase->magic == ARC_PARAM_BLK_MAGIC_BUG); 217 } 218 219 /* 220 * save various information of BIOS for future use. 221 */ 222 223 static void 224 bios_config_id_copy(arc_config_t *cf, char *string, size_t size) 225 { 226 227 size--; 228 if (size > cf->id_len) 229 size = cf->id_len; 230 memcpy(string, cf->id, size); 231 string[size] = '\0'; 232 } 233 234 static void 235 bios_config_component(arc_config_t *cf) 236 { 237 238 switch (cf->class) { 239 case arc_SystemClass: 240 if (cf->type == arc_System) 241 bios_config_id_copy(cf, arc_id, sizeof(arc_id)); 242 break; 243 case arc_CacheClass: 244 if (cf->type == arc_SecondaryDcache) 245 arc_cpu_l2cache_size = 4096 << (cf->key & 0xffff); 246 break; 247 case arc_ControllerClass: 248 if (cf->type == arc_DisplayController && 249 arc_displayc_id[0] == '\0' /* first found one. XXX */) 250 bios_config_id_copy(cf, arc_displayc_id, 251 sizeof(arc_displayc_id)); 252 break; 253 default: 254 break; 255 } 256 } 257 258 static 259 void bios_config_subtree(arc_config_t *cf) 260 { 261 262 for (cf = Bios_GetChild(cf); cf != NULL; cf = Bios_GetPeer(cf)) { 263 bios_config_component(cf); 264 bios_config_subtree(cf); 265 } 266 } 267 268 void 269 bios_save_info(void) 270 { 271 arc_sid_t *sid; 272 273 sid = Bios_GetSystemId(); 274 if (sid) { 275 memcpy(arc_vendor_id, sid->vendor, sizeof(arc_vendor_id) - 1); 276 arc_vendor_id[sizeof(arc_vendor_id) - 1] = 0; 277 memcpy(arc_product_id, sid->prodid, sizeof(arc_product_id)); 278 } 279 280 bios_config_subtree(NULL); 281 282 #ifdef arc 283 arc_displayinfo = *Bios_GetDisplayStatus(1); 284 #endif 285 } 286 287 #ifdef arc 288 /* 289 * Return geometry of the display. Used by pccons.c to set up the 290 * display configuration. 291 */ 292 void 293 bios_display_info(int *xpos, int *ypos, int *xsize, int *ysize) 294 { 295 296 *xpos = arc_displayinfo.CursorXPosition; 297 *ypos = arc_displayinfo.CursorYPosition; 298 *xsize = arc_displayinfo.CursorMaxXPosition; 299 *ysize = arc_displayinfo.CursorMaxYPosition; 300 } 301 #endif 302