1 /*- 2 * Copyright (c) 1997 Nicolas Souchu 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 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $Id: ppi.c,v 1.4 1997/08/28 10:15:16 msmith Exp $ 27 * 28 */ 29 #include "ppi.h" 30 31 #if NPPI > 0 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/conf.h> 36 #include <sys/kernel.h> 37 #include <sys/malloc.h> 38 39 #include <dev/ppbus/ppbconf.h> 40 41 struct ppi_data { 42 43 int ppi_unit; 44 45 struct ppb_device ppi_dev; 46 }; 47 48 #define MAXPPI 8 /* XXX not much better! */ 49 static int nppi = 0; 50 static struct ppi_data *ppidata[MAXPPI]; 51 52 /* 53 * Make ourselves visible as a ppbus driver 54 */ 55 56 static struct ppb_device *ppiprobe(struct ppb_data *ppb); 57 static int ppiattach(struct ppb_device *dev); 58 static void ppiintr(int unit); 59 60 static struct ppb_driver ppidriver = { 61 ppiprobe, ppiattach, "ppi" 62 }; 63 DATA_SET(ppbdriver_set, ppidriver); 64 65 66 static d_open_t ppiopen; 67 static d_close_t ppiclose; 68 static d_ioctl_t ppiioctl; 69 70 #define CDEV_MAJOR 82 71 static struct cdevsw ppi_cdevsw = 72 { ppiopen, ppiclose, noread, nowrite, /* 82 */ 73 ppiioctl, nullstop, nullreset, nodevtotty, 74 seltrue, nommap, nostrat, "ppi", NULL, -1 }; 75 76 /* 77 * ppiprobe() 78 */ 79 static struct ppb_device * 80 ppiprobe(struct ppb_data *ppb) 81 { 82 struct ppi_data *ppi; 83 84 ppi = (struct ppi_data *) malloc(sizeof(struct ppi_data), 85 M_TEMP, M_NOWAIT); 86 if (!ppi) { 87 printf("ppi: cannot malloc!\n"); 88 return 0; 89 } 90 bzero(ppi, sizeof(struct ppi_data)); 91 92 ppidata[nppi] = ppi; 93 94 /* 95 * ppi dependent initialisation. 96 */ 97 ppi->ppi_unit = nppi; 98 99 /* 100 * ppbus dependent initialisation. 101 */ 102 ppi->ppi_dev.id_unit = ppi->ppi_unit; 103 ppi->ppi_dev.ppb = ppb; 104 ppi->ppi_dev.intr = ppiintr; 105 106 /* Ok, go to next device on next probe */ 107 nppi ++; 108 109 return &ppi->ppi_dev; 110 } 111 112 static int 113 ppiattach(struct ppb_device *dev) 114 { 115 struct ppi_data *ppi = ppidata[dev->id_unit]; 116 117 /* 118 * Report ourselves 119 */ 120 printf("ppi%d: <generic parallel i/o> on ppbus %d\n", 121 dev->id_unit, dev->ppb->ppb_link->adapter_unit); 122 123 return (1); 124 } 125 126 static void 127 ppiintr(int unit) 128 { 129 return; 130 } 131 132 static int 133 ppiopen(dev_t dev, int flags, int fmt, struct proc *p) 134 { 135 u_int unit = minor(dev); 136 137 if (unit >= nppi) 138 return (ENXIO); 139 140 printf("ppi open!\n"); 141 142 return (EOPNOTSUPP); 143 } 144 145 static int 146 ppiclose(dev_t dev, int flags, int fmt, struct proc *p) 147 { 148 return (EOPNOTSUPP); 149 } 150 151 static int 152 ppiioctl(dev_t dev, int cmd, caddr_t data, int flags, struct proc *p) 153 { 154 return (EOPNOTSUPP); 155 } 156 157 #ifdef PPI_MODULE 158 159 MOD_DEV(ppi, LM_DT_CHAR, CDEV_MAJOR, &ppi_cdevsw); 160 161 static int 162 ppi_load(struct lkm_table *lkmtp, int cmd) 163 { 164 struct ppb_data *ppb; 165 struct ppb_device *dev; 166 int i; 167 168 for (ppb = ppb_next_bus(NULL); ppb; ppb = ppb_next_bus(ppb)) { 169 170 dev = ppiprobe(ppb); 171 ppiattach(dev); 172 173 ppb_attach_device(dev); 174 } 175 176 return (0); 177 } 178 179 static int 180 ppi_unload(struct lkm_table *lkmtp, int cmd) 181 { 182 int i; 183 184 for (i = nppi-1; i > 0; i--) { 185 ppb_remove_device(&ppidata[i]->ppi_dev); 186 free(ppidata[i], M_TEMP); 187 } 188 189 return (0); 190 } 191 192 int 193 ppi_mod(struct lkm_table *lkmtp, int cmd, int ver) 194 { 195 DISPATCH(lkmtp, cmd, ver, ppi_load, ppi_unload, lkm_nullcmd); 196 } 197 198 #endif /* PPI_MODULE */ 199 200 static ppi_devsw_installed = 0; 201 202 static void ppi_drvinit(void *unused) 203 { 204 dev_t dev; 205 206 if (!ppi_devsw_installed ) { 207 dev = makedev(CDEV_MAJOR, 0); 208 cdevsw_add(&dev, &ppi_cdevsw, NULL); 209 ppi_devsw_installed = 1; 210 } 211 } 212 213 SYSINIT(ppidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ppi_drvinit,NULL) 214 215 #endif /* NPPI */ 216