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 160030 2006-06-29 16:27:19Z obrien $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/rman.h>
34
35#include <dev/puc/puc_bus.h>
36#include <dev/puc/puc_cfg.h>
37#include <dev/puc/puc_bfe.h>
38
39int
40puc_config(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port, intptr_t *r)
41{
42 const struct puc_cfg *cfg = sc->sc_cfg;
43 int error;
44
45 if (cfg->config_function != NULL) {
46 error = cfg->config_function(sc, cmd, port, r);
47 if (!error)
48 return (0);
49 } else
50 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}
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 160030 2006-06-29 16:27:19Z obrien $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/rman.h>
34
35#include <dev/puc/puc_bus.h>
36#include <dev/puc/puc_cfg.h>
37#include <dev/puc/puc_bfe.h>
38
39int
40puc_config(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port, intptr_t *r)
41{
42 const struct puc_cfg *cfg = sc->sc_cfg;
43 int error;
44
45 if (cfg->config_function != NULL) {
46 error = cfg->config_function(sc, cmd, port, r);
47 if (!error)
48 return (0);
49 } else
50 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}