static int lpbb_callback(device_t dev, int index, caddr_t data) { device_t ppbus = device_get_parent(dev); int error = 0; int how; switch (index) { case IIC_REQUEST_BUS: /* request the ppbus */ how = *(int *)data; ppb_lock(ppbus); error = ppb_request_bus(ppbus, dev, how); ppb_unlock(ppbus); break; case IIC_RELEASE_BUS: /* release the ppbus */ ppb_lock(ppbus); error = ppb_release_bus(ppbus, dev); ppb_unlock(ppbus); break; default: error = EINVAL; } return (error); }
static int lpbb_detect(device_t dev) { device_t ppbus = device_get_parent(dev); ppb_lock(ppbus); if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) { ppb_unlock(ppbus); device_printf(dev, "can't allocate ppbus\n"); return (0); } lpbb_reset_bus(dev); if ((ppb_rstr(ppbus) & I2CKEY) || ((ppb_rstr(ppbus) & ALIM) != ALIM)) { ppb_release_bus(ppbus, dev); ppb_unlock(ppbus); return (0); } ppb_release_bus(ppbus, dev); ppb_unlock(ppbus); return (1); }
/* * vpoio_attach() * * Low level attachment of vpo device * */ int vpoio_attach(struct vpoio_data *vpo) { DECLARE_NIBBLE_INBYTE_SUBMICROSEQ; device_t ppbus = device_get_parent(vpo->vpo_dev); int error = 0; vpo->vpo_nibble_inbyte_msq = (struct ppb_microseq *)malloc( sizeof(nibble_inbyte_submicroseq), M_DEVBUF, M_NOWAIT); if (!vpo->vpo_nibble_inbyte_msq) return (ENXIO); bcopy((void *)nibble_inbyte_submicroseq, (void *)vpo->vpo_nibble_inbyte_msq, sizeof(nibble_inbyte_submicroseq)); ppb_MS_init_msq(vpo->vpo_nibble_inbyte_msq, 4, INB_NIBBLE_H, (void *)&(vpo)->vpo_nibble.h, INB_NIBBLE_L, (void *)&(vpo)->vpo_nibble.l, INB_NIBBLE_F, nibble_inbyte_hook, INB_NIBBLE_P, (void *)&(vpo)->vpo_nibble); /* * Initialize mode dependent in/out microsequences */ ppb_lock(ppbus); if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT))) goto error; /* ppbus sets automatically the last mode entered during detection */ switch (vpo->vpo_mode_found) { case VP0_MODE_EPP: ppb_MS_GET_init(ppbus, vpo->vpo_dev, epp17_instr_body); ppb_MS_PUT_init(ppbus, vpo->vpo_dev, epp17_outstr_body); device_printf(vpo->vpo_dev, "EPP mode\n"); break; case VP0_MODE_PS2: ppb_MS_GET_init(ppbus, vpo->vpo_dev, ps2_inbyte_submicroseq); ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq); device_printf(vpo->vpo_dev, "PS2 mode\n"); break; case VP0_MODE_NIBBLE: ppb_MS_GET_init(ppbus, vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq); ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq); device_printf(vpo->vpo_dev, "NIBBLE mode\n"); break; default: panic("vpo: unknown mode %d", vpo->vpo_mode_found); } ppb_release_bus(ppbus, vpo->vpo_dev); error: ppb_unlock(ppbus); return (error); }
static int lpbb_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr) { device_t ppbus = device_get_parent(dev); ppb_lock(ppbus); if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) { ppb_unlock(ppbus); device_printf(dev, "can't allocate ppbus\n"); return (0); } lpbb_reset_bus(dev); ppb_release_bus(ppbus, dev); ppb_unlock(ppbus); return (IIC_ENOADDR); }
static int pcfclock_open(dev_t dev, int flag, int fms, struct thread *td) { u_int unit = minor(dev); struct pcfclock_data *sc = UNITOSOFTC(unit); device_t pcfclockdev = UNITODEVICE(unit); device_t ppbus = device_get_parent(pcfclockdev); int res; if (!sc) return (ENXIO); if ((res = ppb_request_bus(ppbus, pcfclockdev, (flag & O_NONBLOCK) ? PPB_DONTWAIT : PPB_WAIT))) return (res); sc->count++; return (0); }
/* * how : PPB_WAIT or PPB_DONTWAIT */ static int vpoio_connect(struct vpoio_data *vpo, int how) { device_t ppbus = device_get_parent(vpo->vpo_dev); int error; int ret; if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, how))) { #ifdef VP0_DEBUG printf("%s: can't request bus!\n", __func__); #endif return (error); } if (PPB_IN_EPP_MODE(ppbus)) ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_epp_microseq, &ret); else ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret); return (0); }
/* * vpoio_detect() * * Detect and initialise the VP0 adapter. */ static int vpoio_detect(struct vpoio_data *vpo) { device_t ppbus = device_get_parent(vpo->vpo_dev); int error, ret; /* allocate the bus, then apply microsequences */ if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_DONTWAIT))) return (error); /* Force disconnection */ ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); /* Try to enter EPP mode, then connect to the drive in EPP mode */ if (ppb_set_mode(ppbus, PPB_EPP) != -1) { /* call manually the microseq instead of using the appropriate function * since we already requested the ppbus */ ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_epp_microseq, &ret); } /* If EPP mode switch failed or ZIP connection in EPP mode failed, * try to connect in NIBBLE mode */ if (!vpoio_in_disk_mode(vpo)) { /* The interface must be at least PS/2 or NIBBLE capable. * There is no way to know if the ZIP will work with * PS/2 mode since PS/2 and SPP both use the same connect * sequence. One must supress PS/2 with boot flags if * PS/2 mode fails (see ppc(4)). */ if (ppb_set_mode(ppbus, PPB_PS2) != -1) { vpo->vpo_mode_found = VP0_MODE_PS2; } else { if (ppb_set_mode(ppbus, PPB_NIBBLE) == -1) goto error; vpo->vpo_mode_found = VP0_MODE_NIBBLE; } /* Can't know if the interface is capable of PS/2 yet */ ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret); if (!vpoio_in_disk_mode(vpo)) { vpo->vpo_mode_found = VP0_MODE_UNDEFINED; if (bootverbose) device_printf(vpo->vpo_dev, "can't connect to the drive\n"); /* disconnect and release the bus */ ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); goto error; } } else { vpo->vpo_mode_found = VP0_MODE_EPP; } /* send SCSI reset signal */ vpoio_reset(vpo); ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); /* ensure we are disconnected or daisy chained peripheral * may cause serious problem to the disk */ if (vpoio_in_disk_mode(vpo)) { if (bootverbose) device_printf(vpo->vpo_dev, "can't disconnect from the drive\n"); goto error; } ppb_release_bus(ppbus, vpo->vpo_dev); return (0); error: ppb_release_bus(ppbus, vpo->vpo_dev); return (VP0_EINITFAILED); }