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