78}; 79 80static void 81ppsidentify(driver_t *driver, device_t parent) 82{ 83 84 BUS_ADD_CHILD(parent, 0, PPS_NAME, -1); 85} 86 87static int 88ppstry(device_t ppbus, int send, int expect) 89{ 90 int i; 91 92 ppb_wdtr(ppbus, send); 93 i = ppb_rdtr(ppbus); 94 PRVERBOSE("S: %02x E: %02x G: %02x\n", send, expect, i); 95 return (i != expect); 96} 97 98static int 99ppsprobe(device_t ppsdev) 100{ 101 device_set_desc(ppsdev, "Pulse per second Timing Interface"); 102 103 return (0); 104} 105 106static int 107ppsattach(device_t dev) 108{ 109 struct pps_data *sc = DEVTOSOFTC(dev); 110 device_t ppbus = device_get_parent(dev); 111 dev_t d; 112 intptr_t irq; 113 int i, unit, zero = 0; 114 115 bzero(sc, sizeof(struct pps_data)); /* XXX doesn't newbus do this? */ 116 117 /* retrieve the ppbus irq */ 118 BUS_READ_IVAR(ppbus, dev, PPBUS_IVAR_IRQ, &irq); 119 120 if (irq > 0) { 121 /* declare our interrupt handler */ 122 sc->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ, 123 &zero, irq, irq, 1, RF_SHAREABLE); 124 } 125 /* interrupts seem mandatory */ 126 if (sc->intr_resource == NULL) 127 return (ENXIO); 128 129 sc->ppsdev = dev; 130 sc->ppbus = ppbus; 131 unit = device_get_unit(ppbus); 132 d = make_dev(&pps_cdevsw, unit, 133 UID_ROOT, GID_WHEEL, 0600, PPS_NAME "%d", unit); 134 sc->devs[0] = d; 135 sc->pps[0].ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT; 136 d->si_drv1 = sc; 137 d->si_drv2 = (void*)0; 138 pps_init(&sc->pps[0]); 139 140 if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) 141 return (0); 142 143 do { 144 i = ppb_set_mode(sc->ppbus, PPB_EPP); 145 PRVERBOSE("EPP: %d %d\n", i, PPB_IN_EPP_MODE(sc->ppbus)); 146 if (i == -1) 147 break; 148 i = 0; 149 ppb_wctr(ppbus, i); 150 if (ppstry(ppbus, 0x00, 0x00)) 151 break; 152 if (ppstry(ppbus, 0x55, 0x55)) 153 break; 154 if (ppstry(ppbus, 0xaa, 0xaa)) 155 break; 156 if (ppstry(ppbus, 0xff, 0xff)) 157 break; 158 159 i = IRQENABLE | PCD | STROBE | nINIT | SELECTIN; 160 ppb_wctr(ppbus, i); 161 PRVERBOSE("CTR = %02x (%02x)\n", ppb_rctr(ppbus), i); 162 if (ppstry(ppbus, 0x00, 0x00)) 163 break; 164 if (ppstry(ppbus, 0x55, 0x00)) 165 break; 166 if (ppstry(ppbus, 0xaa, 0x00)) 167 break; 168 if (ppstry(ppbus, 0xff, 0x00)) 169 break; 170 171 i = IRQENABLE | PCD | nINIT | SELECTIN; 172 ppb_wctr(ppbus, i); 173 PRVERBOSE("CTR = %02x (%02x)\n", ppb_rctr(ppbus), i); 174 ppstry(ppbus, 0x00, 0xff); 175 ppstry(ppbus, 0x55, 0xff); 176 ppstry(ppbus, 0xaa, 0xff); 177 ppstry(ppbus, 0xff, 0xff); 178 179 for (i = 1; i < 9; i++) { 180 d = make_dev(&pps_cdevsw, unit + 0x10000 * i, 181 UID_ROOT, GID_WHEEL, 0600, PPS_NAME "%db%d", unit, i - 1); 182 sc->devs[i] = d; 183 sc->pps[i].ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; 184 d->si_drv1 = sc; 185 d->si_drv2 = (void *)(intptr_t)i; 186 pps_init(&sc->pps[i]); 187 } 188 } while (0); 189 i = ppb_set_mode(sc->ppbus, PPB_COMPATIBLE); 190 ppb_release_bus(ppbus, dev); 191 192 return (0); 193} 194 195static int 196ppsopen(dev_t dev, int flags, int fmt, struct thread *td) 197{ 198 struct pps_data *sc = dev->si_drv1; 199 int subdev = (intptr_t)dev->si_drv2; 200 int error, i; 201 202 if (!sc->busy) { 203 device_t ppsdev = sc->ppsdev; 204 device_t ppbus = sc->ppbus; 205 206 if (ppb_request_bus(ppbus, ppsdev, PPB_WAIT|PPB_INTR)) 207 return (EINTR); 208 209 /* attach the interrupt handler */ 210 if ((error = BUS_SETUP_INTR(ppbus, ppsdev, sc->intr_resource, 211 INTR_TYPE_TTY, ppsintr, ppsdev, 212 &sc->intr_cookie))) { 213 ppb_release_bus(ppbus, ppsdev); 214 return (error); 215 } 216 217 i = ppb_set_mode(sc->ppbus, PPB_PS2); 218 PRVERBOSE("EPP: %d %d\n", i, PPB_IN_EPP_MODE(sc->ppbus)); 219 220 i = IRQENABLE | PCD | nINIT | SELECTIN; 221 ppb_wctr(ppbus, i); 222 } 223 if (subdev > 0 && !(sc->busy & ~1)) { 224 sc->timeout = timeout(ppshcpoll, sc, 1); 225 sc->lastdata = ppb_rdtr(sc->ppbus); 226 } 227 sc->busy |= (1 << subdev); 228 return(0); 229} 230 231static int 232ppsclose(dev_t dev, int flags, int fmt, struct thread *td) 233{ 234 struct pps_data *sc = dev->si_drv1; 235 int subdev = (intptr_t)dev->si_drv2; 236 237 sc->pps[subdev].ppsparam.mode = 0; /* PHK ??? */ 238 sc->busy &= ~(1 << subdev); 239 if (subdev > 0 && !(sc->busy & ~1)) 240 untimeout(ppshcpoll, sc, sc->timeout); 241 if (!sc->busy) { 242 device_t ppsdev = sc->ppsdev; 243 device_t ppbus = sc->ppbus; 244 245 ppb_wdtr(ppbus, 0); 246 ppb_wctr(ppbus, 0); 247 248 /* Note: the interrupt handler is automatically detached */ 249 ppb_set_mode(ppbus, PPB_COMPATIBLE); 250 ppb_release_bus(ppbus, ppsdev); 251 } 252 return(0); 253} 254 255static void 256ppshcpoll(void *arg) 257{ 258 struct pps_data *sc = arg; 259 int i, j, k, l; 260 261 if (!(sc->busy & ~1)) 262 return; 263 sc->timeout = timeout(ppshcpoll, sc, 1); 264 i = ppb_rdtr(sc->ppbus); 265 if (i == sc->lastdata) 266 return; 267 l = sc->lastdata ^ i; 268 k = 1; 269 for (j = 1; j < 9; j ++) { 270 if (l & k) { 271 pps_capture(&sc->pps[j]); 272 pps_event(&sc->pps[j], 273 i & k ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); 274 } 275 k += k; 276 } 277 sc->lastdata = i; 278} 279 280static void 281ppsintr(void *arg) 282{ 283 device_t ppsdev = (device_t)arg; 284 struct pps_data *sc = DEVTOSOFTC(ppsdev); 285 device_t ppbus = sc->ppbus; 286 287 pps_capture(&sc->pps[0]); 288 if (!(ppb_rstr(ppbus) & nACK)) 289 return; 290 if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) 291 ppb_wctr(ppbus, IRQENABLE | AUTOFEED); 292 pps_event(&sc->pps[0], PPS_CAPTUREASSERT); 293 if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) 294 ppb_wctr(ppbus, IRQENABLE); 295} 296 297static int 298ppsioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td) 299{ 300 struct pps_data *sc = dev->si_drv1; 301 int subdev = (intptr_t)dev->si_drv2; 302 303 return (pps_ioctl(cmd, data, &sc->pps[subdev])); 304} 305 306static device_method_t pps_methods[] = { 307 /* device interface */ 308 DEVMETHOD(device_identify, ppsidentify), 309 DEVMETHOD(device_probe, ppsprobe), 310 DEVMETHOD(device_attach, ppsattach), 311 312 { 0, 0 } 313}; 314 315static driver_t pps_driver = { 316 PPS_NAME, 317 pps_methods, 318 sizeof(struct pps_data), 319}; 320DRIVER_MODULE(pps, ppbus, pps_driver, pps_devclass, 0, 0);
| 70}; 71 72static void 73ppsidentify(driver_t *driver, device_t parent) 74{ 75 76 BUS_ADD_CHILD(parent, 0, PPS_NAME, -1); 77} 78 79static int 80ppstry(device_t ppbus, int send, int expect) 81{ 82 int i; 83 84 ppb_wdtr(ppbus, send); 85 i = ppb_rdtr(ppbus); 86 PRVERBOSE("S: %02x E: %02x G: %02x\n", send, expect, i); 87 return (i != expect); 88} 89 90static int 91ppsprobe(device_t ppsdev) 92{ 93 device_set_desc(ppsdev, "Pulse per second Timing Interface"); 94 95 return (0); 96} 97 98static int 99ppsattach(device_t dev) 100{ 101 struct pps_data *sc = DEVTOSOFTC(dev); 102 device_t ppbus = device_get_parent(dev); 103 dev_t d; 104 intptr_t irq; 105 int i, unit, zero = 0; 106 107 bzero(sc, sizeof(struct pps_data)); /* XXX doesn't newbus do this? */ 108 109 /* retrieve the ppbus irq */ 110 BUS_READ_IVAR(ppbus, dev, PPBUS_IVAR_IRQ, &irq); 111 112 if (irq > 0) { 113 /* declare our interrupt handler */ 114 sc->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ, 115 &zero, irq, irq, 1, RF_SHAREABLE); 116 } 117 /* interrupts seem mandatory */ 118 if (sc->intr_resource == NULL) 119 return (ENXIO); 120 121 sc->ppsdev = dev; 122 sc->ppbus = ppbus; 123 unit = device_get_unit(ppbus); 124 d = make_dev(&pps_cdevsw, unit, 125 UID_ROOT, GID_WHEEL, 0600, PPS_NAME "%d", unit); 126 sc->devs[0] = d; 127 sc->pps[0].ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT; 128 d->si_drv1 = sc; 129 d->si_drv2 = (void*)0; 130 pps_init(&sc->pps[0]); 131 132 if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) 133 return (0); 134 135 do { 136 i = ppb_set_mode(sc->ppbus, PPB_EPP); 137 PRVERBOSE("EPP: %d %d\n", i, PPB_IN_EPP_MODE(sc->ppbus)); 138 if (i == -1) 139 break; 140 i = 0; 141 ppb_wctr(ppbus, i); 142 if (ppstry(ppbus, 0x00, 0x00)) 143 break; 144 if (ppstry(ppbus, 0x55, 0x55)) 145 break; 146 if (ppstry(ppbus, 0xaa, 0xaa)) 147 break; 148 if (ppstry(ppbus, 0xff, 0xff)) 149 break; 150 151 i = IRQENABLE | PCD | STROBE | nINIT | SELECTIN; 152 ppb_wctr(ppbus, i); 153 PRVERBOSE("CTR = %02x (%02x)\n", ppb_rctr(ppbus), i); 154 if (ppstry(ppbus, 0x00, 0x00)) 155 break; 156 if (ppstry(ppbus, 0x55, 0x00)) 157 break; 158 if (ppstry(ppbus, 0xaa, 0x00)) 159 break; 160 if (ppstry(ppbus, 0xff, 0x00)) 161 break; 162 163 i = IRQENABLE | PCD | nINIT | SELECTIN; 164 ppb_wctr(ppbus, i); 165 PRVERBOSE("CTR = %02x (%02x)\n", ppb_rctr(ppbus), i); 166 ppstry(ppbus, 0x00, 0xff); 167 ppstry(ppbus, 0x55, 0xff); 168 ppstry(ppbus, 0xaa, 0xff); 169 ppstry(ppbus, 0xff, 0xff); 170 171 for (i = 1; i < 9; i++) { 172 d = make_dev(&pps_cdevsw, unit + 0x10000 * i, 173 UID_ROOT, GID_WHEEL, 0600, PPS_NAME "%db%d", unit, i - 1); 174 sc->devs[i] = d; 175 sc->pps[i].ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; 176 d->si_drv1 = sc; 177 d->si_drv2 = (void *)(intptr_t)i; 178 pps_init(&sc->pps[i]); 179 } 180 } while (0); 181 i = ppb_set_mode(sc->ppbus, PPB_COMPATIBLE); 182 ppb_release_bus(ppbus, dev); 183 184 return (0); 185} 186 187static int 188ppsopen(dev_t dev, int flags, int fmt, struct thread *td) 189{ 190 struct pps_data *sc = dev->si_drv1; 191 int subdev = (intptr_t)dev->si_drv2; 192 int error, i; 193 194 if (!sc->busy) { 195 device_t ppsdev = sc->ppsdev; 196 device_t ppbus = sc->ppbus; 197 198 if (ppb_request_bus(ppbus, ppsdev, PPB_WAIT|PPB_INTR)) 199 return (EINTR); 200 201 /* attach the interrupt handler */ 202 if ((error = BUS_SETUP_INTR(ppbus, ppsdev, sc->intr_resource, 203 INTR_TYPE_TTY, ppsintr, ppsdev, 204 &sc->intr_cookie))) { 205 ppb_release_bus(ppbus, ppsdev); 206 return (error); 207 } 208 209 i = ppb_set_mode(sc->ppbus, PPB_PS2); 210 PRVERBOSE("EPP: %d %d\n", i, PPB_IN_EPP_MODE(sc->ppbus)); 211 212 i = IRQENABLE | PCD | nINIT | SELECTIN; 213 ppb_wctr(ppbus, i); 214 } 215 if (subdev > 0 && !(sc->busy & ~1)) { 216 sc->timeout = timeout(ppshcpoll, sc, 1); 217 sc->lastdata = ppb_rdtr(sc->ppbus); 218 } 219 sc->busy |= (1 << subdev); 220 return(0); 221} 222 223static int 224ppsclose(dev_t dev, int flags, int fmt, struct thread *td) 225{ 226 struct pps_data *sc = dev->si_drv1; 227 int subdev = (intptr_t)dev->si_drv2; 228 229 sc->pps[subdev].ppsparam.mode = 0; /* PHK ??? */ 230 sc->busy &= ~(1 << subdev); 231 if (subdev > 0 && !(sc->busy & ~1)) 232 untimeout(ppshcpoll, sc, sc->timeout); 233 if (!sc->busy) { 234 device_t ppsdev = sc->ppsdev; 235 device_t ppbus = sc->ppbus; 236 237 ppb_wdtr(ppbus, 0); 238 ppb_wctr(ppbus, 0); 239 240 /* Note: the interrupt handler is automatically detached */ 241 ppb_set_mode(ppbus, PPB_COMPATIBLE); 242 ppb_release_bus(ppbus, ppsdev); 243 } 244 return(0); 245} 246 247static void 248ppshcpoll(void *arg) 249{ 250 struct pps_data *sc = arg; 251 int i, j, k, l; 252 253 if (!(sc->busy & ~1)) 254 return; 255 sc->timeout = timeout(ppshcpoll, sc, 1); 256 i = ppb_rdtr(sc->ppbus); 257 if (i == sc->lastdata) 258 return; 259 l = sc->lastdata ^ i; 260 k = 1; 261 for (j = 1; j < 9; j ++) { 262 if (l & k) { 263 pps_capture(&sc->pps[j]); 264 pps_event(&sc->pps[j], 265 i & k ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); 266 } 267 k += k; 268 } 269 sc->lastdata = i; 270} 271 272static void 273ppsintr(void *arg) 274{ 275 device_t ppsdev = (device_t)arg; 276 struct pps_data *sc = DEVTOSOFTC(ppsdev); 277 device_t ppbus = sc->ppbus; 278 279 pps_capture(&sc->pps[0]); 280 if (!(ppb_rstr(ppbus) & nACK)) 281 return; 282 if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) 283 ppb_wctr(ppbus, IRQENABLE | AUTOFEED); 284 pps_event(&sc->pps[0], PPS_CAPTUREASSERT); 285 if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) 286 ppb_wctr(ppbus, IRQENABLE); 287} 288 289static int 290ppsioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td) 291{ 292 struct pps_data *sc = dev->si_drv1; 293 int subdev = (intptr_t)dev->si_drv2; 294 295 return (pps_ioctl(cmd, data, &sc->pps[subdev])); 296} 297 298static device_method_t pps_methods[] = { 299 /* device interface */ 300 DEVMETHOD(device_identify, ppsidentify), 301 DEVMETHOD(device_probe, ppsprobe), 302 DEVMETHOD(device_attach, ppsattach), 303 304 { 0, 0 } 305}; 306 307static driver_t pps_driver = { 308 PPS_NAME, 309 pps_methods, 310 sizeof(struct pps_data), 311}; 312DRIVER_MODULE(pps, ppbus, pps_driver, pps_devclass, 0, 0);
|