1158124Smarcel/*-
2158124Smarcel * Copyright (c) 2006 Marcel Moolenaar
3158124Smarcel * All rights reserved.
4158124Smarcel *
5158124Smarcel * Redistribution and use in source and binary forms, with or without
6158124Smarcel * modification, are permitted provided that the following conditions
7158124Smarcel * are met:
8158124Smarcel *
9158124Smarcel * 1. Redistributions of source code must retain the above copyright
10158124Smarcel *    notice, this list of conditions and the following disclaimer.
11158124Smarcel * 2. Redistributions in binary form must reproduce the above copyright
12158124Smarcel *    notice, this list of conditions and the following disclaimer in the
13158124Smarcel *    documentation and/or other materials provided with the distribution.
14158124Smarcel *
15158124Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16158124Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17158124Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18158124Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19158124Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20158124Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21158124Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22158124Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23158124Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24158124Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25158124Smarcel */
26158124Smarcel
27158124Smarcel#include <sys/cdefs.h>
28158124Smarcel__FBSDID("$FreeBSD$");
29158124Smarcel
30158124Smarcel#include <sys/param.h>
31158124Smarcel#include <sys/systm.h>
32158124Smarcel#include <sys/bus.h>
33158124Smarcel#include <sys/rman.h>
34263109Srstone#include <sys/sysctl.h>
35158124Smarcel
36158124Smarcel#include <dev/puc/puc_bus.h>
37158124Smarcel#include <dev/puc/puc_cfg.h>
38160030Sobrien#include <dev/puc/puc_bfe.h>
39158124Smarcel
40158124Smarcelint
41158124Smarcelpuc_config(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port, intptr_t *r)
42158124Smarcel{
43158124Smarcel	const struct puc_cfg *cfg = sc->sc_cfg;
44158124Smarcel	int error;
45158124Smarcel
46158124Smarcel	if (cfg->config_function != NULL) {
47158124Smarcel		error = cfg->config_function(sc, cmd, port, r);
48158124Smarcel		if (!error)
49158124Smarcel			return (0);
50158124Smarcel	} else
51158124Smarcel		error = EDOOFUS;
52158124Smarcel
53158124Smarcel	switch (cmd) {
54158124Smarcel	case PUC_CFG_GET_CLOCK:
55158124Smarcel		if (cfg->clock < 0)
56158124Smarcel			return (error);
57158124Smarcel		*r = cfg->clock;
58158124Smarcel		return (0);
59158124Smarcel	case PUC_CFG_GET_DESC:
60158124Smarcel		if (cfg->desc == NULL)
61158124Smarcel			return (error);
62158124Smarcel		*r = (intptr_t)cfg->desc;
63158124Smarcel		return (0);
64158124Smarcel	case PUC_CFG_GET_ILR:
65158124Smarcel		*r = PUC_ILR_NONE;
66158124Smarcel		return (0);
67158124Smarcel	case PUC_CFG_GET_LEN:
68158124Smarcel		/* The length of bus space needed by the port. */
69158124Smarcel		*r = 8;
70158124Smarcel		return (0);
71158124Smarcel	case PUC_CFG_GET_NPORTS:
72158124Smarcel		/* The number of ports on this card. */
73158124Smarcel		switch (cfg->ports) {
74158124Smarcel		case PUC_PORT_NONSTANDARD:
75158124Smarcel			return (error);
76158124Smarcel		case PUC_PORT_1P:
77158124Smarcel		case PUC_PORT_1S:
78158124Smarcel			*r = 1;
79158124Smarcel			return (0);
80158124Smarcel		case PUC_PORT_1S1P:
81158124Smarcel		case PUC_PORT_2P:
82158124Smarcel		case PUC_PORT_2S:
83158124Smarcel			*r = 2;
84158124Smarcel			return (0);
85158124Smarcel		case PUC_PORT_1S2P:
86158124Smarcel		case PUC_PORT_2S1P:
87158124Smarcel		case PUC_PORT_3S:
88158124Smarcel			*r = 3;
89158124Smarcel			return (0);
90158124Smarcel		case PUC_PORT_4S:
91158124Smarcel			*r = 4;
92158124Smarcel			return (0);
93158124Smarcel		case PUC_PORT_4S1P:
94158124Smarcel			*r = 5;
95158124Smarcel			return (0);
96158124Smarcel		case PUC_PORT_6S:
97158124Smarcel			*r = 6;
98158124Smarcel			return (0);
99158124Smarcel		case PUC_PORT_8S:
100158124Smarcel			*r = 8;
101158124Smarcel			return (0);
102158124Smarcel		case PUC_PORT_12S:
103158124Smarcel			*r = 12;
104158124Smarcel			return (0);
105158124Smarcel		case PUC_PORT_16S:
106158124Smarcel			*r = 16;
107158124Smarcel			return (0);
108158124Smarcel		}
109158124Smarcel		break;
110158124Smarcel	case PUC_CFG_GET_OFS:
111158124Smarcel		/* The offset relative to the RID. */
112158124Smarcel		if (cfg->d_ofs < 0)
113158124Smarcel			return (error);
114158124Smarcel		*r = port * cfg->d_ofs;
115158124Smarcel		return (0);
116158124Smarcel	case PUC_CFG_GET_RID:
117158124Smarcel		/* The RID for this port. */
118158124Smarcel		if (port == 0) {
119158124Smarcel			if (cfg->rid < 0)
120158124Smarcel				return (error);
121158124Smarcel			*r = cfg->rid;
122158124Smarcel			return (0);
123158124Smarcel		}
124158124Smarcel		if (cfg->d_rid < 0)
125158124Smarcel			return (error);
126158124Smarcel		if (cfg->rid < 0) {
127158124Smarcel			error = puc_config(sc, PUC_CFG_GET_RID, 0, r);
128158124Smarcel			if (error)
129158124Smarcel				return (error);
130158124Smarcel		} else
131158124Smarcel			*r = cfg->rid;
132158124Smarcel		*r += port * cfg->d_rid;
133158124Smarcel		return (0);
134158124Smarcel	case PUC_CFG_GET_TYPE:
135158124Smarcel		/* The type of this port. */
136158124Smarcel		if (cfg->ports == PUC_PORT_NONSTANDARD)
137158124Smarcel			return (error);
138158124Smarcel		switch (port) {
139158124Smarcel		case 0:
140158124Smarcel			if (cfg->ports == PUC_PORT_1P ||
141158124Smarcel			    cfg->ports == PUC_PORT_2P)
142158124Smarcel				*r = PUC_TYPE_PARALLEL;
143158124Smarcel			else
144158124Smarcel				*r = PUC_TYPE_SERIAL;
145158124Smarcel			return (0);
146158124Smarcel		case 1:
147158124Smarcel			if (cfg->ports == PUC_PORT_1S1P ||
148158124Smarcel			    cfg->ports == PUC_PORT_1S2P ||
149158124Smarcel			    cfg->ports == PUC_PORT_2P)
150158124Smarcel				*r = PUC_TYPE_PARALLEL;
151158124Smarcel			else
152158124Smarcel				*r = PUC_TYPE_SERIAL;
153158124Smarcel			return (0);
154158124Smarcel		case 2:
155158124Smarcel			if (cfg->ports == PUC_PORT_1S2P ||
156158124Smarcel			    cfg->ports == PUC_PORT_2S1P)
157158124Smarcel				*r = PUC_TYPE_PARALLEL;
158158124Smarcel			else
159158124Smarcel				*r = PUC_TYPE_SERIAL;
160158124Smarcel			return (0);
161158124Smarcel		case 4:
162158124Smarcel			if (cfg->ports == PUC_PORT_4S1P)
163158124Smarcel				*r = PUC_TYPE_PARALLEL;
164158124Smarcel			else
165158124Smarcel				*r = PUC_TYPE_SERIAL;
166158124Smarcel			return (0);
167158124Smarcel		}
168158124Smarcel		*r = PUC_TYPE_SERIAL;
169158124Smarcel		return (0);
170158124Smarcel	case PUC_CFG_SETUP:
171158124Smarcel		*r = ENXIO;
172158124Smarcel		return (0);
173158124Smarcel	}
174158124Smarcel
175158124Smarcel	return (ENXIO);
176158124Smarcel}
177