]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - sys/dev/puc/puc_cfg.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / sys / dev / puc / puc_cfg.c
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$");
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
40 int
41 puc_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 }