xref: /netbsd-src/sys/arch/arc/arc/arcbios.c (revision 1e12472c159399ddc73e37c251c100c892d074b1)
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
biosgetc(dev_t dev)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
biosputc(dev_t dev,int ch)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
bios_init_console(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
bios_configure_memory(int * mem_reserved,phys_ram_seg_t * mem_clusters,int * mem_cluster_cnt_return)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
bios_ident(void)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
bios_config_id_copy(arc_config_t * cf,char * string,size_t size)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
bios_config_component(arc_config_t * cf)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
bios_config_subtree(arc_config_t * cf)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
bios_save_info(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
bios_display_info(int * xpos,int * ypos,int * xsize,int * ysize)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