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>
34158124Smarcel
35158124Smarcel#include <dev/puc/puc_bus.h>
36158124Smarcel#include <dev/puc/puc_cfg.h>
37160030Sobrien#include <dev/puc/puc_bfe.h>
38158124Smarcel
39158124Smarcelint
40158124Smarcelpuc_config(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port, intptr_t *r)
41158124Smarcel{
42158124Smarcel	const struct puc_cfg *cfg = sc->sc_cfg;
43158124Smarcel	int error;
44158124Smarcel
45158124Smarcel	if (cfg->config_function != NULL) {
46158124Smarcel		error = cfg->config_function(sc, cmd, port, r);
47158124Smarcel		if (!error)
48158124Smarcel			return (0);
49158124Smarcel	} else
50158124Smarcel		error = EDOOFUS;
51158124Smarcel
52158124Smarcel	switch (cmd) {
53158124Smarcel	case PUC_CFG_GET_CLOCK:
54158124Smarcel		if (cfg->clock < 0)
55158124Smarcel			return (error);
56158124Smarcel		*r = cfg->clock;
57158124Smarcel		return (0);
58158124Smarcel	case PUC_CFG_GET_DESC:
59158124Smarcel		if (cfg->desc == NULL)
60158124Smarcel			return (error);
61158124Smarcel		*r = (intptr_t)cfg->desc;
62158124Smarcel		return (0);
63158124Smarcel	case PUC_CFG_GET_ILR:
64158124Smarcel		*r = PUC_ILR_NONE;
65158124Smarcel		return (0);
66158124Smarcel	case PUC_CFG_GET_LEN:
67158124Smarcel		/* The length of bus space needed by the port. */
68158124Smarcel		*r = 8;
69158124Smarcel		return (0);
70158124Smarcel	case PUC_CFG_GET_NPORTS:
71158124Smarcel		/* The number of ports on this card. */
72158124Smarcel		switch (cfg->ports) {
73158124Smarcel		case PUC_PORT_NONSTANDARD:
74158124Smarcel			return (error);
75158124Smarcel		case PUC_PORT_1P:
76158124Smarcel		case PUC_PORT_1S:
77158124Smarcel			*r = 1;
78158124Smarcel			return (0);
79158124Smarcel		case PUC_PORT_1S1P:
80158124Smarcel		case PUC_PORT_2P:
81158124Smarcel		case PUC_PORT_2S:
82158124Smarcel			*r = 2;
83158124Smarcel			return (0);
84158124Smarcel		case PUC_PORT_1S2P:
85158124Smarcel		case PUC_PORT_2S1P:
86158124Smarcel		case PUC_PORT_3S:
87158124Smarcel			*r = 3;
88158124Smarcel			return (0);
89158124Smarcel		case PUC_PORT_4S:
90158124Smarcel			*r = 4;
91158124Smarcel			return (0);
92158124Smarcel		case PUC_PORT_4S1P:
93158124Smarcel			*r = 5;
94158124Smarcel			return (0);
95158124Smarcel		case PUC_PORT_6S:
96158124Smarcel			*r = 6;
97158124Smarcel			return (0);
98158124Smarcel		case PUC_PORT_8S:
99158124Smarcel			*r = 8;
100158124Smarcel			return (0);
101158124Smarcel		case PUC_PORT_12S:
102158124Smarcel			*r = 12;
103158124Smarcel			return (0);
104158124Smarcel		case PUC_PORT_16S:
105158124Smarcel			*r = 16;
106158124Smarcel			return (0);
107158124Smarcel		}
108158124Smarcel		break;
109158124Smarcel	case PUC_CFG_GET_OFS:
110158124Smarcel		/* The offset relative to the RID. */
111158124Smarcel		if (cfg->d_ofs < 0)
112158124Smarcel			return (error);
113158124Smarcel		*r = port * cfg->d_ofs;
114158124Smarcel		return (0);
115158124Smarcel	case PUC_CFG_GET_RID:
116158124Smarcel		/* The RID for this port. */
117158124Smarcel		if (port == 0) {
118158124Smarcel			if (cfg->rid < 0)
119158124Smarcel				return (error);
120158124Smarcel			*r = cfg->rid;
121158124Smarcel			return (0);
122158124Smarcel		}
123158124Smarcel		if (cfg->d_rid < 0)
124158124Smarcel			return (error);
125158124Smarcel		if (cfg->rid < 0) {
126158124Smarcel			error = puc_config(sc, PUC_CFG_GET_RID, 0, r);
127158124Smarcel			if (error)
128158124Smarcel				return (error);
129158124Smarcel		} else
130158124Smarcel			*r = cfg->rid;
131158124Smarcel		*r += port * cfg->d_rid;
132158124Smarcel		return (0);
133158124Smarcel	case PUC_CFG_GET_TYPE:
134158124Smarcel		/* The type of this port. */
135158124Smarcel		if (cfg->ports == PUC_PORT_NONSTANDARD)
136158124Smarcel			return (error);
137158124Smarcel		switch (port) {
138158124Smarcel		case 0:
139158124Smarcel			if (cfg->ports == PUC_PORT_1P ||
140158124Smarcel			    cfg->ports == PUC_PORT_2P)
141158124Smarcel				*r = PUC_TYPE_PARALLEL;
142158124Smarcel			else
143158124Smarcel				*r = PUC_TYPE_SERIAL;
144158124Smarcel			return (0);
145158124Smarcel		case 1:
146158124Smarcel			if (cfg->ports == PUC_PORT_1S1P ||
147158124Smarcel			    cfg->ports == PUC_PORT_1S2P ||
148158124Smarcel			    cfg->ports == PUC_PORT_2P)
149158124Smarcel				*r = PUC_TYPE_PARALLEL;
150158124Smarcel			else
151158124Smarcel				*r = PUC_TYPE_SERIAL;
152158124Smarcel			return (0);
153158124Smarcel		case 2:
154158124Smarcel			if (cfg->ports == PUC_PORT_1S2P ||
155158124Smarcel			    cfg->ports == PUC_PORT_2S1P)
156158124Smarcel				*r = PUC_TYPE_PARALLEL;
157158124Smarcel			else
158158124Smarcel				*r = PUC_TYPE_SERIAL;
159158124Smarcel			return (0);
160158124Smarcel		case 4:
161158124Smarcel			if (cfg->ports == PUC_PORT_4S1P)
162158124Smarcel				*r = PUC_TYPE_PARALLEL;
163158124Smarcel			else
164158124Smarcel				*r = PUC_TYPE_SERIAL;
165158124Smarcel			return (0);
166158124Smarcel		}
167158124Smarcel		*r = PUC_TYPE_SERIAL;
168158124Smarcel		return (0);
169158124Smarcel	case PUC_CFG_SETUP:
170158124Smarcel		*r = ENXIO;
171158124Smarcel		return (0);
172158124Smarcel	}
173158124Smarcel
174158124Smarcel	return (ENXIO);
175158124Smarcel}
176