1 /* $NetBSD: radio.c,v 1.3 2002/01/05 01:30:01 augustss Exp $ */ 2 /* $OpenBSD: radio.c,v 1.2 2001/12/05 10:27:06 mickey Exp $ */ 3 /* $RuOBSD: radio.c,v 1.7 2001/12/04 06:03:05 tm Exp $ */ 4 5 /* 6 * Copyright (c) 2001 Maxim Tsyplakov <tm@oganer.net> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* This is the /dev/radio driver from OpenBSD */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: radio.c,v 1.3 2002/01/05 01:30:01 augustss Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/proc.h> 38 #include <sys/errno.h> 39 #include <sys/ioctl.h> 40 #include <sys/device.h> 41 #include <sys/vnode.h> 42 #include <sys/radioio.h> 43 #include <sys/conf.h> 44 45 #include <dev/radio_if.h> 46 #include <dev/radiovar.h> 47 48 int radioprobe(struct device *, struct cfdata *, void *); 49 void radioattach(struct device *, struct device *, void *); 50 int radioopen(dev_t, int, int, struct proc *); 51 int radioclose(dev_t, int, int, struct proc *); 52 int radioioctl(dev_t, u_long, caddr_t, int, struct proc *); 53 int radioprint(void *, const char *); 54 int radiodetach(struct device *, int); 55 int radioactivate(struct device *, enum devact); 56 57 struct cfattach radio_ca = { 58 sizeof(struct radio_softc), radioprobe, radioattach, 59 radiodetach, radioactivate 60 }; 61 62 extern struct cfdriver radio_cd; 63 64 int 65 radioprobe(struct device *parent, struct cfdata *match, void *aux) 66 { 67 return (1); 68 } 69 70 void 71 radioattach(struct device *parent, struct device *self, void *aux) 72 { 73 struct radio_softc *sc = (void *)self; 74 struct radio_attach_args *sa = aux; 75 struct radio_hw_if *hwp = sa->hwif; 76 void *hdlp = sa->hdl; 77 78 printf("\n"); 79 sc->hw_if = hwp; 80 sc->hw_hdl = hdlp; 81 sc->sc_dev = parent; 82 } 83 84 int 85 radioopen(dev_t dev, int flags, int fmt, struct proc *p) 86 { 87 int unit; 88 struct radio_softc *sc; 89 90 unit = RADIOUNIT(dev); 91 if (unit >= radio_cd.cd_ndevs || 92 (sc = radio_cd.cd_devs[unit]) == NULL || 93 sc->hw_if == NULL) 94 return (ENXIO); 95 96 if (sc->hw_if->open != NULL) 97 return (sc->hw_if->open(sc->hw_hdl, flags, fmt, p)); 98 else 99 return (0); 100 } 101 102 int 103 radioclose(dev_t dev, int flags, int fmt, struct proc *p) 104 { 105 struct radio_softc *sc; 106 107 sc = radio_cd.cd_devs[RADIOUNIT(dev)]; 108 109 if (sc->hw_if->close != NULL) 110 return (sc->hw_if->close(sc->hw_hdl, flags, fmt, p)); 111 else 112 return (0); 113 } 114 115 int 116 radioioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 117 { 118 struct radio_softc *sc; 119 int unit, error; 120 121 unit = RADIOUNIT(dev); 122 if (unit >= radio_cd.cd_ndevs || 123 (sc = radio_cd.cd_devs[unit]) == NULL || sc->hw_if == NULL) 124 return (ENXIO); 125 126 error = EOPNOTSUPP; 127 switch (cmd) { 128 case RIOCGINFO: 129 if (sc->hw_if->get_info) 130 error = (sc->hw_if->get_info)(sc->hw_hdl, 131 (struct radio_info *)data); 132 break; 133 case RIOCSINFO: 134 if (sc->hw_if->set_info) 135 error = (sc->hw_if->set_info)(sc->hw_hdl, 136 (struct radio_info *)data); 137 break; 138 case RIOCSSRCH: 139 if (sc->hw_if->search) 140 error = (sc->hw_if->search)(sc->hw_hdl, 141 *(int *)data); 142 break; 143 default: 144 error = EINVAL; 145 } 146 147 return (error); 148 } 149 150 /* 151 * Called from hardware driver. This is where the MI radio driver gets 152 * probed/attached to the hardware driver 153 */ 154 struct device * 155 radio_attach_mi(struct radio_hw_if *rhwp, void *hdlp, struct device *dev) 156 { 157 struct radio_attach_args arg; 158 159 arg.hwif = rhwp; 160 arg.hdl = hdlp; 161 return (config_found(dev, &arg, radioprint)); 162 } 163 164 int 165 radioprint(void *aux, const char *pnp) 166 { 167 if (pnp != NULL) 168 printf("radio at %s", pnp); 169 return (UNCONF); 170 } 171 172 int 173 radiodetach(struct device *self, int flags) 174 { 175 /*struct radio_softc *sc = (struct radio_softc *)self;*/ 176 int maj, mn; 177 178 /* locate the major number */ 179 for (maj = 0; maj < nchrdev; maj++) 180 if (cdevsw[maj].d_open == radioopen) 181 break; 182 183 /* Nuke the vnodes for any open instances (calls close). */ 184 mn = self->dv_unit; 185 vdevgone(maj, mn, mn, VCHR); 186 187 return (0); 188 } 189 190 int 191 radioactivate(struct device *self, enum devact act) 192 { 193 struct radio_softc *sc = (struct radio_softc *)self; 194 195 switch (act) { 196 case DVACT_ACTIVATE: 197 return (EOPNOTSUPP); 198 break; 199 200 case DVACT_DEACTIVATE: 201 sc->sc_dying = 1; 202 break; 203 } 204 return (0); 205 } 206