xref: /openbsd-src/sys/arch/hppa/stand/libsa/cmd_hppa.c (revision cf92b8d09c977cd917a08bf5d30d83096035d8e3)
1*cf92b8d0Sjasper /*	$OpenBSD: cmd_hppa.c,v 1.12 2010/12/06 22:51:45 jasper Exp $	*/
24b857dedSmiod 
34b857dedSmiod /*
43e5a02b0Smiod  * Copyright (c) 2002, 2009 Miodrag Vallat
54b857dedSmiod  * All rights reserved.
64b857dedSmiod  *
74b857dedSmiod  * Redistribution and use in source and binary forms, with or without
84b857dedSmiod  * modification, are permitted provided that the following conditions
94b857dedSmiod  * are met:
104b857dedSmiod  * 1. Redistributions of source code must retain the above copyright
114b857dedSmiod  *    notice, this list of conditions and the following disclaimer.
124b857dedSmiod  * 2. Redistributions in binary form must reproduce the above copyright
134b857dedSmiod  *    notice, this list of conditions and the following disclaimer in the
144b857dedSmiod  *    documentation and/or other materials provided with the distribution.
154b857dedSmiod  *
164b857dedSmiod  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
174b857dedSmiod  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
184b857dedSmiod  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19fef2e65fSmickey  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20fef2e65fSmickey  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21fef2e65fSmickey  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22fef2e65fSmickey  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23fef2e65fSmickey  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24fef2e65fSmickey  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25fef2e65fSmickey  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26fef2e65fSmickey  * THE POSSIBILITY OF SUCH DAMAGE.
274b857dedSmiod  */
284b857dedSmiod 
294b857dedSmiod #include <sys/param.h>
304b857dedSmiod /* would come from <sys/param.h> if -D_KERNEL */
314b857dedSmiod #define offsetof(s, e) ((size_t)&((s *)0)->e)
324b857dedSmiod 
334b857dedSmiod #include <machine/iomod.h>
344b857dedSmiod #include <machine/pdc.h>
354b857dedSmiod 
364b857dedSmiod #include <arch/hppa/dev/cpudevs.h>
373e5a02b0Smiod #include <arch/hppa/dev/elroyreg.h>
383e5a02b0Smiod 
393e5a02b0Smiod #include <dev/pci/pcireg.h>
403e5a02b0Smiod #include <dev/pci/pcidevs.h>
414b857dedSmiod 
424b857dedSmiod #include <libsa.h>
434b857dedSmiod #include "cmd.h"
444b857dedSmiod #include "dev_hppa.h"	/* pdc */
454b857dedSmiod 
464b857dedSmiod extern struct stable_storage sstor;
474b857dedSmiod extern int sstorsiz;
484b857dedSmiod 
494b857dedSmiod /* storage sizes we're interested in */
504b857dedSmiod #define	CONSOLEOFFSET \
514b857dedSmiod 	offsetof(struct stable_storage, ss_console)
524b857dedSmiod #define	CONSOLESIZE \
534b857dedSmiod 	(offsetof(struct stable_storage, ss_console) + \
544b857dedSmiod 	 sizeof(struct device_path))
554b857dedSmiod 
564b857dedSmiod #define	KEYBOARDOFFSET \
574b857dedSmiod 	offsetof(struct stable_storage, ss_keyboard)
584b857dedSmiod #define	KEYBOARDSIZE \
594b857dedSmiod 	(offsetof(struct stable_storage, ss_keyboard) + \
604b857dedSmiod 	 sizeof(struct device_path))
614b857dedSmiod 
624b857dedSmiod /*
634b857dedSmiod  * Table for the possible console devices found during the device walk.
644b857dedSmiod  */
654b857dedSmiod struct consoledev {
664b857dedSmiod 	struct device_path dp;
674b857dedSmiod 	int	type;
68c178470fSmiod 	int	iodc_type;
69c178470fSmiod 	int	iodc_model;
704b857dedSmiod };
714b857dedSmiod 
724b857dedSmiod #define	PS2		1
734b857dedSmiod #define	HIL		2
743e5a02b0Smiod #define	USB		3
753e5a02b0Smiod #define	SERIAL		4
763e5a02b0Smiod #define	GRAPHICS	5
774b857dedSmiod 
78c178470fSmiod #define	MAX_SERIALS	4
793e5a02b0Smiod #define	MAX_KEYBOARDS	4
80c178470fSmiod #define	MAX_GRAPHICS	4
814b857dedSmiod 
824b857dedSmiod struct consoledev serials[MAX_SERIALS];
834b857dedSmiod struct consoledev keyboards[MAX_KEYBOARDS];
844b857dedSmiod struct consoledev graphics[MAX_GRAPHICS];
854b857dedSmiod 
864b857dedSmiod int walked;
874b857dedSmiod 
883e5a02b0Smiod void	bus_walk(struct device_path *, int);
893e5a02b0Smiod uint32_t dino_conf_read(u_int, int, int, u_int);
903e5a02b0Smiod uint32_t elroy_conf_read(u_int, int, int, u_int);
913e5a02b0Smiod int	path_match(struct device_path *, struct device_path *);
923e5a02b0Smiod void	path_shift(struct device_path *, int);
933e5a02b0Smiod void	pci_bus_walk(struct device_path *, struct iodc_data *,
943e5a02b0Smiod 	    struct pdc_memmap *);
953e5a02b0Smiod void	register_device(struct consoledev *, int, struct device_path *,
963e5a02b0Smiod 	    struct iodc_data *, int, int);
974b857dedSmiod 
98c4071fd1Smillert int	Xconsole(void);
99c4071fd1Smillert void	print_console(void);
100c4071fd1Smillert int	set_graphics(struct device_path *, int, char *);
101c4071fd1Smillert int	set_serial(struct device_path *, int, char *);
102c4071fd1Smillert int	set_console(struct device_path *);
1034b857dedSmiod 
104c4071fd1Smillert int	Xkeyboard(void);
105c4071fd1Smillert void	print_keyboard(void);
106c4071fd1Smillert int	set_keyboard(struct device_path *);
1074b857dedSmiod 
1084b857dedSmiod struct cmd_table cmd_machine[] = {
1094b857dedSmiod 	{ "console",	CMDT_CMD,	Xconsole },
1104b857dedSmiod 	{ "keyboard",	CMDT_CMD,	Xkeyboard },
1114b857dedSmiod 	{ NULL, },
1124b857dedSmiod };
1134b857dedSmiod 
1144b857dedSmiod /* value to console speed table */
1153e5a02b0Smiod const int i_speeds[] = {
1164b857dedSmiod 	50,
1174b857dedSmiod 	75,
1184b857dedSmiod 	110,
1194b857dedSmiod 	150,
1204b857dedSmiod 	300,
1214b857dedSmiod 	600,
1224b857dedSmiod 	1200,
1234b857dedSmiod 	2400,
1244b857dedSmiod 	4800,
1254b857dedSmiod 	7200,
1264b857dedSmiod 	9600,
127c178470fSmiod 	19200,
128c178470fSmiod 	38400,
129c178470fSmiod 	57600,
130c178470fSmiod 	115200,
131c178470fSmiod 	230400,
1324b857dedSmiod };
1334b857dedSmiod 
1343e5a02b0Smiod const char *c_speeds[] = {
1354b857dedSmiod 	"50",
1364b857dedSmiod 	"75",
1374b857dedSmiod 	"110",
1384b857dedSmiod 	"150",
1394b857dedSmiod 	"300",
1404b857dedSmiod 	"600",
1414b857dedSmiod 	"1200",
1424b857dedSmiod 	"2400",
1434b857dedSmiod 	"4800",
1444b857dedSmiod 	"7200",
1454b857dedSmiod 	"9600",
146c178470fSmiod 	"19200",
147c178470fSmiod 	"38400",
148c178470fSmiod 	"57600",
149c178470fSmiod 	"115200",
150c178470fSmiod 	"230400",
1514b857dedSmiod };
1524b857dedSmiod 
1534b857dedSmiod /* values to console parity table */
1543e5a02b0Smiod const char *parities[] = {
1554b857dedSmiod 	"none",
1564b857dedSmiod 	"odd",
1574b857dedSmiod 	"<unknown parity>",
1584b857dedSmiod 	"even",
1594b857dedSmiod };
1604b857dedSmiod 
1614b857dedSmiod /*
1624b857dedSmiod  * C O N S O L E   S E T T I N G S
1634b857dedSmiod  */
1644b857dedSmiod 
1654b857dedSmiod void
print_console()1664b857dedSmiod print_console()
1674b857dedSmiod {
1684b857dedSmiod 	int port, mode, speed, parity, bits;
1694b857dedSmiod 	int i;
1704b857dedSmiod 
1714b857dedSmiod #ifdef DEBUG
1724b857dedSmiod 	printf("console flags %x mod %x bc %d/%d/%d/%d/%d/%d\n",
1734b857dedSmiod 	    sstor.ss_console.dp_flags,
1744b857dedSmiod 	    sstor.ss_console.dp_mod,
1754b857dedSmiod 	    sstor.ss_console.dp_bc[0],
1764b857dedSmiod 	    sstor.ss_console.dp_bc[1],
1774b857dedSmiod 	    sstor.ss_console.dp_bc[2],
1784b857dedSmiod 	    sstor.ss_console.dp_bc[3],
1794b857dedSmiod 	    sstor.ss_console.dp_bc[4],
1804b857dedSmiod 	    sstor.ss_console.dp_bc[5]);
1814b857dedSmiod 
1824b857dedSmiod 	printf("console path %x/%x/%x/%x/%x/%x\n",
1834b857dedSmiod 	    sstor.ss_console.dp_layers[0],
1844b857dedSmiod 	    sstor.ss_console.dp_layers[1],
1854b857dedSmiod 	    sstor.ss_console.dp_layers[2],
1864b857dedSmiod 	    sstor.ss_console.dp_layers[3],
1874b857dedSmiod 	    sstor.ss_console.dp_layers[4],
1884b857dedSmiod 	    sstor.ss_console.dp_layers[5]);
1894b857dedSmiod #endif
1904b857dedSmiod 
1914b857dedSmiod 	printf("Console path: ");
1924b857dedSmiod 
1934b857dedSmiod 	/* look for a serial console */
1944b857dedSmiod 	for (port = i = 0; i < MAX_SERIALS; i++)
1953e5a02b0Smiod 		if (path_match(&serials[i].dp, &sstor.ss_console)) {
1964b857dedSmiod 			port = i + 1;
1974b857dedSmiod 			break;
1984b857dedSmiod 		}
1994b857dedSmiod 
2004b857dedSmiod 	if (port == 0) {
2014b857dedSmiod 		/*
2024b857dedSmiod 		 * Graphics console
2034b857dedSmiod 		 */
2044b857dedSmiod 
2054b857dedSmiod 		for (port = i = 0; i < MAX_GRAPHICS; i++)
2063e5a02b0Smiod 			if (path_match(&graphics[i].dp, &sstor.ss_console)) {
2074b857dedSmiod 				port = i;
2084b857dedSmiod 				break;
2094b857dedSmiod 			}
2104b857dedSmiod 
2114b857dedSmiod 		/*
2124b857dedSmiod 		 * If the console could still not be identified, consider
213d783d4a7Smiod 		 * it is a simplified encoding for the default graphics
2144b857dedSmiod 		 * console. Hence port == 0, no need to check.
2154b857dedSmiod 		 */
2164b857dedSmiod 		if (port == 0)
2174b857dedSmiod 			printf("graphics");
2184b857dedSmiod 		else
2194b857dedSmiod 			printf("graphics_%d", port);
2204b857dedSmiod 
2214b857dedSmiod 		mode = sstor.ss_console.dp_layers[0];
2224b857dedSmiod 		if (mode != 0)
2234b857dedSmiod 			printf(".%d", mode);
2244b857dedSmiod 	} else {
2254b857dedSmiod 		/*
2264b857dedSmiod 		 * Serial console
2274b857dedSmiod 		 */
2284b857dedSmiod 
229c178470fSmiod 		if (port == 1)
230c178470fSmiod 			printf("rs232");
231c178470fSmiod 		else
232c178470fSmiod 			printf("rs232_%d", port);
2334b857dedSmiod 
2344b857dedSmiod 		speed = PZL_SPEED(sstor.ss_console.dp_layers[0]);
235c178470fSmiod 		printf(".%d", i_speeds[speed]);
2364b857dedSmiod 
2374b857dedSmiod 		bits = PZL_BITS(sstor.ss_console.dp_layers[0]);
2384b857dedSmiod 		printf(".%d", bits);
2394b857dedSmiod 
2404b857dedSmiod 		parity = PZL_PARITY(sstor.ss_console.dp_layers[0]);
2414b857dedSmiod 		printf(".%s", parities[parity]);
2424b857dedSmiod 	}
2434b857dedSmiod 
2444b857dedSmiod 	printf("\n");
2454b857dedSmiod }
2464b857dedSmiod 
2474b857dedSmiod int
set_graphics(console,port,arg)2484b857dedSmiod set_graphics(console, port, arg)
2494b857dedSmiod 	struct device_path *console;
2504b857dedSmiod 	int port;
2514b857dedSmiod 	char *arg;
2524b857dedSmiod {
2534b857dedSmiod 	int maxmode, mode = 0;
2544b857dedSmiod 	char *digit;
2554b857dedSmiod 
2564b857dedSmiod 	/* head */
2574b857dedSmiod 	if (graphics[port].type == 0) {
2584b857dedSmiod 		printf("no such device found\n");
2594b857dedSmiod 		return 0;
2604b857dedSmiod 	}
2614b857dedSmiod 
2624b857dedSmiod 	/* mode */
2634b857dedSmiod 	if (arg != NULL) {
2644b857dedSmiod 		for (digit = arg; *digit != '\0'; digit++) {
2654b857dedSmiod 			if (*digit >= '0' && *digit <= '9')
2664b857dedSmiod 				mode = 10 * mode + (*digit - '0');
2674b857dedSmiod 			else {
2683e5a02b0Smiod 				printf("invalid mode specification, %s\n", arg);
2694b857dedSmiod 				return 0;
2704b857dedSmiod 			}
2714b857dedSmiod 		}
2724b857dedSmiod 
2734b857dedSmiod 		if (mode <= 0) {
2743e5a02b0Smiod 			printf("invalid mode specification, %s\n", arg);
2754b857dedSmiod 			return 0;
2764b857dedSmiod 		}
2774b857dedSmiod 	}
2784b857dedSmiod 
2794b857dedSmiod 	/*
2804b857dedSmiod 	 * If we are just changing the mode of the same graphics
2814b857dedSmiod 	 * console, check that our mode is in the valid range.
2824b857dedSmiod 	 */
2833e5a02b0Smiod 	if (path_match(&graphics[port].dp, &sstor.ss_console)) {
2844b857dedSmiod 		maxmode = sstor.ss_console.dp_layers[1];
2854b857dedSmiod 
2864b857dedSmiod 		/* pick back same mode if unspecified */
2874b857dedSmiod 		if (mode == 0)
2884b857dedSmiod 			mode = sstor.ss_console.dp_layers[0];
2894b857dedSmiod 
2904b857dedSmiod 		if (mode > maxmode) {
2914b857dedSmiod 			printf("invalid mode value, available range is 1-%d\n",
2924b857dedSmiod 			    maxmode);
2934b857dedSmiod 			return 0;
2944b857dedSmiod 		}
2954b857dedSmiod 	} else {
2964b857dedSmiod 		if (mode == 0)
2974b857dedSmiod 			mode = 1;
2984b857dedSmiod 		maxmode = mode;
2994b857dedSmiod 	}
3004b857dedSmiod 
3014b857dedSmiod 	*console = graphics[port].dp;
3024b857dedSmiod 	console->dp_layers[0] = mode;
3034b857dedSmiod 	console->dp_layers[1] = maxmode;
3044b857dedSmiod 	console->dp_layers[2] = console->dp_layers[3] =
3054b857dedSmiod 	console->dp_layers[4] = console->dp_layers[5] = 0;
3064b857dedSmiod 
3074b857dedSmiod 	return 1;
3084b857dedSmiod }
3094b857dedSmiod 
3104b857dedSmiod int
set_serial(console,port,arg)3114b857dedSmiod set_serial(console, port, arg)
3124b857dedSmiod 	struct device_path *console;
3134b857dedSmiod 	int port;
3144b857dedSmiod 	char *arg;
3154b857dedSmiod {
3164b857dedSmiod 	char *dot;
3174b857dedSmiod 	int i;
3184b857dedSmiod 	int speed, parity, bits;
3194b857dedSmiod 
3204b857dedSmiod 	/* port */
3214b857dedSmiod 	port--;
3224b857dedSmiod 	if (serials[port].type == 0) {
3234b857dedSmiod 		printf("no such device found\n");
3244b857dedSmiod 		return 0;
3254b857dedSmiod 	}
3264b857dedSmiod 
3274b857dedSmiod 	/* speed */
3284b857dedSmiod 	dot = strchr(arg, '.');
3294b857dedSmiod 	if (dot != NULL)
3304b857dedSmiod 		*dot++ = '\0';
3314b857dedSmiod 
332d783d4a7Smiod 	speed = 0;
3334b857dedSmiod 	if (arg == NULL || *arg == '\0') {
334*cf92b8d0Sjasper 		for (i = 0; i < nitems(i_speeds); i++)
3354b857dedSmiod 			if (i_speeds[i] == 9600) {
3364b857dedSmiod 				speed = i;
3374b857dedSmiod 				break;
3384b857dedSmiod 			}
3394b857dedSmiod 	} else {
340*cf92b8d0Sjasper 		for (i = 0; i < nitems(c_speeds); i++)
3414b857dedSmiod 			if (strcmp(arg, c_speeds[i]) == 0) {
3424b857dedSmiod 				speed = i;
3434b857dedSmiod 				break;
3444b857dedSmiod 			}
3454b857dedSmiod 		if (speed == 0) {
3464b857dedSmiod 			printf("invalid speed specification, %s\n", arg);
3474b857dedSmiod 			return 0;
3484b857dedSmiod 		}
3494b857dedSmiod 	}
3504b857dedSmiod 
3514b857dedSmiod 	/* data bits */
3524b857dedSmiod 	arg = dot;
3534b857dedSmiod 	dot = strchr(arg, '.');
3544b857dedSmiod 
3554b857dedSmiod 	if (arg == NULL || *arg == '\0')
3564b857dedSmiod 		bits = 8;
3574b857dedSmiod 	else {
3584b857dedSmiod 		if (dot == arg + 1)
3594b857dedSmiod 			bits = *arg - '0';
3604b857dedSmiod 		else
3614b857dedSmiod 			bits = 0;
3624b857dedSmiod 
3634b857dedSmiod 		if (bits < 5 || bits > 8) {
3644b857dedSmiod 			printf("invalid bits specification, %s\n", arg);
3654b857dedSmiod 			return 0;
3664b857dedSmiod 		}
3674b857dedSmiod 	}
3684b857dedSmiod 	if (dot != NULL)
3694b857dedSmiod 		*dot++ = '\0';
3704b857dedSmiod 
3714b857dedSmiod 	/* parity */
3724b857dedSmiod 	arg = dot;
3734b857dedSmiod 	if (arg == NULL || *arg == '\0')
3744b857dedSmiod 		parity = 0;	/* none */
3754b857dedSmiod 	else {
3764b857dedSmiod 		parity = -1;
3774b857dedSmiod 		for (i = 0; i <= 3; i++)
3784b857dedSmiod 			if (strcmp(arg, parities[i]) == 0) {
3794b857dedSmiod 				parity = i;
3804b857dedSmiod 				break;
3814b857dedSmiod 			}
3824b857dedSmiod 		if (parity == 2)
3834b857dedSmiod 			parity = -1;	/* unknown parity */
3844b857dedSmiod 	}
3854b857dedSmiod 	if (parity < 0) {
3864b857dedSmiod 		printf("invalid parity specification, %s\n", arg);
3874b857dedSmiod 		return 0;
3884b857dedSmiod 	}
3894b857dedSmiod 
3904b857dedSmiod 	*console = serials[port].dp;
3914b857dedSmiod 	console->dp_layers[0] = PZL_ENCODE(bits, parity, speed);
3924b857dedSmiod 
3934b857dedSmiod 	return 1;
3944b857dedSmiod }
3954b857dedSmiod 
3964b857dedSmiod int
set_console(console)3974b857dedSmiod set_console(console)
3984b857dedSmiod 	struct device_path *console;
3994b857dedSmiod {
4004b857dedSmiod 	char *arg = cmd.argv[1], *dot;
401c178470fSmiod 	int port;
4024b857dedSmiod 
4034b857dedSmiod 	/* extract first word */
4044b857dedSmiod 	dot = strchr(arg, '.');
4054b857dedSmiod 	if (dot != NULL)
4064b857dedSmiod 		*dot++ = '\0';
4074b857dedSmiod 
4084b857dedSmiod 	/*
4094b857dedSmiod 	 * Graphics console
4104b857dedSmiod 	 */
4114b857dedSmiod 	if (strcmp(arg, "graphics") == 0)
4124b857dedSmiod 		return set_graphics(console, 0, dot);
413c178470fSmiod 	if (strncmp(arg, "graphics_", 9) == 0) {
414c178470fSmiod 		port = arg[9] - '0';
415c178470fSmiod 		if (port > 0 && port < MAX_GRAPHICS)
416c178470fSmiod 			return set_graphics(console, port, dot);
417c178470fSmiod 	}
4184b857dedSmiod 
4194b857dedSmiod 	/*
4204b857dedSmiod 	 * Serial console
4214b857dedSmiod 	 */
4224b857dedSmiod 	if (strcmp(arg, "rs232") == 0)
4234b857dedSmiod 		return set_serial(console, 1, dot);
424c178470fSmiod 	if (strncmp(arg, "rs232_", 6) == 0) {
425c178470fSmiod 		port = arg[6] - '0';
426c178470fSmiod 		if (port > 0 && port <= MAX_SERIALS)
427c178470fSmiod 			return set_serial(console, port, dot);
428c178470fSmiod 	}
4294b857dedSmiod 
4304b857dedSmiod 	printf("invalid device specification, %s\n", arg);
4314b857dedSmiod 	return 0;
4324b857dedSmiod }
4334b857dedSmiod 
4344b857dedSmiod int
Xconsole()4354b857dedSmiod Xconsole()
4364b857dedSmiod {
4374b857dedSmiod 	struct device_path console;
4384b857dedSmiod 	int rc;
4394b857dedSmiod 
4404b857dedSmiod 	/* walk the device list if not already done */
4414b857dedSmiod 	if (walked == 0) {
4423e5a02b0Smiod 		bus_walk(NULL, MAXMODBUS);
4434b857dedSmiod 		walked++;
4444b857dedSmiod 	}
4454b857dedSmiod 
4464b857dedSmiod 	if (sstorsiz < CONSOLESIZE) {
4474b857dedSmiod 		printf("no console information in stable storage\n");
4484b857dedSmiod 		return 0;
4494b857dedSmiod 	}
4504b857dedSmiod 
4514b857dedSmiod 	if (cmd.argc == 1) {
4524b857dedSmiod 		print_console();
4534b857dedSmiod 	} else {
4544b857dedSmiod 		console = sstor.ss_console;
4554b857dedSmiod 		if (set_console(&console)) {
4564b857dedSmiod 			if (memcmp(&sstor.ss_console, &console,
4574b857dedSmiod 			    sizeof console) != 0) {
4584b857dedSmiod 				sstor.ss_console = console;
4594b857dedSmiod 
4604b857dedSmiod 				/* alea jacta est */
4614b857dedSmiod 				rc = (*pdc)(PDC_STABLE, PDC_STABLE_WRITE,
4624b857dedSmiod 				    CONSOLEOFFSET, &sstor.ss_console,
4634b857dedSmiod 				    sizeof(sstor.ss_console));
4644b857dedSmiod 				if (rc != 0) {
4653e5a02b0Smiod 					printf("failed to save console"
4663e5a02b0Smiod 					    " settings, error %d\n", rc);
4674b857dedSmiod 					/* read sstor again for safety */
4684b857dedSmiod 					(*pdc)(PDC_STABLE, PDC_STABLE_READ,
4694b857dedSmiod 					    CONSOLEOFFSET, &sstor.ss_console,
4704b857dedSmiod 					    sizeof(sstor.ss_console));
4714b857dedSmiod 				} else
4724b857dedSmiod 					printf("you will need to power-cycle "
4734b857dedSmiod 					       "your machine for the changes "
4744b857dedSmiod 					       "to take effect.\n");
4754b857dedSmiod 			}
4764b857dedSmiod 			print_console();
4774b857dedSmiod 		}
4784b857dedSmiod 	}
4794b857dedSmiod 
4804b857dedSmiod 	return 0;
4814b857dedSmiod }
4824b857dedSmiod 
4834b857dedSmiod /*
4844b857dedSmiod  * K E Y B O A R D   S E T T I N G S
4854b857dedSmiod  */
4864b857dedSmiod 
4874b857dedSmiod void
print_keyboard()4884b857dedSmiod print_keyboard()
4894b857dedSmiod {
4904b857dedSmiod 	int type;
4914b857dedSmiod 	int i;
4924b857dedSmiod 
4934b857dedSmiod #ifdef DEBUG
4944b857dedSmiod 	printf("keyboard flags %x mod %x bc %d/%d/%d/%d/%d/%d\n",
4954b857dedSmiod 	    sstor.ss_keyboard.dp_flags,
4964b857dedSmiod 	    sstor.ss_keyboard.dp_mod,
4974b857dedSmiod 	    sstor.ss_keyboard.dp_bc[0],
4984b857dedSmiod 	    sstor.ss_keyboard.dp_bc[1],
4994b857dedSmiod 	    sstor.ss_keyboard.dp_bc[2],
5004b857dedSmiod 	    sstor.ss_keyboard.dp_bc[3],
5014b857dedSmiod 	    sstor.ss_keyboard.dp_bc[4],
5024b857dedSmiod 	    sstor.ss_keyboard.dp_bc[5]);
5034b857dedSmiod 
5044b857dedSmiod 	printf("keyboard path %x/%x/%x/%x/%x/%x\n",
5054b857dedSmiod 	    sstor.ss_keyboard.dp_layers[0],
5064b857dedSmiod 	    sstor.ss_keyboard.dp_layers[1],
5074b857dedSmiod 	    sstor.ss_keyboard.dp_layers[2],
5084b857dedSmiod 	    sstor.ss_keyboard.dp_layers[3],
5094b857dedSmiod 	    sstor.ss_keyboard.dp_layers[4],
5104b857dedSmiod 	    sstor.ss_keyboard.dp_layers[5]);
5114b857dedSmiod #endif
5124b857dedSmiod 
5134b857dedSmiod 	printf("Keyboard path: ");
5144b857dedSmiod 
5154b857dedSmiod 	for (type = i = 0; i < MAX_KEYBOARDS; i++)
5163e5a02b0Smiod 		if (path_match(&keyboards[i].dp, &sstor.ss_keyboard)) {
5174b857dedSmiod 			type = keyboards[i].type;
5184b857dedSmiod 			break;
5194b857dedSmiod 		}
5204b857dedSmiod 
5214b857dedSmiod 	switch (type) {
5223e5a02b0Smiod 	case USB:
5233e5a02b0Smiod 		printf("usb");
5243e5a02b0Smiod 		break;
5254b857dedSmiod 	case HIL:
5264b857dedSmiod 		printf("hil");
5274b857dedSmiod 		break;
5284b857dedSmiod 	case PS2:
5294b857dedSmiod 		printf("ps2");
5304b857dedSmiod 		break;
5314b857dedSmiod 	default:
5324b857dedSmiod 		printf("unknown");
5334b857dedSmiod 		break;
5344b857dedSmiod 	}
5354b857dedSmiod 
5364b857dedSmiod 	printf("\n");
5374b857dedSmiod }
5384b857dedSmiod 
5394b857dedSmiod int
set_keyboard(keyboard)5404b857dedSmiod set_keyboard(keyboard)
5414b857dedSmiod 	struct device_path *keyboard;
5424b857dedSmiod {
5434b857dedSmiod 	int i;
5444b857dedSmiod 	char *arg = cmd.argv[1];
5454b857dedSmiod 	int type;
5464b857dedSmiod 
5474b857dedSmiod 	if (strcmp(arg, "hil") == 0)
5484b857dedSmiod 		type = HIL;
5494b857dedSmiod 	else if (strcmp(arg, "ps2") == 0)
5504b857dedSmiod 		type = PS2;
5513e5a02b0Smiod 	else if (strcmp(arg, "usb") == 0)
5523e5a02b0Smiod 		type = USB;
5534b857dedSmiod 	else {
5543e5a02b0Smiod 		/* XXX should probably handle multiple USB controllers */
5554b857dedSmiod 		printf("invalid device specification, %s\n", arg);
5564b857dedSmiod 		return 0;
5574b857dedSmiod 	}
5584b857dedSmiod 
5594b857dedSmiod 	for (i = 0; i < MAX_KEYBOARDS; i++)
5604b857dedSmiod 		if (keyboards[i].type == type) {
5614b857dedSmiod 			*keyboard = keyboards[i].dp;
5624b857dedSmiod 			return 1;
5634b857dedSmiod 		}
5644b857dedSmiod 
5654b857dedSmiod 	printf("no such device found\n");
5664b857dedSmiod 	return 0;
5674b857dedSmiod }
5684b857dedSmiod 
5694b857dedSmiod int
Xkeyboard()5704b857dedSmiod Xkeyboard()
5714b857dedSmiod {
5724b857dedSmiod 	struct device_path keyboard;
5734b857dedSmiod 	int rc;
5744b857dedSmiod 
5754b857dedSmiod 	/* walk the device list if not already done */
5764b857dedSmiod 	if (walked == 0) {
5773e5a02b0Smiod 		bus_walk(NULL, MAXMODBUS);
5784b857dedSmiod 		walked++;
5794b857dedSmiod 	}
5804b857dedSmiod 
5814b857dedSmiod 	if (sstorsiz < KEYBOARDSIZE) {
5824b857dedSmiod 		printf("no keyboard information in stable storage\n");
5834b857dedSmiod 		return 0;
5844b857dedSmiod 	}
5854b857dedSmiod 
5864b857dedSmiod 	if (cmd.argc == 1) {
5874b857dedSmiod 		print_keyboard();
5884b857dedSmiod 	} else {
5894b857dedSmiod 		keyboard = sstor.ss_keyboard;
5904b857dedSmiod 		if (set_keyboard(&keyboard)) {
5914b857dedSmiod 			if (memcmp(&sstor.ss_keyboard, &keyboard,
5924b857dedSmiod 			    sizeof keyboard) != 0) {
5934b857dedSmiod 				sstor.ss_keyboard = keyboard;
5944b857dedSmiod 
5954b857dedSmiod 				/* alea jacta est */
5964b857dedSmiod 				rc = (*pdc)(PDC_STABLE, PDC_STABLE_WRITE,
5974b857dedSmiod 				    KEYBOARDOFFSET, &sstor.ss_keyboard,
5984b857dedSmiod 				    sizeof(sstor.ss_keyboard));
5994b857dedSmiod 				if (rc != 0) {
6003e5a02b0Smiod 					printf("failed to save keyboard"
6013e5a02b0Smiod 					    " settings, error %d\n", rc);
6024b857dedSmiod 					/* read sstor again for safety */
6034b857dedSmiod 					(*pdc)(PDC_STABLE, PDC_STABLE_READ,
6044b857dedSmiod 					    KEYBOARDOFFSET, &sstor.ss_keyboard,
6054b857dedSmiod 					    sizeof(sstor.ss_keyboard));
6064b857dedSmiod 				} else
6074b857dedSmiod 					printf("you will need to power-cycle "
6084b857dedSmiod 					       "your machine for the changes "
6094b857dedSmiod 					       "to take effect.\n");
6104b857dedSmiod 			}
6114b857dedSmiod 			print_keyboard();
6124b857dedSmiod 		}
6134b857dedSmiod 	}
6144b857dedSmiod 
6154b857dedSmiod 	return 0;
6164b857dedSmiod }
6174b857dedSmiod 
6184b857dedSmiod /*
6194b857dedSmiod  * U T I L I T I E S
6204b857dedSmiod  */
6214b857dedSmiod 
6224b857dedSmiod /*
6234b857dedSmiod  * Bus walker.
6244b857dedSmiod  * This routine will walk all the modules on a given bus, registering
6254b857dedSmiod  * serial ports, keyboard and graphics devices as they are found.
6264b857dedSmiod  */
6274b857dedSmiod void
bus_walk(struct device_path * idp,int maxmod)6283e5a02b0Smiod bus_walk(struct device_path *idp, int maxmod)
6294b857dedSmiod {
6304b857dedSmiod 	struct device_path dp;
6314b857dedSmiod 	struct pdc_memmap memmap;
6324b857dedSmiod 	struct iodc_data mptr;
633fa7c453aSmickey 	int err, i, kluge_ps2 = 0;	/* kluge, see below */
6344b857dedSmiod 
6353e5a02b0Smiod 	for (i = 0; i < maxmod; i++) {
636fa7c453aSmickey 		if (idp) {
6373e5a02b0Smiod 			dp = *idp;
6383e5a02b0Smiod 			path_shift(&dp, i);
639fa7c453aSmickey 		} else {
6403e5a02b0Smiod 			dp.dp_flags = 0;
641fa7c453aSmickey 			dp.dp_bc[0] = dp.dp_bc[1] = dp.dp_bc[2] =
642fa7c453aSmickey 			dp.dp_bc[3] = dp.dp_bc[4] = dp.dp_bc[5] = -1;
6433e5a02b0Smiod 			dp.dp_mod = i;
6443e5a02b0Smiod 			bzero(&dp.dp_layers, sizeof dp.dp_layers);
6454b857dedSmiod 		}
6464b857dedSmiod 
647fa7c453aSmickey 		if ((pdc)(PDC_MEMMAP, PDC_MEMMAP_HPA, &memmap, &dp) < 0 &&
648fa7c453aSmickey 		    (pdc)(PDC_SYSMAP, PDC_SYSMAP_HPA, &memmap, &dp) < 0)
649fa7c453aSmickey 			continue;
650fa7c453aSmickey 
651fa7c453aSmickey 		if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, &pdcbuf, memmap.hpa,
652fa7c453aSmickey 		    IODC_DATA, &mptr, sizeof(mptr))) < 0)
653fa7c453aSmickey 			continue;
654fa7c453aSmickey 
6554b857dedSmiod #ifdef DEBUG
656fa7c453aSmickey 		printf("device %d/%d/%d/%d/%d/%d "
657fa7c453aSmickey 		    "flags %d mod %x type %x model %x\n",
658fa7c453aSmickey 		    dp.dp_bc[0], dp.dp_bc[1], dp.dp_bc[2], dp.dp_bc[3],
659fa7c453aSmickey 		    dp.dp_bc[4], dp.dp_bc[5], dp.dp_flags, dp.dp_mod,
6604b857dedSmiod 		    mptr.iodc_type, mptr.iodc_sv_model);
6614b857dedSmiod #endif
6623e5a02b0Smiod 
6634b857dedSmiod 		/*
6644b857dedSmiod 		 * If the device can be considered as a valid rs232,
6654b857dedSmiod 		 * graphics console or keyboard, register it.
6664b857dedSmiod 		 *
667c178470fSmiod 		 * Unfortunately, devices which should be considered as
668c178470fSmiod 		 * ``main'' aren't necessarily seen first.
669c178470fSmiod 		 * The rules we try to enforce here are as follows:
670c178470fSmiod 		 * - GIO PS/2 ports wins over any other PS/2 port.
671c178470fSmiod 		 * - the first GIO serial found wins over any other
672c178470fSmiod 		 *   serial port.
673c178470fSmiod 		 * The second rule is a bit tricky to achieve, since on
674c178470fSmiod 		 * some machines (for example, 715/100XC), the two serial
675c178470fSmiod 		 * ports are not seen as attached to the same busses...
6764b857dedSmiod 		 */
6774b857dedSmiod 		switch (mptr.iodc_type) {
678fa7c453aSmickey 		case HPPA_TYPE_BCPORT:
6793e5a02b0Smiod 			bus_walk(&dp, MAXMODBUS);
680fa7c453aSmickey 			break;
681fa7c453aSmickey 		case HPPA_TYPE_BRIDGE:
6823e5a02b0Smiod 			if (mptr.iodc_sv_model == HPPA_BRIDGE_DINO) {
6833e5a02b0Smiod 				pci_bus_walk(&dp, &mptr, &memmap);
6843e5a02b0Smiod 				break;
685fa7c453aSmickey 			}
6863e5a02b0Smiod 			/* FALLTHROUGH */
6873e5a02b0Smiod 		case HPPA_TYPE_BHA:
6883e5a02b0Smiod 			/* if there was no phantomas(4) here */
6893e5a02b0Smiod 			if (dp.dp_bc[5] == -1)
6903e5a02b0Smiod 				path_shift(&dp, 0);
6913e5a02b0Smiod 			bus_walk(&dp, MAXMODBUS);
692fa7c453aSmickey 			break;
6934b857dedSmiod 		case HPPA_TYPE_ADIRECT:
6944b857dedSmiod 			switch (mptr.iodc_sv_model) {
6954b857dedSmiod 			case HPPA_ADIRECT_RS232:
6964b857dedSmiod 				register_device(serials, MAX_SERIALS,
697c178470fSmiod 				    &dp, &mptr, SERIAL, 0);
6984b857dedSmiod 				break;
6994b857dedSmiod 			case HPPA_ADIRECT_HIL:
7004b857dedSmiod 				register_device(keyboards, MAX_KEYBOARDS,
701c178470fSmiod 				    &dp, &mptr, HIL, 0);
7024b857dedSmiod 				break;
7034b857dedSmiod 			case HPPA_ADIRECT_PEACOCK:
7044b857dedSmiod 			case HPPA_ADIRECT_LEONARDO:
7054b857dedSmiod 				register_device(graphics, MAX_GRAPHICS,
706c178470fSmiod 				    &dp, &mptr, GRAPHICS, 0);
7074b857dedSmiod 				break;
7084b857dedSmiod 			}
7094b857dedSmiod 			break;
7104b857dedSmiod 		case HPPA_TYPE_FIO:
7114b857dedSmiod 			switch (mptr.iodc_sv_model) {
7124b857dedSmiod 			case HPPA_FIO_HIL:
7134b857dedSmiod 				register_device(keyboards, MAX_KEYBOARDS,
714c178470fSmiod 				    &dp, &mptr, HIL, 0);
7154b857dedSmiod 				break;
7163e5a02b0Smiod 			case HPPA_FIO_RS232:	/* com@gsc */
7174b857dedSmiod 				register_device(serials, MAX_SERIALS,
718c178470fSmiod 				    &dp, &mptr, SERIAL, 0);
7194b857dedSmiod 				break;
7204b857dedSmiod 			case HPPA_FIO_DINOPCK:
7214b857dedSmiod 				register_device(keyboards, MAX_KEYBOARDS,
722c178470fSmiod 				    &dp, &mptr, PS2, 0);
7234b857dedSmiod 				break;
7244b857dedSmiod 			case HPPA_FIO_GPCIO:
7254b857dedSmiod 				/*
7264b857dedSmiod 				 * KLUGE! At this point, there is no way to
7274b857dedSmiod 				 * know if this port is the keyboard port or
7284b857dedSmiod 				 * the mouse port.
7294b857dedSmiod 				 * Let's assume the first port found is the
7304b857dedSmiod 				 * keyboard, and ignore the others.
7314b857dedSmiod 				 */
7324b857dedSmiod 				if (kluge_ps2 != 0)
7334b857dedSmiod 					break;
7344b857dedSmiod 				register_device(keyboards, MAX_KEYBOARDS,
735c178470fSmiod 				    &dp, &mptr, PS2, 1);
7364b857dedSmiod 				kluge_ps2++;
7374b857dedSmiod 				break;
7383e5a02b0Smiod 			case HPPA_FIO_GRS232:	/* com@dino, com@gsc */
739c178470fSmiod 			{
740c178470fSmiod 				int j, first;
741c178470fSmiod 
742c178470fSmiod 				/*
743c178470fSmiod 				 * If a GIO serial port is already registered,
744d783d4a7Smiod 				 * register as extra port...
745c178470fSmiod 				 */
746c178470fSmiod 				first = 1;
747c178470fSmiod 				for (j = 0; j < MAX_SERIALS; j++)
748c178470fSmiod 					if (serials[j].type == SERIAL &&
749c178470fSmiod 					    serials[j].iodc_type ==
750c178470fSmiod 					      HPPA_TYPE_FIO &&
751c178470fSmiod 					    serials[j].iodc_model ==
752c178470fSmiod 					      HPPA_FIO_GRS232) {
753c178470fSmiod 						first = 0;
754c178470fSmiod 						break;
755c178470fSmiod 					}
756c178470fSmiod 
7574b857dedSmiod 				register_device(serials, MAX_SERIALS,
758c178470fSmiod 				    &dp, &mptr, SERIAL, first);
759c178470fSmiod 			}
7604b857dedSmiod 				break;
7614b857dedSmiod 			case HPPA_FIO_SGC:
7624b857dedSmiod 				register_device(graphics, MAX_GRAPHICS,
763c178470fSmiod 				    &dp, &mptr, GRAPHICS, 0);
7644b857dedSmiod 				break;
7654b857dedSmiod 			case HPPA_FIO_GSGC:
7664b857dedSmiod 				register_device(graphics, MAX_GRAPHICS,
767c178470fSmiod 				    &dp, &mptr, GRAPHICS, 1);
7684b857dedSmiod 				break;
7693e5a02b0Smiod #if 0 /* can these really be used as console? */
7703e5a02b0Smiod 			case HPPA_FIO_GRJ16:	/* com@gsc */
7713e5a02b0Smiod 				register_device(serials, MAX_SERIALS,
7723e5a02b0Smiod 				    &dp, &mptr, SERIAL, 0);
7733e5a02b0Smiod 				break;
7743e5a02b0Smiod #endif
7753e5a02b0Smiod 			}
7763e5a02b0Smiod 			break;
7773e5a02b0Smiod 		case HPPA_TYPE_IOA:
7783e5a02b0Smiod 			switch (mptr.iodc_sv_model) {
7793e5a02b0Smiod 			case HPPA_IOA_UTURN:
7803e5a02b0Smiod 				bus_walk(&dp, MAXMODBUS - 1);
7813e5a02b0Smiod 				break;
7824b857dedSmiod 			}
7834b857dedSmiod 			break;
7844b857dedSmiod 		}
7854b857dedSmiod 	}
7864b857dedSmiod }
7874b857dedSmiod 
7883e5a02b0Smiod /*
7893e5a02b0Smiod  * PCI bus walker.
7903e5a02b0Smiod  * The PDC device enumeration stops at the PCI bridge level, however
7913e5a02b0Smiod  * in order to properly handle console path on systems with PCI graphics
7923e5a02b0Smiod  * and USB controllers, it is necessary to dig further.
7933e5a02b0Smiod  *
7943e5a02b0Smiod  * Note that there are apparently PDC routines to access bridge configuration
7953e5a02b0Smiod  * space, but I have yet to find documentation about them.
7963e5a02b0Smiod  *
7973e5a02b0Smiod  * We ignore multi-function devices and subordinate PCI busses here, since
7983e5a02b0Smiod  * PDC PCI device paths stop at the PCI device number, and subordinate
7993e5a02b0Smiod  * busses are unlikely to be configured by the PDC.
8003e5a02b0Smiod  */
8013e5a02b0Smiod 
8023e5a02b0Smiod #define	ELROY_MODEL	0x78
8033e5a02b0Smiod #define	DINO_PAMR	0x804
8043e5a02b0Smiod #define	DINO_CFG_ADDR	0x64
8053e5a02b0Smiod #define	DINO_CFG_DATA	0x68
8063e5a02b0Smiod 
8073e5a02b0Smiod void
pci_bus_walk(struct device_path * idp,struct iodc_data * mptr,struct pdc_memmap * memmap)8083e5a02b0Smiod pci_bus_walk(struct device_path *idp, struct iodc_data *mptr,
8093e5a02b0Smiod     struct pdc_memmap *memmap)
8103e5a02b0Smiod {
8113e5a02b0Smiod 	struct device_path dp;
8123e5a02b0Smiod 	int dev, fn, nfuncs;
8133e5a02b0Smiod 	uint32_t id, bhlcr, class;
8143e5a02b0Smiod 	uint32_t (*conf_read)(u_int, int, int, u_int);
8153e5a02b0Smiod 
8163e5a02b0Smiod 	if (mptr->iodc_model == ELROY_MODEL)
8173e5a02b0Smiod 		conf_read = elroy_conf_read;
8183e5a02b0Smiod 	else
8193e5a02b0Smiod 		conf_read = dino_conf_read;
8203e5a02b0Smiod 
8213e5a02b0Smiod 	for (dev = 0; dev < 32; dev++) {
8223e5a02b0Smiod 		id = (*conf_read)(memmap->hpa, dev, 0, PCI_ID_REG);
8233e5a02b0Smiod 
8243e5a02b0Smiod 		if (PCI_VENDOR(id) == PCI_VENDOR_INVALID || PCI_VENDOR(id) == 0)
8253e5a02b0Smiod 			continue;
8263e5a02b0Smiod 
8273e5a02b0Smiod 		bhlcr = (*conf_read)(memmap->hpa, dev, 0, PCI_BHLC_REG);
8283e5a02b0Smiod 		nfuncs = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
8293e5a02b0Smiod 
8303e5a02b0Smiod 		for (fn = 0; fn < nfuncs; fn++) {
8313e5a02b0Smiod 			dp = *idp;
8323e5a02b0Smiod 			path_shift(&dp, dev);
8333e5a02b0Smiod 			path_shift(&dp, fn);
8343e5a02b0Smiod 
8353e5a02b0Smiod 			if (fn != 0)
8363e5a02b0Smiod 				id = (*conf_read)(memmap->hpa, dev, fn,
8373e5a02b0Smiod 				    PCI_ID_REG);
8383e5a02b0Smiod 			class = (*conf_read)(memmap->hpa, dev, fn,
8393e5a02b0Smiod 			    PCI_CLASS_REG);
8403e5a02b0Smiod 
8413e5a02b0Smiod 			/*
8423e5a02b0Smiod 			 * We are only interested in two kinds of devices
8433e5a02b0Smiod 			 * here: sti graphics, and USB controllers.
8443e5a02b0Smiod 			 */
8453e5a02b0Smiod 			if (PCI_CLASS(class) == PCI_CLASS_SERIALBUS &&
8463e5a02b0Smiod 			    PCI_SUBCLASS(class) == PCI_SUBCLASS_SERIALBUS_USB) {
8473e5a02b0Smiod 				/*
8483e5a02b0Smiod 				 * Note about the last parameter of the
8493e5a02b0Smiod 				 * register_device() call below being zero:
8503e5a02b0Smiod 				 * machines with USB keyboards have neither
8513e5a02b0Smiod 				 * PS/2 nor HIL controllers, so it doesn't
8523e5a02b0Smiod 				 * matter what order the USB controllers are
8533e5a02b0Smiod 				 * in.
8543e5a02b0Smiod 				 * However machines with PS/2 keyboards
8553e5a02b0Smiod 				 * might have an USB PCI card plugged in,
8563e5a02b0Smiod 				 * which better appear after the PS/2
8573e5a02b0Smiod 				 * keyboard.
8583e5a02b0Smiod 				 */
8593e5a02b0Smiod 				register_device(keyboards, MAX_KEYBOARDS,
8603e5a02b0Smiod 				    &dp, mptr, USB, 0);
8613e5a02b0Smiod 				continue;
8623e5a02b0Smiod 			}
8633e5a02b0Smiod 
8643e5a02b0Smiod 			switch (PCI_VENDOR(id)) {
8653e5a02b0Smiod 			case PCI_VENDOR_HP:
8663e5a02b0Smiod 				switch (PCI_PRODUCT(id)) {
8673e5a02b0Smiod 				case PCI_PRODUCT_HP_VISUALIZE_EG:
8683e5a02b0Smiod 				case PCI_PRODUCT_HP_VISUALIZE_FX2:
8693e5a02b0Smiod 				case PCI_PRODUCT_HP_VISUALIZE_FX4:
8703e5a02b0Smiod 				case PCI_PRODUCT_HP_VISUALIZE_FX6:
8713e5a02b0Smiod 				case PCI_PRODUCT_HP_VISUALIZE_FXE:
8723e5a02b0Smiod 					register_device(graphics, MAX_GRAPHICS,
8733e5a02b0Smiod 					    &dp, mptr, GRAPHICS, 0);
8743e5a02b0Smiod 					break;
8753e5a02b0Smiod 				}
8763e5a02b0Smiod 				break;
8773e5a02b0Smiod 			case PCI_VENDOR_NS:
8783e5a02b0Smiod 				if (PCI_PRODUCT(id) == PCI_PRODUCT_NS_PC87560) {
8793e5a02b0Smiod 					/* serial_2 */
8803e5a02b0Smiod 					path_shift(&dp, 2);
8813e5a02b0Smiod 					register_device(serials, MAX_SERIALS,
8823e5a02b0Smiod 					    &dp, mptr, SERIAL, 1);
8833e5a02b0Smiod 					/* serial_1 */
8843e5a02b0Smiod 					dp.dp_mod = 1;
8853e5a02b0Smiod 					register_device(serials, MAX_SERIALS,
8863e5a02b0Smiod 					    &dp, mptr, SERIAL, 1);
8873e5a02b0Smiod 				}
8883e5a02b0Smiod 				break;
8893e5a02b0Smiod 			}
8903e5a02b0Smiod 		}
8913e5a02b0Smiod 	}
8923e5a02b0Smiod }
8933e5a02b0Smiod 
8943e5a02b0Smiod uint32_t
dino_conf_read(u_int hpa,int dev,int fn,u_int reg)8953e5a02b0Smiod dino_conf_read(u_int hpa, int dev, int fn, u_int reg)
8963e5a02b0Smiod {
8973e5a02b0Smiod 	volatile uint32_t *dino = (volatile uint32_t *)hpa;
8983e5a02b0Smiod 	uint32_t pamr;
8993e5a02b0Smiod 	uint32_t addr, id;
9003e5a02b0Smiod 
9013e5a02b0Smiod 	addr = (dev << 11) | (fn << 8) | reg;
9023e5a02b0Smiod 
9033e5a02b0Smiod 	pamr = dino[DINO_PAMR / 4];
9043e5a02b0Smiod 	dino[DINO_PAMR / 4] = 0;
9053e5a02b0Smiod 	dino[DINO_CFG_ADDR / 4] = addr;
9063e5a02b0Smiod 	id = dino[DINO_CFG_DATA / 4];
9073e5a02b0Smiod 	dino[DINO_PAMR / 4] = pamr;
9083e5a02b0Smiod 
9093e5a02b0Smiod 	return letoh32(id);
9103e5a02b0Smiod }
9113e5a02b0Smiod 
9123e5a02b0Smiod uint32_t
elroy_conf_read(u_int hpa,int dev,int fn,u_int reg)9133e5a02b0Smiod elroy_conf_read(u_int hpa, int dev, int fn, u_int reg)
9143e5a02b0Smiod {
9153e5a02b0Smiod 	volatile struct elroy_regs *elroy = (volatile struct elroy_regs *)hpa;
9163e5a02b0Smiod 	uint32_t arb_mask, err_cfg, control;
9173e5a02b0Smiod 	uint32_t addr, id;
9183e5a02b0Smiod 
9193e5a02b0Smiod 	addr = (dev << 11) | (fn << 8) | reg;
9203e5a02b0Smiod 
9213e5a02b0Smiod 	arb_mask = *(volatile uint32_t *)&elroy->arb_mask;
9223e5a02b0Smiod 	err_cfg = *(volatile uint32_t *)&elroy->err_cfg;
9233e5a02b0Smiod 	control = *(volatile uint32_t *)&elroy->control;
9243e5a02b0Smiod 
9253e5a02b0Smiod 	if (arb_mask == 0)
9263e5a02b0Smiod 		*(volatile uint32_t *)&elroy->arb_mask =
9273e5a02b0Smiod 		    htole32(ELROY_ARB_ENABLE);
9283e5a02b0Smiod 	*(volatile uint32_t *)&elroy->err_cfg = err_cfg |
9293e5a02b0Smiod 	    htole32(ELROY_ERRCFG_SMART | ELROY_ERRCFG_CM);
9303e5a02b0Smiod 	*(volatile uint32_t *)&elroy->control =
9313e5a02b0Smiod 	    (control | htole32(ELROY_CONTROL_CE)) & ~htole32(ELROY_CONTROL_HF);
9323e5a02b0Smiod 
9333e5a02b0Smiod 	*(volatile uint32_t *)&elroy->pci_conf_addr = htole32(addr);
9343e5a02b0Smiod 	addr = *(volatile uint32_t *)&elroy->pci_conf_addr;
9353e5a02b0Smiod 	id = *(volatile uint32_t *)&elroy->pci_conf_data;
9363e5a02b0Smiod 
9373e5a02b0Smiod 	*(volatile uint32_t *)&elroy->control =
9383e5a02b0Smiod 	    control | htole32(ELROY_CONTROL_CE | ELROY_CONTROL_CL);
9393e5a02b0Smiod 	*(volatile uint32_t *)&elroy->control = control;
9403e5a02b0Smiod 	*(volatile uint32_t *)&elroy->err_cfg = err_cfg;
9413e5a02b0Smiod 	if (arb_mask == 0)
9423e5a02b0Smiod 		*(volatile uint32_t *)&elroy->arb_mask = arb_mask;
9433e5a02b0Smiod 
9443e5a02b0Smiod 	return letoh32(id);
9453e5a02b0Smiod }
9463e5a02b0Smiod 
9473e5a02b0Smiod /*
9483e5a02b0Smiod  * Relaxed device comparison
9493e5a02b0Smiod  */
9503e5a02b0Smiod int
path_match(struct device_path * dev1,struct device_path * dev2)9513e5a02b0Smiod path_match(struct device_path *dev1, struct device_path *dev2)
9523e5a02b0Smiod {
9533e5a02b0Smiod 	return dev1->dp_mod == dev2->dp_mod &&
9543e5a02b0Smiod 	    dev1->dp_bc[0] == dev2->dp_bc[0] &&
9553e5a02b0Smiod 	    dev1->dp_bc[1] == dev2->dp_bc[1] &&
9563e5a02b0Smiod 	    dev1->dp_bc[2] == dev2->dp_bc[2] &&
9573e5a02b0Smiod 	    dev1->dp_bc[3] == dev2->dp_bc[3] &&
9583e5a02b0Smiod 	    dev1->dp_bc[4] == dev2->dp_bc[4] &&
9593e5a02b0Smiod 	    dev1->dp_bc[5] == dev2->dp_bc[5];
9603e5a02b0Smiod }
9613e5a02b0Smiod 
9623e5a02b0Smiod /*
9633e5a02b0Smiod  * Shift a device path, inserting a new value as dp_mod.
9643e5a02b0Smiod  */
9653e5a02b0Smiod void
path_shift(struct device_path * dp,int nmod)9663e5a02b0Smiod path_shift(struct device_path *dp, int nmod)
9673e5a02b0Smiod {
9683e5a02b0Smiod 	dp->dp_bc[0] = dp->dp_bc[1];
9693e5a02b0Smiod 	dp->dp_bc[1] = dp->dp_bc[2];
9703e5a02b0Smiod 	dp->dp_bc[2] = dp->dp_bc[3];
9713e5a02b0Smiod 	dp->dp_bc[3] = dp->dp_bc[4];
9723e5a02b0Smiod 	dp->dp_bc[4] = dp->dp_bc[5];
9733e5a02b0Smiod 	dp->dp_bc[5] = dp->dp_mod;
9743e5a02b0Smiod 	dp->dp_mod = nmod;
9753e5a02b0Smiod }
9763e5a02b0Smiod 
9774b857dedSmiod void
register_device(devlist,cnt,dp,mptr,type,first)978c178470fSmiod register_device(devlist, cnt, dp, mptr, type, first)
9794b857dedSmiod 	struct consoledev *devlist;
9804b857dedSmiod 	int cnt;
9814b857dedSmiod 	struct device_path *dp;
982c178470fSmiod 	struct iodc_data *mptr;
9834b857dedSmiod 	int type;
9844b857dedSmiod 	int first;
9854b857dedSmiod {
9864b857dedSmiod 	int i;
9874b857dedSmiod 	struct consoledev *dev;
9884b857dedSmiod 
9894b857dedSmiod 	for (i = 0, dev = devlist; i < cnt; i++, dev++)
9904b857dedSmiod 		if (dev->type == 0)
9914b857dedSmiod 			break;
9924b857dedSmiod 
9934b857dedSmiod 	if (i == cnt) {
9944b857dedSmiod #ifdef DEBUG
9954b857dedSmiod 		printf("can't register device, need more room!\n");
9964b857dedSmiod #endif
9974b857dedSmiod 		return;
9984b857dedSmiod 	}
9994b857dedSmiod 
10004b857dedSmiod 	/*
10014b857dedSmiod 	 * If this is supposedly the main device, insert on top
10024b857dedSmiod 	 */
10034b857dedSmiod 	if (first != 0) {
10044b857dedSmiod 		memcpy(devlist + 1, devlist,
10054b857dedSmiod 		    (cnt - 1) * sizeof(struct consoledev));
10064b857dedSmiod 		dev = devlist;
10074b857dedSmiod 	}
10084b857dedSmiod 
10094b857dedSmiod 	dev->dp = *dp;
10104b857dedSmiod 	dev->type = type;
1011c178470fSmiod 	dev->iodc_type = mptr->iodc_type;
1012c178470fSmiod 	dev->iodc_model = mptr->iodc_sv_model;
10134b857dedSmiod 
10144b857dedSmiod #ifdef DEBUG
10154b857dedSmiod 	printf("(registered as type %d)\n", type);
10164b857dedSmiod #endif
10174b857dedSmiod }
1018