Home | History | Annotate | Line # | Download | only in arc
      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