puc_cfg.c revision 259065
1251607Sdim/*-
2251607Sdim * Copyright (c) 2006 Marcel Moolenaar
3251607Sdim * All rights reserved.
4251607Sdim *
5251607Sdim * Redistribution and use in source and binary forms, with or without
6251607Sdim * modification, are permitted provided that the following conditions
7251607Sdim * are met:
8251607Sdim *
9251607Sdim * 1. Redistributions of source code must retain the above copyright
10251607Sdim *    notice, this list of conditions and the following disclaimer.
11288943Sdim * 2. Redistributions in binary form must reproduce the above copyright
12288943Sdim *    notice, this list of conditions and the following disclaimer in the
13251607Sdim *    documentation and/or other materials provided with the distribution.
14251607Sdim *
15251607Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16288943Sdim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17288943Sdim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18276479Sdim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19276479Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20288943Sdim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21288943Sdim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22288943Sdim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23288943Sdim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24251607Sdim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25288943Sdim */
26288943Sdim
27288943Sdim#include <sys/cdefs.h>
28288943Sdim__FBSDID("$FreeBSD: releng/10.0/sys/dev/puc/puc_cfg.c 160030 2006-06-29 16:27:19Z obrien $");
29288943Sdim
30288943Sdim#include <sys/param.h>
31288943Sdim#include <sys/systm.h>
32288943Sdim#include <sys/bus.h>
33288943Sdim#include <sys/rman.h>
34288943Sdim
35288943Sdim#include <dev/puc/puc_bus.h>
36288943Sdim#include <dev/puc/puc_cfg.h>
37288943Sdim#include <dev/puc/puc_bfe.h>
38288943Sdim
39288943Sdimint
40288943Sdimpuc_config(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port, intptr_t *r)
41288943Sdim{
42251607Sdim	const struct puc_cfg *cfg = sc->sc_cfg;
43251607Sdim	int error;
44276479Sdim
45251607Sdim	if (cfg->config_function != NULL) {
46251607Sdim		error = cfg->config_function(sc, cmd, port, r);
47251607Sdim		if (!error)
48288943Sdim			return (0);
49251607Sdim	} else
50251607Sdim		error = EDOOFUS;
51
52	switch (cmd) {
53	case PUC_CFG_GET_CLOCK:
54		if (cfg->clock < 0)
55			return (error);
56		*r = cfg->clock;
57		return (0);
58	case PUC_CFG_GET_DESC:
59		if (cfg->desc == NULL)
60			return (error);
61		*r = (intptr_t)cfg->desc;
62		return (0);
63	case PUC_CFG_GET_ILR:
64		*r = PUC_ILR_NONE;
65		return (0);
66	case PUC_CFG_GET_LEN:
67		/* The length of bus space needed by the port. */
68		*r = 8;
69		return (0);
70	case PUC_CFG_GET_NPORTS:
71		/* The number of ports on this card. */
72		switch (cfg->ports) {
73		case PUC_PORT_NONSTANDARD:
74			return (error);
75		case PUC_PORT_1P:
76		case PUC_PORT_1S:
77			*r = 1;
78			return (0);
79		case PUC_PORT_1S1P:
80		case PUC_PORT_2P:
81		case PUC_PORT_2S:
82			*r = 2;
83			return (0);
84		case PUC_PORT_1S2P:
85		case PUC_PORT_2S1P:
86		case PUC_PORT_3S:
87			*r = 3;
88			return (0);
89		case PUC_PORT_4S:
90			*r = 4;
91			return (0);
92		case PUC_PORT_4S1P:
93			*r = 5;
94			return (0);
95		case PUC_PORT_6S:
96			*r = 6;
97			return (0);
98		case PUC_PORT_8S:
99			*r = 8;
100			return (0);
101		case PUC_PORT_12S:
102			*r = 12;
103			return (0);
104		case PUC_PORT_16S:
105			*r = 16;
106			return (0);
107		}
108		break;
109	case PUC_CFG_GET_OFS:
110		/* The offset relative to the RID. */
111		if (cfg->d_ofs < 0)
112			return (error);
113		*r = port * cfg->d_ofs;
114		return (0);
115	case PUC_CFG_GET_RID:
116		/* The RID for this port. */
117		if (port == 0) {
118			if (cfg->rid < 0)
119				return (error);
120			*r = cfg->rid;
121			return (0);
122		}
123		if (cfg->d_rid < 0)
124			return (error);
125		if (cfg->rid < 0) {
126			error = puc_config(sc, PUC_CFG_GET_RID, 0, r);
127			if (error)
128				return (error);
129		} else
130			*r = cfg->rid;
131		*r += port * cfg->d_rid;
132		return (0);
133	case PUC_CFG_GET_TYPE:
134		/* The type of this port. */
135		if (cfg->ports == PUC_PORT_NONSTANDARD)
136			return (error);
137		switch (port) {
138		case 0:
139			if (cfg->ports == PUC_PORT_1P ||
140			    cfg->ports == PUC_PORT_2P)
141				*r = PUC_TYPE_PARALLEL;
142			else
143				*r = PUC_TYPE_SERIAL;
144			return (0);
145		case 1:
146			if (cfg->ports == PUC_PORT_1S1P ||
147			    cfg->ports == PUC_PORT_1S2P ||
148			    cfg->ports == PUC_PORT_2P)
149				*r = PUC_TYPE_PARALLEL;
150			else
151				*r = PUC_TYPE_SERIAL;
152			return (0);
153		case 2:
154			if (cfg->ports == PUC_PORT_1S2P ||
155			    cfg->ports == PUC_PORT_2S1P)
156				*r = PUC_TYPE_PARALLEL;
157			else
158				*r = PUC_TYPE_SERIAL;
159			return (0);
160		case 4:
161			if (cfg->ports == PUC_PORT_4S1P)
162				*r = PUC_TYPE_PARALLEL;
163			else
164				*r = PUC_TYPE_SERIAL;
165			return (0);
166		}
167		*r = PUC_TYPE_SERIAL;
168		return (0);
169	case PUC_CFG_SETUP:
170		*r = ENXIO;
171		return (0);
172	}
173
174	return (ENXIO);
175}
176