1/*	$NetBSD$	*/
2/*
3 * Copyright (c) 2009 KIYOHARA Takashi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27#include <sys/cdefs.h>
28__KERNEL_RCSID(0, "$NetBSD$");
29
30#include <sys/param.h>
31#include <sys/device.h>
32#include <sys/termios.h>
33
34#include <machine/bus.h>
35#include <machine/dig64.h>
36#include <machine/md_var.h>
37
38#include <dev/acpi/acpica.h>
39
40#include "com.h"
41#include "vga.h"
42#include "ssccons.h"
43
44#include <dev/cons.h>
45#if NCOM > 0
46#include <dev/ic/comvar.h>
47#endif
48#if NVGA > 0
49#include <dev/ic/vgareg.h>
50#include <dev/ic/vgavar.h>
51#endif
52
53
54static void pcdp_cnprobe(struct consdev *);
55static void pcdp_cninit(struct consdev *);
56
57cons_decl(ssc);
58
59struct consdev constab[] = {
60	{ pcdp_cnprobe, pcdp_cninit,
61	  NULL, NULL, NULL, NULL, NULL, NULL, NODEV, CN_DEAD },
62#if NSSCCONS > 0
63	cons_init(ssc),
64#endif
65	{ NULL }
66};
67
68
69void
70consinit()
71{
72
73	cninit();
74}
75
76static void
77pcdp_cnprobe(struct consdev *cn)
78{
79	struct dig64_hcdp_table *tbl;
80	union dev_desc *desc;
81	uint64_t hcdp;
82	int n, m;
83
84	hcdp = ia64_get_hcdp();
85	if (hcdp != 0) {
86		tbl = (void*)IA64_PHYS_TO_RR7(hcdp);
87		n = 0;
88		m = tbl->length - sizeof(struct dig64_hcdp_table);
89		while (n < m) {
90			desc = (union dev_desc *)((char *)tbl->entry + n);
91#if NVGA > 0
92			if (devdesc->type ==
93			    (DIG64_ENTRYTYPE_VGA | DIG64_ENTRYTYPE_OUTONLY)) {
94#if defined(DIAGNOSTIC)
95				if (tbl->revision < 3)
96					panic("PCDP found in HCDP rev.%d."
97					    " Maybe unsupport PCDP",
98					    tbl->revision);
99#endif
100				cn->cn_pri = CN_NORMAL;
101				break;
102			}
103#endif
104#if NCOM > 0
105			if (desc->type == DIG64_HCDP_CONSOLE) {
106				cn->cn_pri = CN_REMOTE;
107				break;
108			}
109#endif
110
111			if (desc->type == DIG64_ENTRYTYPE_TYPE0 ||
112			    desc->type == DIG64_ENTRYTYPE_TYPE1)
113				n += sizeof(struct dig64_hcdp_entry);
114			else
115				n += desc->pcdp.length;
116		}
117	}
118	if (cn->cn_pri != CN_DEAD)
119		cn->cn_dev = ~NODEV;	/* Shall we makedev()? */
120}
121
122static void
123pcdp_cninit(struct consdev *cn)
124{
125	struct dig64_hcdp_table *tbl;
126	union dev_desc *desc;
127	uint64_t hcdp;
128	int n, m;
129
130	hcdp = ia64_get_hcdp();
131	if (hcdp == 0)
132		panic("lost console...\n");
133
134	tbl = (void *)IA64_PHYS_TO_RR7(hcdp);
135	n = 0;
136	m = tbl->length - sizeof(struct dig64_hcdp_table);
137	while (n < m) {
138		desc = (union dev_desc *)((char *)tbl->entry + n);
139#if NVGA > 0
140
141/* not yet... */
142/* Our VGA is Framebuffer? */
143
144		if (cn->cn_pri == CN_NORMAL &&
145		    desc->type ==
146			    (DIG64_ENTRYTYPE_VGA | DIG64_ENTRYTYPE_OUTONLY)) {
147			struct dig64_pcdp_entry *ent = &desc->pcdp;
148
149			if (ent->specs.type == DIG64_PCDP_SPEC_PCI) {
150				struct dig64_pci_spec *spec = ent->specs.pci;
151
152				if (spec->flags & DIG64_FLAGS_MMIO_TRA_VALID)
153					(void*)spec->mmio_tra;
154				if (spec->flags & DIG64_FLAGS_IOPORT_TRA_VALID)
155					(void*)spec->ioport_tra;
156			}
157
158			break;
159		}
160#endif
161#if NCOM > 0
162		if (cn->cn_pri == CN_REMOTE &&
163		    desc->type == DIG64_HCDP_CONSOLE) {
164			struct dig64_hcdp_entry *ent = &desc->uart;
165			bus_addr_t ioaddr;
166			bus_space_tag_t iot;
167			const uint64_t rate =
168			    ((uint64_t)ent->baud_high << 32) | ent->baud_low;
169			tcflag_t cflag =
170			    TTYDEF_CFLAG & ~(CSIZE | PARENB | PARODD);
171
172			switch (ent->databits) {
173			case 5:
174				cflag = CS5;
175				break;
176			case 6:
177				cflag = CS6;
178				break;
179			case 7:
180				cflag = CS7;
181				break;
182			case 8:
183				cflag = CS8;
184				break;
185			default:
186				panic("unsupported databits %d\n",
187				    ent->databits);
188			}
189			switch (ent->parity) {
190			case DIG64_HCDP_PARITY_NO:
191				break;
192			case DIG64_HCDP_PARITY_ODD:
193				cflag |= PARODD;
194
195				/* FALLTHROUGH */
196
197			case DIG64_HCDP_PARITY_EVEN:
198				cflag |= PARENB;
199				break;
200			case DIG64_HCDP_PARITY_MARK:
201			case DIG64_HCDP_PARITY_SPACE:
202			default:
203				panic("unsupported parity type %d\n",
204				    ent->parity);
205			}
206			if (ent->stopbits == DIG64_HCDP_STOPBITS_1)
207				cflag &= ~CSTOPB;
208			else if (ent->stopbits == DIG64_HCDP_STOPBITS_2)
209				cflag |= CSTOPB;
210			else
211				panic("unsupported stopbits type %d\n",
212				    ent->stopbits);
213			iot = (ent->address.addr_space ==
214						ACPI_ADR_SPACE_SYSTEM_MEMORY) ?
215			    IA64_BUS_SPACE_MEM : IA64_BUS_SPACE_IO;
216			ioaddr = ((uint64_t)ent->address.addr_high << 32) |
217			    ent->address.addr_low;
218			comcnattach(iot, ioaddr, rate,
219			    (ent->pclock != 0) ? ent->pclock : COM_FREQ,
220			    COM_TYPE_NORMAL, cflag);
221			break;
222		}
223#endif
224	}
225}
226