1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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/param.h> 30 #include <sys/systm.h> 31 #include <sys/bus.h> 32 #include <sys/rman.h> 33 #include <sys/sysctl.h> 34 35 #include <dev/puc/puc_bus.h> 36 #include <dev/puc/puc_cfg.h> 37 #include <dev/puc/puc_bfe.h> 38 39 int 40 puc_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 } 176