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