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 } 177