1/*-
2 * Copyright (c) 2006 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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 WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/dev/puc/puc_cfg.c 263109 2014-03-13 15:57:25Z rstone $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/rman.h>
34#include <sys/sysctl.h>
35
36#include <dev/puc/puc_bus.h>
37#include <dev/puc/puc_cfg.h>
38#include <dev/puc/puc_bfe.h>
39
40int
41puc_config(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port, intptr_t *r)
42{
43 const struct puc_cfg *cfg = sc->sc_cfg;
44 int error;
45
46 if (cfg->config_function != NULL) {
47 error = cfg->config_function(sc, cmd, port, r);
48 if (!error)
49 return (0);
50 } else
51 error = EDOOFUS;
52
53 switch (cmd) {
54 case PUC_CFG_GET_CLOCK:
55 if (cfg->clock < 0)
56 return (error);
57 *r = cfg->clock;
58 return (0);
59 case PUC_CFG_GET_DESC:
60 if (cfg->desc == NULL)
61 return (error);
62 *r = (intptr_t)cfg->desc;
63 return (0);
64 case PUC_CFG_GET_ILR:
65 *r = PUC_ILR_NONE;
66 return (0);
67 case PUC_CFG_GET_LEN:
68 /* The length of bus space needed by the port. */
69 *r = 8;
70 return (0);
71 case PUC_CFG_GET_NPORTS:
72 /* The number of ports on this card. */
73 switch (cfg->ports) {
74 case PUC_PORT_NONSTANDARD:
75 return (error);
76 case PUC_PORT_1P:
77 case PUC_PORT_1S:
78 *r = 1;
79 return (0);
80 case PUC_PORT_1S1P:
81 case PUC_PORT_2P:
82 case PUC_PORT_2S:
83 *r = 2;
84 return (0);
85 case PUC_PORT_1S2P:
86 case PUC_PORT_2S1P:
87 case PUC_PORT_3S:
88 *r = 3;
89 return (0);
90 case PUC_PORT_4S:
91 *r = 4;
92 return (0);
93 case PUC_PORT_4S1P:
94 *r = 5;
95 return (0);
96 case PUC_PORT_6S:
97 *r = 6;
98 return (0);
99 case PUC_PORT_8S:
100 *r = 8;
101 return (0);
102 case PUC_PORT_12S:
103 *r = 12;
104 return (0);
105 case PUC_PORT_16S:
106 *r = 16;
107 return (0);
108 }
109 break;
110 case PUC_CFG_GET_OFS:
111 /* The offset relative to the RID. */
112 if (cfg->d_ofs < 0)
113 return (error);
114 *r = port * cfg->d_ofs;
115 return (0);
116 case PUC_CFG_GET_RID:
117 /* The RID for this port. */
118 if (port == 0) {
119 if (cfg->rid < 0)
120 return (error);
121 *r = cfg->rid;
122 return (0);
123 }
124 if (cfg->d_rid < 0)
125 return (error);
126 if (cfg->rid < 0) {
127 error = puc_config(sc, PUC_CFG_GET_RID, 0, r);
128 if (error)
129 return (error);
130 } else
131 *r = cfg->rid;
132 *r += port * cfg->d_rid;
133 return (0);
134 case PUC_CFG_GET_TYPE:
135 /* The type of this port. */
136 if (cfg->ports == PUC_PORT_NONSTANDARD)
137 return (error);
138 switch (port) {
139 case 0:
140 if (cfg->ports == PUC_PORT_1P ||
141 cfg->ports == PUC_PORT_2P)
142 *r = PUC_TYPE_PARALLEL;
143 else
144 *r = PUC_TYPE_SERIAL;
145 return (0);
146 case 1:
147 if (cfg->ports == PUC_PORT_1S1P ||
148 cfg->ports == PUC_PORT_1S2P ||
149 cfg->ports == PUC_PORT_2P)
150 *r = PUC_TYPE_PARALLEL;
151 else
152 *r = PUC_TYPE_SERIAL;
153 return (0);
154 case 2:
155 if (cfg->ports == PUC_PORT_1S2P ||
156 cfg->ports == PUC_PORT_2S1P)
157 *r = PUC_TYPE_PARALLEL;
158 else
159 *r = PUC_TYPE_SERIAL;
160 return (0);
161 case 4:
162 if (cfg->ports == PUC_PORT_4S1P)
163 *r = PUC_TYPE_PARALLEL;
164 else
165 *r = PUC_TYPE_SERIAL;
166 return (0);
167 }
168 *r = PUC_TYPE_SERIAL;
169 return (0);
170 case PUC_CFG_SETUP:
171 *r = ENXIO;
172 return (0);
173 }
174
175 return (ENXIO);
176}
2 * Copyright (c) 2006 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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 WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/dev/puc/puc_cfg.c 263109 2014-03-13 15:57:25Z rstone $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/rman.h>
34#include <sys/sysctl.h>
35
36#include <dev/puc/puc_bus.h>
37#include <dev/puc/puc_cfg.h>
38#include <dev/puc/puc_bfe.h>
39
40int
41puc_config(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port, intptr_t *r)
42{
43 const struct puc_cfg *cfg = sc->sc_cfg;
44 int error;
45
46 if (cfg->config_function != NULL) {
47 error = cfg->config_function(sc, cmd, port, r);
48 if (!error)
49 return (0);
50 } else
51 error = EDOOFUS;
52
53 switch (cmd) {
54 case PUC_CFG_GET_CLOCK:
55 if (cfg->clock < 0)
56 return (error);
57 *r = cfg->clock;
58 return (0);
59 case PUC_CFG_GET_DESC:
60 if (cfg->desc == NULL)
61 return (error);
62 *r = (intptr_t)cfg->desc;
63 return (0);
64 case PUC_CFG_GET_ILR:
65 *r = PUC_ILR_NONE;
66 return (0);
67 case PUC_CFG_GET_LEN:
68 /* The length of bus space needed by the port. */
69 *r = 8;
70 return (0);
71 case PUC_CFG_GET_NPORTS:
72 /* The number of ports on this card. */
73 switch (cfg->ports) {
74 case PUC_PORT_NONSTANDARD:
75 return (error);
76 case PUC_PORT_1P:
77 case PUC_PORT_1S:
78 *r = 1;
79 return (0);
80 case PUC_PORT_1S1P:
81 case PUC_PORT_2P:
82 case PUC_PORT_2S:
83 *r = 2;
84 return (0);
85 case PUC_PORT_1S2P:
86 case PUC_PORT_2S1P:
87 case PUC_PORT_3S:
88 *r = 3;
89 return (0);
90 case PUC_PORT_4S:
91 *r = 4;
92 return (0);
93 case PUC_PORT_4S1P:
94 *r = 5;
95 return (0);
96 case PUC_PORT_6S:
97 *r = 6;
98 return (0);
99 case PUC_PORT_8S:
100 *r = 8;
101 return (0);
102 case PUC_PORT_12S:
103 *r = 12;
104 return (0);
105 case PUC_PORT_16S:
106 *r = 16;
107 return (0);
108 }
109 break;
110 case PUC_CFG_GET_OFS:
111 /* The offset relative to the RID. */
112 if (cfg->d_ofs < 0)
113 return (error);
114 *r = port * cfg->d_ofs;
115 return (0);
116 case PUC_CFG_GET_RID:
117 /* The RID for this port. */
118 if (port == 0) {
119 if (cfg->rid < 0)
120 return (error);
121 *r = cfg->rid;
122 return (0);
123 }
124 if (cfg->d_rid < 0)
125 return (error);
126 if (cfg->rid < 0) {
127 error = puc_config(sc, PUC_CFG_GET_RID, 0, r);
128 if (error)
129 return (error);
130 } else
131 *r = cfg->rid;
132 *r += port * cfg->d_rid;
133 return (0);
134 case PUC_CFG_GET_TYPE:
135 /* The type of this port. */
136 if (cfg->ports == PUC_PORT_NONSTANDARD)
137 return (error);
138 switch (port) {
139 case 0:
140 if (cfg->ports == PUC_PORT_1P ||
141 cfg->ports == PUC_PORT_2P)
142 *r = PUC_TYPE_PARALLEL;
143 else
144 *r = PUC_TYPE_SERIAL;
145 return (0);
146 case 1:
147 if (cfg->ports == PUC_PORT_1S1P ||
148 cfg->ports == PUC_PORT_1S2P ||
149 cfg->ports == PUC_PORT_2P)
150 *r = PUC_TYPE_PARALLEL;
151 else
152 *r = PUC_TYPE_SERIAL;
153 return (0);
154 case 2:
155 if (cfg->ports == PUC_PORT_1S2P ||
156 cfg->ports == PUC_PORT_2S1P)
157 *r = PUC_TYPE_PARALLEL;
158 else
159 *r = PUC_TYPE_SERIAL;
160 return (0);
161 case 4:
162 if (cfg->ports == PUC_PORT_4S1P)
163 *r = PUC_TYPE_PARALLEL;
164 else
165 *r = PUC_TYPE_SERIAL;
166 return (0);
167 }
168 *r = PUC_TYPE_SERIAL;
169 return (0);
170 case PUC_CFG_SETUP:
171 *r = ENXIO;
172 return (0);
173 }
174
175 return (ENXIO);
176}