Property changes on: . ___________________________________________________________________ Modified: svn:mergeinfo Merged /head/sys:r182013-182014,182016,183053,184130,184164,184176,184896,185003 Index: dev/ppc/ppc_acpi.c =================================================================== --- dev/ppc/ppc_acpi.c (revision 187564) +++ dev/ppc/ppc_acpi.c (working copy) @@ -33,7 +33,7 @@ #include #include #include - + #include #include @@ -63,9 +63,9 @@ /* bus interface */ DEVMETHOD(bus_read_ivar, ppc_read_ivar), - DEVMETHOD(bus_setup_intr, ppc_setup_intr), - DEVMETHOD(bus_teardown_intr, ppc_teardown_intr), - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_write_ivar, ppc_write_ivar), + DEVMETHOD(bus_alloc_resource, ppc_alloc_resource), + DEVMETHOD(bus_release_resource, ppc_release_resource), /* ppbus interface */ DEVMETHOD(ppbus_io, ppc_io), Index: dev/ppc/ppc_isa.c =================================================================== --- dev/ppc/ppc_isa.c (revision 187564) +++ dev/ppc/ppc_isa.c (working copy) @@ -32,10 +32,13 @@ #include #include #include +#include #include +#include #include #include #include +#include #if defined(__i386__) && defined(PC98) #include @@ -60,13 +63,13 @@ /* device interface */ DEVMETHOD(device_probe, ppc_isa_probe), DEVMETHOD(device_attach, ppc_isa_attach), - DEVMETHOD(device_detach, ppc_attach), + DEVMETHOD(device_detach, ppc_detach), /* bus interface */ DEVMETHOD(bus_read_ivar, ppc_read_ivar), - DEVMETHOD(bus_setup_intr, ppc_setup_intr), - DEVMETHOD(bus_teardown_intr, ppc_teardown_intr), - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_write_ivar, ppc_write_ivar), + DEVMETHOD(bus_alloc_resource, ppc_alloc_resource), + DEVMETHOD(bus_release_resource, ppc_release_resource), /* ppbus interface */ DEVMETHOD(ppbus_io, ppc_io), @@ -146,7 +149,8 @@ int s, error = 0; int spin; - if (!(ppc->ppc_avm & PPB_ECP) || !ppc->ppc_registered) + PPC_ASSERT_LOCKED(ppc); + if (!(ppc->ppc_avm & PPB_ECP)) return (EINVAL); if (ppc->ppc_dmachan == 0) return (EINVAL); @@ -218,7 +222,8 @@ */ do { /* release CPU */ - error = tsleep(ppc, PPBPRI | PCATCH, "ppcdma", 0); + error = mtx_sleep(ppc, &ppc->ppc_lock, PPBPRI | PCATCH, + "ppcdma", 0); } while (error == EWOULDBLOCK); splx(s); @@ -247,7 +252,8 @@ #ifdef PPC_DEBUG printf("Z"); #endif - error = tsleep(ppc, PPBPRI | PCATCH, "ppcfifo", hz/100); + error = mtx_sleep(ppc, &ppc->ppc_lock, PPBPRI | PCATCH, + "ppcfifo", hz / 100); if (error != EWOULDBLOCK) { #ifdef PPC_DEBUG printf("I"); Index: dev/ppc/ppcvar.h =================================================================== --- dev/ppc/ppcvar.h (revision 187564) +++ dev/ppc/ppcvar.h (working copy) @@ -32,6 +32,7 @@ int ppc_attach(device_t dev); int ppc_detach(device_t dev); int ppc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val); +int ppc_write_ivar(device_t bus, device_t dev, int index, uintptr_t val); int ppc_read(device_t, char *, int, int); int ppc_write(device_t, char *, int, int); @@ -39,9 +40,10 @@ u_char ppc_io(device_t, int, u_char *, int, u_char); int ppc_exec_microseq(device_t, struct ppb_microseq **); -int ppc_setup_intr(device_t, device_t, struct resource *, int, - driver_filter_t *filt, void (*)(void *), void *, void **); -int ppc_teardown_intr(device_t, device_t, struct resource *, void *); +struct resource *ppc_alloc_resource(device_t bus, device_t child, int type, + int *rid, u_long start, u_long end, u_long count, u_int flags); +int ppc_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r); void ppc_reset_epp(device_t); void ppc_ecp_sync(device_t); int ppc_setmode(device_t, int); Index: dev/ppc/ppc.c =================================================================== --- dev/ppc/ppc.c (revision 187564) +++ dev/ppc/ppc.c (working copy) @@ -32,11 +32,15 @@ #include #include +#include #include +#include +#include #include -#include #include - +#include +#include + #include #include #include @@ -112,11 +116,12 @@ * ppc_ecp_sync() XXX */ void -ppc_ecp_sync(device_t dev) { - +ppc_ecp_sync(device_t dev) +{ int i, r; struct ppc_data *ppc = DEVTOSOFTC(dev); + PPC_ASSERT_LOCKED(ppc); if (!(ppc->ppc_avm & PPB_ECP) && !(ppc->ppc_dtm & PPB_ECP)) return; @@ -131,8 +136,7 @@ DELAY(100); } - printf("ppc%d: ECP sync failed as data still " \ - "present in FIFO.\n", ppc->ppc_unit); + device_printf(dev, "ECP sync failed as data still present in FIFO.\n"); return; } @@ -148,7 +152,7 @@ char ecr_sav; char ctr_sav, ctr, cc; short i; - + /* save registers */ ecr_sav = r_ecr(ppc); ctr_sav = r_ctr(ppc); @@ -235,7 +239,7 @@ LOG_PPC(__func__, ppc, "can't empty the FIFO"); goto error; } - + w_ctr(ppc, ctr_sav); w_ecr(ppc, ecr_sav); @@ -406,9 +410,9 @@ static int index = 0; int idport, irq; int ptr, pcr, val, i; - + while ((idport = pc873xx_basetab[index++])) { - + /* XXX should check first to see if this location is already claimed */ /* @@ -455,7 +459,7 @@ } printf("\n"); } - + /* * We think we have one. Is it enabled and where we want it to be? */ @@ -473,7 +477,7 @@ /* First try to change the port address to that requested... */ - switch(ppc->ppc_base) { + switch (ppc->ppc_base) { case 0x378: val &= 0xfc; break; @@ -512,7 +516,7 @@ } outb(idport, PC873_PTR); - ptr = inb(idport + 1); + ptr = inb(idport + 1); /* get irq settings */ if (ppc->ppc_base == 0x378) @@ -522,7 +526,7 @@ if (bootverbose) printf("PC873xx irq %d at 0x%x\n", irq, ppc->ppc_base); - + /* * Check if irq settings are correct */ @@ -552,7 +556,7 @@ outb(idport, PC873_PCR); pcr = inb(idport + 1); - + if ((ptr & PC873_CFGLOCK) || !chipset_mode) { if (bootverbose) printf("PC873xx %s", (ptr & PC873_CFGLOCK)?"locked":"unlocked"); @@ -562,7 +566,7 @@ printf(", NIBBLE"); if (pcr & PC873_EPPEN) { - ppc->ppc_avm |= PPB_EPP; + ppc->ppc_avm |= PPB_EPP; if (bootverbose) printf(", EPP"); @@ -595,8 +599,8 @@ ptr = inb(idport + 1); if (ptr & PC873_EXTENDED) { ppc->ppc_avm |= PPB_SPP; - if (bootverbose) - printf(", SPP"); + if (bootverbose) + printf(", SPP"); } } } else { @@ -651,7 +655,7 @@ if (bootverbose) printf(", PS/2"); - + } else { /* default to NIBBLE mode */ ptr &= ~PC873_EXTENDED; @@ -698,7 +702,7 @@ /* * Detection: enter configuration mode and read CRD register. */ - + s = splhigh(); outb(csr, SMC665_iCODE); outb(csr, SMC665_iCODE); @@ -750,8 +754,8 @@ if (bootverbose) { outb(csr, 0x1); - printf("ppc%d: SMC registers CR1=0x%x", ppc->ppc_unit, - inb(cio) & 0xff); + device_printf(ppc->ppc_dev, "SMC registers CR1=0x%x", + inb(cio) & 0xff); outb(csr, 0x4); printf(" CR4=0x%x", inb(cio) & 0xff); @@ -913,7 +917,7 @@ ppc->ppc_model = type; outb(SMC935_IND, SMC935_LOGDEV); /* select parallel port, */ - outb(SMC935_DAT, 3); /* which is logical device 3 */ + outb(SMC935_DAT, 3); /* which is logical device 3 */ /* set io port base */ outb(SMC935_IND, SMC935_PORTHI); @@ -982,7 +986,7 @@ #define efdr ((efer == 0x250) ? 0x252 : 0x3f1) static int w83877f_efers[] = { 0x250, 0x3f0, 0x3f0, 0x250 }; -static int w83877f_keys[] = { 0x89, 0x86, 0x87, 0x88 }; +static int w83877f_keys[] = { 0x89, 0x86, 0x87, 0x88 }; static int w83877f_keyiter[] = { 1, 2, 2, 1 }; static int w83877f_hefs[] = { WINB_HEFERE, WINB_HEFRAS, WINB_HEFERE | WINB_HEFRAS, 0 }; @@ -1044,7 +1048,7 @@ if (bootverbose) { /* dump of registers */ - printf("ppc%d: 0x%x - ", ppc->ppc_unit, w83877f_keys[i]); + device_printf(ppc->ppc_dev, "0x%x - ", w83877f_keys[i]); for (i = 0; i <= 0xd; i ++) { outb(efir, i); printf("0x%x ", inb(efdr)); @@ -1060,7 +1064,6 @@ printf("0x%x ", inb(efdr)); } printf("\n"); - printf("ppc%d:", ppc->ppc_unit); } ppc->ppc_type = PPC_TYPE_GENERIC; @@ -1079,8 +1082,8 @@ switch (r) { case WINB_W83757: if (bootverbose) - printf("ppc%d: W83757 compatible mode\n", - ppc->ppc_unit); + device_printf(ppc->ppc_dev, + "W83757 compatible mode\n"); return (-1); /* generic or SMC-like */ case WINB_EXTFDC: @@ -1088,19 +1091,20 @@ case WINB_EXT2FDD: case WINB_JOYSTICK: if (bootverbose) - printf(" not in parallel port mode\n"); + device_printf(ppc->ppc_dev, + "not in parallel port mode\n"); return (-1); case (WINB_PARALLEL | WINB_EPP_SPP): ppc->ppc_avm |= PPB_EPP | PPB_SPP; if (bootverbose) - printf(" EPP SPP"); + device_printf(ppc->ppc_dev, "EPP SPP\n"); break; case (WINB_PARALLEL | WINB_ECP): ppc->ppc_avm |= PPB_ECP | PPB_SPP; if (bootverbose) - printf(" ECP SPP"); + device_printf(ppc->ppc_dev, "ECP SPP\n"); break; case (WINB_PARALLEL | WINB_ECP_EPP): @@ -1108,7 +1112,7 @@ ppc->ppc_type = PPC_TYPE_SMCLIKE; if (bootverbose) - printf(" ECP+EPP SPP"); + device_printf(ppc->ppc_dev, "ECP+EPP SPP\n"); break; default: printf("%s: unknown case (0x%x)!\n", __func__, r); @@ -1129,27 +1133,25 @@ if (chipset_mode & PPB_EPP) { outb(efdr, inb(efdr) | WINB_ECP_EPP); if (bootverbose) - printf(" ECP+EPP"); + device_printf(ppc->ppc_dev, + "ECP+EPP\n"); ppc->ppc_type = PPC_TYPE_SMCLIKE; } else { outb(efdr, inb(efdr) | WINB_ECP); if (bootverbose) - printf(" ECP"); + device_printf(ppc->ppc_dev, "ECP\n"); } } else { /* select EPP_SPP otherwise */ outb(efdr, inb(efdr) | WINB_EPP_SPP); if (bootverbose) - printf(" EPP SPP"); + device_printf(ppc->ppc_dev, "EPP SPP\n"); } ppc->ppc_avm = chipset_mode; } - if (bootverbose) - printf("\n"); - /* exit configuration mode */ outb(efer, 0xaa); @@ -1176,14 +1178,14 @@ ppc->ppc_type = PPC_TYPE_GENERIC; if (bootverbose) - printf("ppc%d:", ppc->ppc_unit); + device_printf(ppc->ppc_dev, "SPP"); /* first, check for ECP */ w_ecr(ppc, PPC_ECR_PS2); if ((r_ecr(ppc) & 0xe0) == PPC_ECR_PS2) { ppc->ppc_dtm |= PPB_ECP | PPB_SPP; if (bootverbose) - printf(" ECP SPP"); + printf(" ECP "); /* search for SMC style ECP+EPP mode */ w_ecr(ppc, PPC_ECR_EPP); @@ -1212,9 +1214,6 @@ /* XXX try to detect NIBBLE and PS2 modes */ ppc->ppc_dtm |= PPB_NIBBLE; - if (bootverbose) - printf(" SPP"); - if (chipset_mode) ppc->ppc_avm = chipset_mode; else @@ -1319,21 +1318,22 @@ /* microsequence registers are equivalent to PC-like port registers */ -#define r_reg(reg,ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, reg)) -#define w_reg(reg, ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, reg, byte)) +#define r_reg(reg,ppc) (bus_read_1((ppc)->res_ioport, reg)) +#define w_reg(reg, ppc, byte) (bus_write_1((ppc)->res_ioport, reg, byte)) #define INCR_PC (mi ++) /* increment program counter */ + PPC_ASSERT_LOCKED(ppc); mi = *p_msq; for (;;) { - switch (mi->opcode) { + switch (mi->opcode) { case MS_OP_RSET: cc = r_reg(mi->arg[0].i, ppc); cc &= (char)mi->arg[2].i; /* clear mask */ cc |= (char)mi->arg[1].i; /* assert mask */ - w_reg(mi->arg[0].i, ppc, cc); + w_reg(mi->arg[0].i, ppc, cc); INCR_PC; - break; + break; case MS_OP_RASSERT_P: reg = mi->arg[1].i; @@ -1352,7 +1352,7 @@ INCR_PC; break; - case MS_OP_RFETCH_P: + case MS_OP_RFETCH_P: reg = mi->arg[1].i; mask = (char)mi->arg[2].i; ptr = ppc->ppc_ptr; @@ -1368,17 +1368,17 @@ ppc->ppc_ptr = ptr; INCR_PC; - break; + break; - case MS_OP_RFETCH: + case MS_OP_RFETCH: *((char *) mi->arg[2].p) = r_reg(mi->arg[0].i, ppc) & (char)mi->arg[1].i; INCR_PC; - break; + break; case MS_OP_RASSERT: - case MS_OP_DELAY: - + case MS_OP_DELAY: + /* let's suppose the next instr. is the same */ prefetch: for (;mi->opcode == MS_OP_RASSERT; INCR_PC) @@ -1392,8 +1392,11 @@ break; case MS_OP_ADELAY: - if (mi->arg[0].i) + if (mi->arg[0].i) { + PPC_UNLOCK(ppc); pause("ppbdelay", mi->arg[0].i * (hz/1000)); + PPC_LOCK(ppc); + } INCR_PC; break; @@ -1410,30 +1413,30 @@ INCR_PC; break; - case MS_OP_SET: - ppc->ppc_accum = mi->arg[0].i; + case MS_OP_SET: + ppc->ppc_accum = mi->arg[0].i; INCR_PC; - break; + break; - case MS_OP_DBRA: - if (--ppc->ppc_accum > 0) - mi += mi->arg[0].i; + case MS_OP_DBRA: + if (--ppc->ppc_accum > 0) + mi += mi->arg[0].i; INCR_PC; - break; + break; - case MS_OP_BRSET: - cc = r_str(ppc); - if ((cc & (char)mi->arg[0].i) == (char)mi->arg[0].i) - mi += mi->arg[1].i; + case MS_OP_BRSET: + cc = r_str(ppc); + if ((cc & (char)mi->arg[0].i) == (char)mi->arg[0].i) + mi += mi->arg[1].i; INCR_PC; - break; + break; - case MS_OP_BRCLEAR: - cc = r_str(ppc); - if ((cc & (char)mi->arg[0].i) == 0) - mi += mi->arg[1].i; + case MS_OP_BRCLEAR: + cc = r_str(ppc); + if ((cc & (char)mi->arg[0].i) == 0) + mi += mi->arg[1].i; INCR_PC; - break; + break; case MS_OP_BRSTAT: cc = r_str(ppc); @@ -1488,9 +1491,9 @@ INCR_PC; break; - case MS_OP_PUT: - case MS_OP_GET: - case MS_OP_RET: + case MS_OP_PUT: + case MS_OP_GET: + case MS_OP_RET: /* can't return to ppb level during the execution * of a submicrosequence */ if (stack) @@ -1503,10 +1506,10 @@ /* return to ppb level of execution */ return (0); - default: - panic("%s: unknown microsequence opcode 0x%x", - __func__, mi->opcode); - } + default: + panic("%s: unknown microsequence opcode 0x%x", + __func__, mi->opcode); + } } /* unreached */ @@ -1515,10 +1518,23 @@ static void ppcintr(void *arg) { - device_t dev = (device_t)arg; - struct ppc_data *ppc = (struct ppc_data *)device_get_softc(dev); + struct ppc_data *ppc = arg; u_char ctr, ecr, str; + /* + * If we have any child interrupt handlers registered, let + * them handle this interrupt. + * + * XXX: If DMA is in progress should we just complete that w/o + * doing this? + */ + PPC_LOCK(ppc); + if (ppc->ppc_intr_hook != NULL && + ppc->ppc_intr_hook(ppc->ppc_intr_arg) == 0) { + PPC_UNLOCK(ppc); + return; + } + str = r_str(ppc); ctr = r_ctr(ppc); ecr = r_ecr(ppc); @@ -1529,6 +1545,7 @@ /* don't use ecp mode with IRQENABLE set */ if (ctr & IRQENABLE) { + PPC_UNLOCK(ppc); return; } @@ -1543,6 +1560,7 @@ ppc->ppc_irqstat &= ~PPC_IRQ_nFAULT; } else { /* shall be handled by underlying layers XXX */ + PPC_UNLOCK(ppc); return; } } @@ -1578,6 +1596,7 @@ /* classic interrupt I/O */ ppc->ppc_irqstat &= ~PPC_IRQ_FIFO; } + PPC_UNLOCK(ppc); return; } @@ -1598,7 +1617,8 @@ ppc_reset_epp(device_t dev) { struct ppc_data *ppc = DEVTOSOFTC(dev); - + + PPC_ASSERT_LOCKED(ppc); ppc_reset_epp_timeout(ppc); return; @@ -1609,6 +1629,7 @@ { struct ppc_data *ppc = DEVTOSOFTC(dev); + PPC_ASSERT_LOCKED(ppc); switch (ppc->ppc_type) { case PPC_TYPE_SMCLIKE: return (ppc_smclike_setmode(ppc, mode)); @@ -1661,19 +1682,18 @@ next_bios_ppc += 1; if (bootverbose) device_printf(dev, - "parallel port found at 0x%x\n", - (int) port); + "parallel port found at 0x%lx\n", port); } #else - if((next_bios_ppc < BIOS_MAX_PPC) && - (*(BIOS_PORTS+next_bios_ppc) != 0) ) { - port = *(BIOS_PORTS+next_bios_ppc++); + if ((next_bios_ppc < BIOS_MAX_PPC) && + (*(BIOS_PORTS + next_bios_ppc) != 0)) { + port = *(BIOS_PORTS + next_bios_ppc++); if (bootverbose) - device_printf(dev, "parallel port found at 0x%x\n", - (int) port); + device_printf(dev, + "parallel port found at 0x%lx\n", port); } else { device_printf(dev, "parallel port not found.\n"); - return ENXIO; + return (ENXIO); } #endif /* PC98 */ bus_set_resource(dev, SYS_RES_IOPORT, rid, port, @@ -1708,9 +1728,6 @@ ppc->ppc_base = rman_get_start(ppc->res_ioport); - ppc->bsh = rman_get_bushandle(ppc->res_ioport); - ppc->bst = rman_get_bustag(ppc->res_ioport); - ppc->ppc_flags = device_get_flags(dev); if (!(ppc->ppc_flags & 0x20)) { @@ -1727,7 +1744,7 @@ if (ppc->res_drq) ppc->ppc_dmachan = rman_get_start(ppc->res_drq); - ppc->ppc_unit = device_get_unit(dev); + ppc->ppc_dev = dev; ppc->ppc_model = GENERIC; ppc->ppc_mode = PPB_COMPATIBLE; @@ -1793,37 +1810,40 @@ ppc_attach(device_t dev) { struct ppc_data *ppc = DEVTOSOFTC(dev); + int error; - device_t ppbus; + mtx_init(&ppc->ppc_lock, device_get_nameunit(dev), "ppc", MTX_DEF); device_printf(dev, "%s chipset (%s) in %s mode%s\n", ppc_models[ppc->ppc_model], ppc_avms[ppc->ppc_avm], ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ? ppc_epp_protocol[ppc->ppc_epp] : ""); - + if (ppc->ppc_fifo) device_printf(dev, "FIFO with %d/%d/%d bytes threshold\n", ppc->ppc_fifo, ppc->ppc_wthr, ppc->ppc_rthr); + if (ppc->res_irq) { + /* default to the tty mask for registration */ /* XXX */ + error = bus_setup_intr(dev, ppc->res_irq, INTR_TYPE_TTY | + INTR_MPSAFE, NULL, ppcintr, ppc, &ppc->intr_cookie); + if (error) { + device_printf(dev, + "failed to register interrupt handler: %d\n", + error); + mtx_destroy(&ppc->ppc_lock); + return (error); + } + } + /* add ppbus as a child of this isa to parallel bridge */ - ppbus = device_add_child(dev, "ppbus", -1); + ppc->ppbus = device_add_child(dev, "ppbus", -1); /* * Probe the ppbus and attach devices found. */ - device_probe_and_attach(ppbus); + device_probe_and_attach(ppc->ppbus); - /* register the ppc interrupt handler as default */ - if (ppc->res_irq) { - /* default to the tty mask for registration */ /* XXX */ - if (bus_setup_intr(dev, ppc->res_irq, INTR_TYPE_TTY, - NULL, ppcintr, dev, &ppc->intr_cookie) == 0) { - - /* remember the ppcintr is registered */ - ppc->ppc_registered = 1; - } - } - return (0); } @@ -1860,6 +1880,8 @@ ppc->res_drq); } + mtx_destroy(&ppc->ppc_lock); + return (0); } @@ -1867,24 +1889,26 @@ ppc_io(device_t ppcdev, int iop, u_char *addr, int cnt, u_char byte) { struct ppc_data *ppc = DEVTOSOFTC(ppcdev); + + PPC_ASSERT_LOCKED(ppc); switch (iop) { case PPB_OUTSB_EPP: - bus_space_write_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt); + bus_write_multi_1(ppc->res_ioport, PPC_EPP_DATA, addr, cnt); break; case PPB_OUTSW_EPP: - bus_space_write_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt); + bus_write_multi_2(ppc->res_ioport, PPC_EPP_DATA, (u_int16_t *)addr, cnt); break; case PPB_OUTSL_EPP: - bus_space_write_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt); + bus_write_multi_4(ppc->res_ioport, PPC_EPP_DATA, (u_int32_t *)addr, cnt); break; case PPB_INSB_EPP: - bus_space_read_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt); + bus_read_multi_1(ppc->res_ioport, PPC_EPP_DATA, addr, cnt); break; case PPB_INSW_EPP: - bus_space_read_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt); + bus_read_multi_2(ppc->res_ioport, PPC_EPP_DATA, (u_int16_t *)addr, cnt); break; case PPB_INSL_EPP: - bus_space_read_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt); + bus_read_multi_4(ppc->res_ioport, PPC_EPP_DATA, (u_int32_t *)addr, cnt); break; case PPB_RDTR: return (r_dtr(ppc)); @@ -1936,10 +1960,11 @@ switch (index) { case PPC_IVAR_EPP_PROTO: + PPC_ASSERT_LOCKED(ppc); *val = (u_long)ppc->ppc_epp; break; - case PPC_IVAR_IRQ: - *val = (u_long)ppc->ppc_irq; + case PPC_IVAR_LOCK: + *val = (uintptr_t)&ppc->ppc_lock; break; default: return (ENOENT); @@ -1948,65 +1973,69 @@ return (0); } -/* - * Resource is useless here since ppbus devices' interrupt handlers are - * multiplexed to the same resource initially allocated by ppc - */ int -ppc_setup_intr(device_t bus, device_t child, struct resource *r, int flags, - driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep) +ppc_write_ivar(device_t bus, device_t dev, int index, uintptr_t val) { - int error; - struct ppc_data *ppc = DEVTOSOFTC(bus); + struct ppc_data *ppc = (struct ppc_data *)device_get_softc(bus); - if (ppc->ppc_registered) { - /* XXX refuse registration if DMA is in progress */ - - /* first, unregister the default interrupt handler */ - if ((error = BUS_TEARDOWN_INTR(device_get_parent(bus), - bus, ppc->res_irq, ppc->intr_cookie))) - return (error); - -/* bus_deactivate_resource(bus, SYS_RES_IRQ, ppc->rid_irq, */ -/* ppc->res_irq); */ - - /* DMA/FIFO operation won't be possible anymore */ - ppc->ppc_registered = 0; + switch (index) { + case PPC_IVAR_INTR_HANDLER: + PPC_ASSERT_LOCKED(ppc); + if (dev != ppc->ppbus) + return (EINVAL); + if (val == 0) { + ppc->ppc_intr_hook = NULL; + break; + } + if (ppc->ppc_intr_hook != NULL) + return (EBUSY); + ppc->ppc_intr_hook = (void *)val; + ppc->ppc_intr_arg = device_get_softc(dev); + break; + default: + return (ENOENT); } - /* - * pass registration to the upper layer, ignore the incoming - * resource - */ - return (BUS_SETUP_INTR(device_get_parent(bus), child, - r, flags, filt, ihand, arg, cookiep)); + return (0); } /* - * When no underlying device has a registered interrupt, register the ppc - * layer one + * We allow child devices to allocate an IRQ resource at rid 0 for their + * interrupt handlers. */ -int -ppc_teardown_intr(device_t bus, device_t child, struct resource *r, void *ih) +struct resource * +ppc_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) { - int error; struct ppc_data *ppc = DEVTOSOFTC(bus); - device_t parent = device_get_parent(bus); - /* pass unregistration to the upper layer */ - if ((error = BUS_TEARDOWN_INTR(parent, child, r, ih))) - return (error); + switch (type) { + case SYS_RES_IRQ: + if (*rid == 0) + return (ppc->res_irq); + break; + } + return (NULL); +} - /* default to the tty mask for registration */ /* XXX */ - if (ppc->ppc_irq && - !(error = BUS_SETUP_INTR(parent, bus, ppc->res_irq, - INTR_TYPE_TTY, NULL, ppcintr, bus, &ppc->intr_cookie))) { +int +ppc_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ +#ifdef INVARIANTS + struct ppc_data *ppc = DEVTOSOFTC(bus); +#endif - /* remember the ppcintr is registered */ - ppc->ppc_registered = 1; + switch (type) { + case SYS_RES_IRQ: + if (rid == 0) { + KASSERT(r == ppc->res_irq, + ("ppc child IRQ resource mismatch")); + return (0); + } + break; } - - return (error); + return (EINVAL); } MODULE_DEPEND(ppc, ppbus, 1, 1, 1); Index: dev/ppc/ppcreg.h =================================================================== --- dev/ppc/ppcreg.h (revision 187564) +++ dev/ppc/ppcreg.h (working copy) @@ -29,6 +29,9 @@ #ifndef __PPCREG_H #define __PPCREG_H +#include +#include + /* * Parallel Port Chipset type. */ @@ -56,8 +59,7 @@ * Generic structure to hold parallel port chipset info. */ struct ppc_data { - - int ppc_unit; + device_t ppc_dev; int ppc_model; /* chipset model if detected */ int ppc_type; /* generic or smclike chipset type */ @@ -107,14 +109,18 @@ int rid_irq, rid_drq, rid_ioport; struct resource *res_irq, *res_drq, *res_ioport; - bus_space_handle_t bsh; - bus_space_tag_t bst; - void *intr_cookie; - int ppc_registered; /* 1 if ppcintr() is the registered interrupt */ + ppc_intr_handler ppc_intr_hook; + void *ppc_intr_arg; + + struct mtx ppc_lock; }; +#define PPC_LOCK(data) mtx_lock(&(data)->ppc_lock) +#define PPC_UNLOCK(data) mtx_unlock(&(data)->ppc_lock) +#define PPC_ASSERT_LOCKED(data) mtx_assert(&(data)->ppc_lock, MA_OWNED) + /* * Parallel Port Chipset registers. */ @@ -151,25 +157,25 @@ #define PPC_DISABLE_INTR (PPC_SERVICE_INTR | PPC_nFAULT_INTR) #define PPC_ECR_RESET (PPC_ECR_PS2 | PPC_DISABLE_INTR) -#define r_dtr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_DTR)) -#define r_str(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_STR)) -#define r_ctr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_CTR)) +#define r_dtr(ppc) (bus_read_1((ppc)->res_ioport, PPC_SPP_DTR)) +#define r_str(ppc) (bus_read_1((ppc)->res_ioport, PPC_SPP_STR)) +#define r_ctr(ppc) (bus_read_1((ppc)->res_ioport, PPC_SPP_CTR)) -#define r_epp_A(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_EPP_ADDR)) -#define r_epp_D(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_EPP_DATA)) -#define r_cnfgA(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_CNFGA)) -#define r_cnfgB(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_CNFGB)) -#define r_ecr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_ECR)) -#define r_fifo(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_D_FIFO)) +#define r_epp_A(ppc) (bus_read_1((ppc)->res_ioport, PPC_EPP_ADDR)) +#define r_epp_D(ppc) (bus_read_1((ppc)->res_ioport, PPC_EPP_DATA)) +#define r_cnfgA(ppc) (bus_read_1((ppc)->res_ioport, PPC_ECP_CNFGA)) +#define r_cnfgB(ppc) (bus_read_1((ppc)->res_ioport, PPC_ECP_CNFGB)) +#define r_ecr(ppc) (bus_read_1((ppc)->res_ioport, PPC_ECP_ECR)) +#define r_fifo(ppc) (bus_read_1((ppc)->res_ioport, PPC_ECP_D_FIFO)) -#define w_dtr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_DTR, byte)) -#define w_str(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_STR, byte)) -#define w_ctr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_CTR, byte)) +#define w_dtr(ppc, byte) (bus_write_1((ppc)->res_ioport, PPC_SPP_DTR, byte)) +#define w_str(ppc, byte) (bus_write_1((ppc)->res_ioport, PPC_SPP_STR, byte)) +#define w_ctr(ppc, byte) (bus_write_1((ppc)->res_ioport, PPC_SPP_CTR, byte)) -#define w_epp_A(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_EPP_ADDR, byte)) -#define w_epp_D(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_EPP_DATA, byte)) -#define w_ecr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_ECP_ECR, byte)) -#define w_fifo(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_ECP_D_FIFO, byte)) +#define w_epp_A(ppc, byte) (bus_write_1((ppc)->res_ioport, PPC_EPP_ADDR, byte)) +#define w_epp_D(ppc, byte) (bus_write_1((ppc)->res_ioport, PPC_EPP_DATA, byte)) +#define w_ecr(ppc, byte) (bus_write_1((ppc)->res_ioport, PPC_ECP_ECR, byte)) +#define w_fifo(ppc, byte) (bus_write_1((ppc)->res_ioport, PPC_ECP_D_FIFO, byte)) /* * Register defines for the PC873xx parts Index: dev/ppc/ppc_puc.c =================================================================== --- dev/ppc/ppc_puc.c (revision 187564) +++ dev/ppc/ppc_puc.c (working copy) @@ -55,9 +55,9 @@ /* bus interface */ DEVMETHOD(bus_read_ivar, ppc_read_ivar), - DEVMETHOD(bus_setup_intr, ppc_setup_intr), - DEVMETHOD(bus_teardown_intr, ppc_teardown_intr), - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_write_ivar, ppc_write_ivar), + DEVMETHOD(bus_alloc_resource, ppc_alloc_resource), + DEVMETHOD(bus_release_resource, ppc_release_resource), /* ppbus interface */ DEVMETHOD(ppbus_io, ppc_io), Index: dev/ppc/ppc_pci.c =================================================================== --- dev/ppc/ppc_pci.c (revision 187564) +++ dev/ppc/ppc_pci.c (working copy) @@ -53,9 +53,9 @@ /* bus interface */ DEVMETHOD(bus_read_ivar, ppc_read_ivar), - DEVMETHOD(bus_setup_intr, ppc_setup_intr), - DEVMETHOD(bus_teardown_intr, ppc_teardown_intr), - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_write_ivar, ppc_write_ivar), + DEVMETHOD(bus_alloc_resource, ppc_alloc_resource), + DEVMETHOD(bus_release_resource, ppc_release_resource), /* ppbus interface */ DEVMETHOD(ppbus_io, ppc_io), Index: dev/ppbus/lpt.c =================================================================== --- dev/ppbus/lpt.c (revision 187564) +++ dev/ppbus/lpt.c (working copy) @@ -87,9 +87,9 @@ #include #ifndef LPT_DEBUG -#define lprintf(args) +#define lprintf(args) #else -#define lprintf(args) \ +#define lprintf(args) \ do { \ if (lptflag) \ printf args; \ @@ -104,54 +104,48 @@ #define BUFSIZE 1024 #define BUFSTATSIZE 32 -#define LPTUNIT(s) ((s)&0x03) -#define LPTFLAGS(s) ((s)&0xfc) - struct lpt_data { - + device_t sc_dev; + struct cdev *sc_cdev; + struct cdev *sc_cdev_bypass; short sc_state; /* default case: negative prime, negative ack, handshake strobe, prime once */ u_char sc_control; char sc_flags; -#define LP_POS_INIT 0x04 /* if we are a postive init signal */ -#define LP_POS_ACK 0x08 /* if we are a positive going ack */ -#define LP_NO_PRIME 0x10 /* don't prime the printer at all */ -#define LP_PRIMEOPEN 0x20 /* prime on every open */ -#define LP_AUTOLF 0x40 /* tell printer to do an automatic lf */ -#define LP_BYPASS 0x80 /* bypass printer ready checks */ +#define LP_POS_INIT 0x04 /* if we are a postive init signal */ +#define LP_POS_ACK 0x08 /* if we are a positive going ack */ +#define LP_NO_PRIME 0x10 /* don't prime the printer at all */ +#define LP_PRIMEOPEN 0x20 /* prime on every open */ +#define LP_AUTOLF 0x40 /* tell printer to do an automatic lf */ +#define LP_BYPASS 0x80 /* bypass printer ready checks */ void *sc_inbuf; void *sc_statbuf; short sc_xfercnt ; char sc_primed; char *sc_cp ; u_short sc_irq ; /* IRQ status of port */ -#define LP_HAS_IRQ 0x01 /* we have an irq available */ -#define LP_USE_IRQ 0x02 /* we are using our irq */ -#define LP_ENABLE_IRQ 0x04 /* enable IRQ on open */ -#define LP_ENABLE_EXT 0x10 /* we shall use advanced mode when possible */ +#define LP_HAS_IRQ 0x01 /* we have an irq available */ +#define LP_USE_IRQ 0x02 /* we are using our irq */ +#define LP_ENABLE_IRQ 0x04 /* enable IRQ on open */ +#define LP_ENABLE_EXT 0x10 /* we shall use advanced mode when possible */ u_char sc_backoff ; /* time to call lptout() again */ + struct callout sc_timer; - struct resource *intr_resource; /* interrupt resource */ - void *intr_cookie; /* interrupt registration cookie */ - + struct resource *sc_intr_resource; /* interrupt resource */ + void *sc_intr_cookie; /* interrupt cookie */ }; -#define LPT_NAME "lpt" /* our official name */ +#define LPT_NAME "lpt" /* our official name */ static timeout_t lptout; static int lpt_port_test(device_t dev, u_char data, u_char mask); static int lpt_detect(device_t dev); -#define DEVTOSOFTC(dev) \ +#define DEVTOSOFTC(dev) \ ((struct lpt_data *)device_get_softc(dev)) -#define UNITOSOFTC(unit) \ - ((struct lpt_data *)devclass_get_softc(lpt_devclass, (unit))) -#define UNITODEVICE(unit) \ - (devclass_get_device(lpt_devclass, (unit))) -static void lptintr(device_t dev); -static void lpt_intr(void *arg); /* without spls */ +static void lptintr(void *arg); static devclass_t lpt_devclass; @@ -161,17 +155,15 @@ #define ASLP (1<<1) /* awaiting draining of printer */ #define EERROR (1<<2) /* error was received from printer */ #define OBUSY (1<<3) /* printer is busy doing output */ -#define LPTOUT (1<<4) /* timeout while not selected */ -#define TOUT (1<<5) /* timeout while not selected */ -#define LPTINIT (1<<6) /* waiting to initialize for open */ -#define INTERRUPTED (1<<7) /* write call was interrupted */ +#define LPTOUT (1<<4) /* timeout while not selected */ +#define TOUT (1<<5) /* timeout while not selected */ +#define LPTINIT (1<<6) /* waiting to initialize for open */ +#define INTERRUPTED (1<<7) /* write call was interrupted */ +#define HAVEBUS (1<<8) /* the driver owns the bus */ -#define HAVEBUS (1<<8) /* the driver owns the bus */ - - /* status masks to interrogate printer status */ -#define RDY_MASK (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR) /* ready ? */ -#define LP_READY (LPS_SEL|LPS_NBSY|LPS_NERR) +#define RDY_MASK (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR) /* ready ? */ +#define LP_READY (LPS_SEL|LPS_NBSY|LPS_NERR) /* Printer Ready condition - from lpa.c */ /* Only used in polling code */ @@ -191,7 +183,6 @@ static struct cdevsw lpt_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = lptopen, .d_close = lptclose, .d_read = lptread, @@ -207,13 +198,17 @@ struct lpt_data *sc = DEVTOSOFTC(dev); int error; + /* + * We might already have the bus for a write(2) after an interrupted + * write(2) call. + */ + ppb_assert_locked(ppbus); if (sc->sc_state & HAVEBUS) return (0); - /* we have the bus only if the request succeded */ - if ((error = ppb_request_bus(ppbus, dev, how)) == 0) + error = ppb_request_bus(ppbus, dev, how); + if (error == 0) sc->sc_state |= HAVEBUS; - return (error); } @@ -224,9 +219,12 @@ struct lpt_data *sc = DEVTOSOFTC(dev); int error = 0; - if ((error = ppb_release_bus(ppbus, dev)) == 0) - sc->sc_state &= ~HAVEBUS; - + ppb_assert_locked(ppbus); + if (sc->sc_state & HAVEBUS) { + error = ppb_release_bus(ppbus, dev); + if (error == 0) + sc->sc_state &= ~HAVEBUS; + } return (error); } @@ -314,24 +312,25 @@ status = 1; /* assume success */ + ppb_lock(ppbus); if ((error = lpt_request_ppbus(dev, PPB_DONTWAIT))) { - printf(LPT_NAME ": cannot alloc ppbus (%d)!\n", error); - status = 0; - goto end_probe; + ppb_unlock(ppbus); + device_printf(dev, "cannot alloc ppbus (%d)!\n", error); + return (0); } for (i = 0; i < 18 && status; i++) if (!lpt_port_test(ppbus, testbyte[i], 0xff)) { status = 0; - goto end_probe; + break; } -end_probe: /* write 0's to control and data ports */ ppb_wdtr(ppbus, 0); ppb_wctr(ppbus, 0); lpt_release_ppbus(dev); + ppb_unlock(ppbus); return (status); } @@ -367,45 +366,56 @@ { device_t ppbus = device_get_parent(dev); struct lpt_data *sc = DEVTOSOFTC(dev); - int zero = 0, unit = device_get_unit(dev); + int rid = 0, unit = device_get_unit(dev); int error; - intptr_t irq; sc->sc_primed = 0; /* not primed yet */ + ppb_init_callout(ppbus, &sc->sc_timer, 0); + ppb_lock(ppbus); if ((error = lpt_request_ppbus(dev, PPB_DONTWAIT))) { - printf(LPT_NAME ": cannot alloc ppbus (%d)!\n", error); + ppb_unlock(ppbus); + device_printf(dev, "cannot alloc ppbus (%d)!\n", error); return (0); } ppb_wctr(ppbus, LPC_NINIT); + ppb_unlock(ppbus); + lpt_release_ppbus(dev); - /* check if we can use interrupt, should be done by ppc stuff */ - lprintf(("oldirq %x\n", sc->sc_irq)); - - /* retrieve the ppbus irq */ - BUS_READ_IVAR(ppbus, dev, PPBUS_IVAR_IRQ, &irq); - - if (irq > 0) { - /* declare our interrupt handler */ - sc->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ, - &zero, irq, irq, 1, RF_SHAREABLE); - } - if (sc->intr_resource) { + /* declare our interrupt handler */ + sc->sc_intr_resource = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_SHAREABLE); + if (sc->sc_intr_resource) { + error = bus_setup_intr(dev, sc->sc_intr_resource, + INTR_TYPE_TTY | INTR_MPSAFE, NULL, lptintr, sc, + &sc->sc_intr_cookie); + if (error) { + bus_release_resource(dev, SYS_RES_IRQ, rid, + sc->sc_intr_resource); + device_printf(dev, + "Unable to register interrupt handler\n"); + return (error); + } sc->sc_irq = LP_HAS_IRQ | LP_USE_IRQ | LP_ENABLE_IRQ; device_printf(dev, "Interrupt-driven port\n"); } else { sc->sc_irq = 0; device_printf(dev, "Polled port\n"); } - lprintf(("irq %x %x\n", (int)irq, sc->sc_irq)); + lprintf(("irq %x\n", sc->sc_irq)); - lpt_release_ppbus(dev); - - make_dev(&lpt_cdevsw, unit, + sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK); + sc->sc_statbuf = malloc(BUFSTATSIZE, M_DEVBUF, M_WAITOK); + sc->sc_dev = dev; + sc->sc_cdev = make_dev(&lpt_cdevsw, unit, UID_ROOT, GID_WHEEL, 0600, LPT_NAME "%d", unit); - make_dev(&lpt_cdevsw, unit | LP_BYPASS, + sc->sc_cdev->si_drv1 = sc; + sc->sc_cdev->si_drv2 = 0; + sc->sc_cdev_bypass = make_dev(&lpt_cdevsw, unit, UID_ROOT, GID_WHEEL, 0600, LPT_NAME "%d.ctl", unit); + sc->sc_cdev_bypass->si_drv1 = sc; + sc->sc_cdev_bypass->si_drv2 = (void *)LP_BYPASS; return (0); } @@ -413,13 +423,21 @@ lpt_detach(device_t dev) { struct lpt_data *sc = DEVTOSOFTC(dev); + device_t ppbus = device_get_parent(dev); + destroy_dev(sc->sc_cdev); + destroy_dev(sc->sc_cdev_bypass); + ppb_lock(ppbus); lpt_release_ppbus(dev); - if (sc->intr_resource != 0) { - BUS_TEARDOWN_INTR(device_get_parent(dev), dev, - sc->intr_resource, sc->intr_cookie); - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->intr_resource); + ppb_unlock(ppbus); + callout_drain(&sc->sc_timer); + if (sc->sc_intr_resource != NULL) { + bus_teardown_intr(dev, sc->sc_intr_resource, + sc->sc_intr_cookie); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_intr_resource); } + free(sc->sc_inbuf, M_DEVBUF); + free(sc->sc_statbuf, M_DEVBUF); return (0); } @@ -427,18 +445,17 @@ static void lptout(void *arg) { - device_t dev = (device_t)arg; - struct lpt_data *sc = DEVTOSOFTC(dev); -#ifdef LPT_DEBUG + struct lpt_data *sc = arg; + device_t dev = sc->sc_dev; device_t ppbus = device_get_parent(dev); -#endif + ppb_assert_locked(ppbus); lprintf(("T %x ", ppb_rstr(ppbus))); if (sc->sc_state & OPEN) { sc->sc_backoff++; if (sc->sc_backoff > hz/LPTOUTMAX) sc->sc_backoff = sc->sc_backoff > hz/LPTOUTMAX; - timeout(lptout, (caddr_t)dev, sc->sc_backoff); + callout_reset(&sc->sc_timer, sc->sc_backoff, lptout, sc); } else sc->sc_state &= ~TOUT; @@ -449,7 +466,7 @@ * Avoid possible hangs due to missed interrupts */ if (sc->sc_xfercnt) { - lptintr(dev); + lptintr(sc); } else { sc->sc_state &= ~OBUSY; wakeup(dev); @@ -465,27 +482,29 @@ static int lptopen(struct cdev *dev, int flags, int fmt, struct thread *td) { - int s; int trys, err; - u_int unit = LPTUNIT(minor(dev)); - struct lpt_data *sc = UNITOSOFTC(unit); - device_t lptdev = UNITODEVICE(unit); + struct lpt_data *sc = dev->si_drv1; + device_t lptdev = sc->sc_dev; device_t ppbus = device_get_parent(lptdev); if (!sc) return (ENXIO); + ppb_lock(ppbus); if (sc->sc_state) { - lprintf((LPT_NAME ": still open %x\n", sc->sc_state)); + lprintf(("%s: still open %x\n", device_get_nameunit(lptdev), + sc->sc_state)); + ppb_unlock(ppbus); return(EBUSY); } else sc->sc_state |= LPTINIT; - sc->sc_flags = LPTFLAGS(minor(dev)); + sc->sc_flags = (uintptr_t)dev->si_drv2; /* Check for open with BYPASS flag set. */ if (sc->sc_flags & LP_BYPASS) { sc->sc_state = OPEN; + ppb_unlock(ppbus); return(0); } @@ -493,11 +512,12 @@ if ((err = lpt_request_ppbus(lptdev, PPB_WAIT|PPB_INTR)) != 0) { /* give it a chance to try later */ sc->sc_state = 0; + ppb_unlock(ppbus); return (err); } - s = spltty(); - lprintf((LPT_NAME " flags 0x%x\n", sc->sc_flags)); + lprintf(("%s flags 0x%x\n", device_get_nameunit(lptdev), + sc->sc_flags)); /* set IRQ status according to ENABLE_IRQ flag */ @@ -508,7 +528,7 @@ /* init printer */ if ((sc->sc_flags & LP_NO_PRIME) == 0) { - if((sc->sc_flags & LP_PRIMEOPEN) || sc->sc_primed == 0) { + if ((sc->sc_flags & LP_PRIMEOPEN) || sc->sc_primed == 0) { ppb_wctr(ppbus, 0); sc->sc_primed++; DELAY(500); @@ -522,21 +542,21 @@ do { /* ran out of waiting for the printer */ if (trys++ >= LPINITRDY*4) { - splx(s); sc->sc_state = 0; lprintf(("status %x\n", ppb_rstr(ppbus))); lpt_release_ppbus(lptdev); + ppb_unlock(ppbus); return (EBUSY); } /* wait 1/4 second, give up if we get a signal */ - if (tsleep(lptdev, LPPRI|PCATCH, "lptinit", hz/4) != - EWOULDBLOCK) { + if (ppb_sleep(ppbus, lptdev, LPPRI | PCATCH, "lptinit", + hz / 4) != EWOULDBLOCK) { sc->sc_state = 0; - splx(s); lpt_release_ppbus(lptdev); + ppb_unlock(ppbus); return (EBUSY); } @@ -556,22 +576,20 @@ ppb_wctr(ppbus, sc->sc_control); sc->sc_state = OPEN; - sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK); - sc->sc_statbuf = malloc(BUFSTATSIZE, M_DEVBUF, M_WAITOK); sc->sc_xfercnt = 0; - splx(s); - /* release the ppbus */ - lpt_release_ppbus(lptdev); - /* only use timeout if using interrupt */ lprintf(("irq %x\n", sc->sc_irq)); if (sc->sc_irq & LP_USE_IRQ) { sc->sc_state |= TOUT; - timeout(lptout, (caddr_t)lptdev, - (sc->sc_backoff = hz/LPTOUTINITIAL)); + sc->sc_backoff = hz / LPTOUTINITIAL; + callout_reset(&sc->sc_timer, sc->sc_backoff, lptout, sc); } + /* release the ppbus */ + lpt_release_ppbus(lptdev); + ppb_unlock(ppbus); + lprintf(("opened.\n")); return(0); } @@ -585,42 +603,46 @@ static int lptclose(struct cdev *dev, int flags, int fmt, struct thread *td) { - u_int unit = LPTUNIT(minor(dev)); - struct lpt_data *sc = UNITOSOFTC(unit); - device_t lptdev = UNITODEVICE(unit); - device_t ppbus = device_get_parent(lptdev); + struct lpt_data *sc = dev->si_drv1; + device_t lptdev = sc->sc_dev; + device_t ppbus = device_get_parent(lptdev); int err; - if(sc->sc_flags & LP_BYPASS) + ppb_lock(ppbus); + if (sc->sc_flags & LP_BYPASS) { + sc->sc_state = 0; + ppb_unlock(ppbus); goto end_close; + } - if ((err = lpt_request_ppbus(lptdev, PPB_WAIT|PPB_INTR)) != 0) + if ((err = lpt_request_ppbus(lptdev, PPB_WAIT|PPB_INTR)) != 0) { + ppb_unlock(ppbus); return (err); + } - sc->sc_state &= ~OPEN; - /* if the last write was interrupted, don't complete it */ - if((!(sc->sc_state & INTERRUPTED)) && (sc->sc_irq & LP_USE_IRQ)) + if ((!(sc->sc_state & INTERRUPTED)) && (sc->sc_irq & LP_USE_IRQ)) while ((ppb_rstr(ppbus) & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) != (LPS_SEL|LPS_NBSY|LPS_NERR) || sc->sc_xfercnt) /* wait 1/4 second, give up if we get a signal */ - if (tsleep(lptdev, LPPRI|PCATCH, - "lpclose", hz) != EWOULDBLOCK) + if (ppb_sleep(ppbus, lptdev, LPPRI | PCATCH, "lpclose", + hz) != EWOULDBLOCK) break; + sc->sc_state &= ~OPEN; + callout_stop(&sc->sc_timer); ppb_wctr(ppbus, LPC_NINIT); - free(sc->sc_inbuf, M_DEVBUF); - free(sc->sc_statbuf, M_DEVBUF); + sc->sc_state = 0; + sc->sc_xfercnt = 0; -end_close: - /* release the bus anyway + /* * unregistration of interrupt forced by release */ lpt_release_ppbus(lptdev); + ppb_unlock(ppbus); - sc->sc_state = 0; - sc->sc_xfercnt = 0; +end_close: lprintf(("closed.\n")); return(0); } @@ -634,13 +656,14 @@ * This code is only used when we are polling the port */ static int -lpt_pushbytes(device_t dev) +lpt_pushbytes(struct lpt_data *sc) { - struct lpt_data *sc = DEVTOSOFTC(dev); + device_t dev = sc->sc_dev; device_t ppbus = device_get_parent(dev); int spin, err, tic; char ch; + ppb_assert_locked(ppbus); lprintf(("p")); /* loop for every character .. */ while (sc->sc_xfercnt > 0) { @@ -669,7 +692,7 @@ */ if (tic > MAX_SLEEP) tic = MAX_SLEEP; - err = tsleep(dev, LPPRI, + err = ppb_sleep(ppbus, dev, LPPRI, LPT_NAME "poll", tic); if (err != EWOULDBLOCK) { return (err); @@ -694,10 +717,9 @@ static int lptread(struct cdev *dev, struct uio *uio, int ioflag) { - u_int unit = LPTUNIT(minor(dev)); - struct lpt_data *sc = UNITOSOFTC(unit); - device_t lptdev = UNITODEVICE(unit); - device_t ppbus = device_get_parent(lptdev); + struct lpt_data *sc = dev->si_drv1; + device_t lptdev = sc->sc_dev; + device_t ppbus = device_get_parent(lptdev); int error = 0, len; if (sc->sc_flags & LP_BYPASS) { @@ -705,8 +727,11 @@ return (EPERM); } - if ((error = ppb_1284_negociate(ppbus, PPB_NIBBLE, 0))) + ppb_lock(ppbus); + if ((error = ppb_1284_negociate(ppbus, PPB_NIBBLE, 0))) { + ppb_unlock(ppbus); return (error); + } /* read data in an other buffer, read/write may be simultaneous */ len = 0; @@ -720,12 +745,16 @@ if (!len) goto error; /* no more data */ - if ((error = uiomove(sc->sc_statbuf, len, uio))) + ppb_unlock(ppbus); + error = uiomove(sc->sc_statbuf, len, uio); + ppb_lock(ppbus); + if (error) goto error; } error: ppb_1284_terminate(ppbus); + ppb_unlock(ppbus); return (error); } @@ -741,38 +770,31 @@ { register unsigned n; int err; - u_int unit = LPTUNIT(minor(dev)); - struct lpt_data *sc = UNITOSOFTC(unit); - device_t lptdev = UNITODEVICE(unit); - device_t ppbus = device_get_parent(lptdev); + struct lpt_data *sc = dev->si_drv1; + device_t lptdev = sc->sc_dev; + device_t ppbus = device_get_parent(lptdev); - if(sc->sc_flags & LP_BYPASS) { + if (sc->sc_flags & LP_BYPASS) { /* we can't do writes in bypass mode */ - return(EPERM); + return (EPERM); } /* request the ppbus only if we don't have it already */ - /* XXX interrupt registration?! */ - if ((err = lpt_request_ppbus(lptdev, PPB_WAIT|PPB_INTR)) != 0) + ppb_lock(ppbus); + if ((err = lpt_request_ppbus(lptdev, PPB_WAIT|PPB_INTR)) != 0) { + ppb_unlock(ppbus); return (err); - - /* if interrupts are working, register the handler */ - if (sc->sc_irq & LP_USE_IRQ) { - /* register our interrupt handler */ - err = bus_setup_intr(lptdev, sc->intr_resource, - INTR_TYPE_TTY, NULL, lpt_intr, lptdev, - &sc->intr_cookie); - if (err) { - device_printf(lptdev, "handler registration failed, polled mode.\n"); - sc->sc_irq &= ~LP_USE_IRQ; - } } sc->sc_state &= ~INTERRUPTED; while ((n = min(BUFSIZE, uio->uio_resid)) != 0) { sc->sc_cp = sc->sc_inbuf; - uiomove(sc->sc_cp, n, uio); - sc->sc_xfercnt = n ; + ppb_unlock(ppbus); + err = uiomove(sc->sc_cp, n, uio); + ppb_lock(ppbus); + if (err) + break; + sc->sc_xfercnt = n; if (sc->sc_irq & LP_ENABLE_EXT) { /* try any extended mode */ @@ -785,14 +807,18 @@ sc->sc_xfercnt = 0; break; case EINTR: - sc->sc_state |= INTERRUPTED; - return(err); + sc->sc_state |= INTERRUPTED; + ppb_unlock(ppbus); + return (err); case EINVAL: /* advanced mode not avail */ - log(LOG_NOTICE, LPT_NAME "%d: advanced mode not avail, polling\n", unit); + log(LOG_NOTICE, + "%s: advanced mode not avail, polling\n", + device_get_nameunit(sc->sc_dev)); break; default: - return(err); + ppb_unlock(ppbus); + return (err); } } else while ((sc->sc_xfercnt > 0)&&(sc->sc_irq & LP_USE_IRQ)) { lprintf(("i")); @@ -800,53 +826,52 @@ /* give it one */ if ((sc->sc_state & OBUSY) == 0){ lprintf(("\nC %d. ", sc->sc_xfercnt)); - lptintr(lptdev); + lptintr(sc); } lprintf(("W ")); if (sc->sc_state & OBUSY) - if ((err = tsleep(lptdev, + if ((err = ppb_sleep(ppbus, lptdev, LPPRI|PCATCH, LPT_NAME "write", 0))) { sc->sc_state |= INTERRUPTED; + ppb_unlock(ppbus); return(err); } } /* check to see if we must do a polled write */ - if(!(sc->sc_irq & LP_USE_IRQ) && (sc->sc_xfercnt)) { + if (!(sc->sc_irq & LP_USE_IRQ) && (sc->sc_xfercnt)) { lprintf(("p")); - err = lpt_pushbytes(lptdev); + err = lpt_pushbytes(sc); - if (err) - return(err); + if (err) { + ppb_unlock(ppbus); + return (err); + } } } /* we have not been interrupted, release the ppbus */ lpt_release_ppbus(lptdev); + ppb_unlock(ppbus); - return(0); + return (err); } /* - * lpt_intr -- handle printer interrupts which occur when the printer is + * lptintr -- handle printer interrupts which occur when the printer is * ready to accept another char. * * do checking for interrupted write call. */ - static void -lpt_intr(void *arg) +lptintr(void *arg) { - device_t lptdev = (device_t)arg; - device_t ppbus = device_get_parent(lptdev); - struct lpt_data *sc = DEVTOSOFTC(lptdev); + struct lpt_data *sc = arg; + device_t lptdev = sc->sc_dev; + device_t ppbus = device_get_parent(lptdev); int sts = 0; int i; - - /* we must own the bus to use it */ - if ((sc->sc_state & HAVEBUS) == 0) - return; /* * Is printer online and ready for output? @@ -859,7 +884,7 @@ if ((sts & RDY_MASK) == LP_READY) { sc->sc_state = (sc->sc_state | OBUSY) & ~EERROR; - sc->sc_backoff = hz/LPTOUTINITIAL; + sc->sc_backoff = hz / LPTOUTINITIAL; if (sc->sc_xfercnt) { /* send char */ @@ -870,7 +895,8 @@ ppb_wctr(ppbus, sc->sc_control); /* any more data for printer */ - if(--(sc->sc_xfercnt) > 0) return; + if (--(sc->sc_xfercnt) > 0) + return; } /* @@ -879,12 +905,12 @@ */ sc->sc_state &= ~OBUSY; - if(!(sc->sc_state & INTERRUPTED)) + if (!(sc->sc_state & INTERRUPTED)) wakeup(lptdev); lprintf(("w ")); return; } else { /* check for error */ - if(((sts & (LPS_NERR | LPS_OUT) ) != LPS_NERR) && + if (((sts & (LPS_NERR | LPS_OUT) ) != LPS_NERR) && (sc->sc_state & OPEN)) sc->sc_state |= EERROR; /* lptout() will jump in and try to restart. */ @@ -892,29 +918,19 @@ lprintf(("sts %x ", sts)); } -static void -lptintr(device_t dev) -{ - /* call the interrupt at required spl level */ - int s = spltty(); - - lpt_intr(dev); - - splx(s); - return; -} - static int lptioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) { int error = 0; - u_int unit = LPTUNIT(minor(dev)); - struct lpt_data *sc = UNITOSOFTC(unit); + struct lpt_data *sc = dev->si_drv1; + device_t ppbus; u_char old_sc_irq; /* old printer IRQ status */ switch (cmd) { case LPT_IRQ : - if(sc->sc_irq & LP_HAS_IRQ) { + ppbus = device_get_parent(sc->sc_dev); + ppb_lock(ppbus); + if (sc->sc_irq & LP_HAS_IRQ) { /* * NOTE: * If the IRQ status is changed, @@ -925,7 +941,7 @@ * this gets syslog'd. */ old_sc_irq = sc->sc_irq; - switch(*(int*)data) { + switch (*(int*)data) { case 0: sc->sc_irq &= (~LP_ENABLE_IRQ); break; @@ -946,16 +962,17 @@ default: break; } - + if (old_sc_irq != sc->sc_irq ) - log(LOG_NOTICE, LPT_NAME "%d: switched to %s %s mode\n", - unit, + log(LOG_NOTICE, "%s: switched to %s %s mode\n", + device_get_nameunit(sc->sc_dev), (sc->sc_irq & LP_ENABLE_IRQ)? "interrupt-driven":"polled", (sc->sc_irq & LP_ENABLE_EXT)? "extended":"standard"); } else /* polled port */ error = EOPNOTSUPP; + ppb_unlock(ppbus); break; default: error = ENODEV; Index: dev/ppbus/ppb_1284.c =================================================================== --- dev/ppbus/ppb_1284.c (revision 187564) +++ dev/ppbus/ppb_1284.c (working copy) @@ -36,6 +36,8 @@ #include "opt_ppb_1284.h" #include +#include +#include #include #include @@ -92,7 +94,10 @@ int ppb_1284_get_state(device_t bus) { - return (DEVTOSOFTC(bus)->state); + struct ppb_data *ppb = DEVTOSOFTC(bus); + + mtx_assert(ppb->ppc_lock, MA_OWNED); + return (ppb->state); } /* @@ -107,6 +112,7 @@ /* call ppb_1284_reset_error() if you absolutly want to change * the state from PPB_ERROR to another */ + mtx_assert(ppb->ppc_lock, MA_OWNED); if ((ppb->state != PPB_ERROR) && (ppb->error == PPB_NO_ERROR)) { ppb->state = state; @@ -293,7 +299,7 @@ } /* Event 24 */ - ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); + ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); /* Event 25 - wait up to host response time (1s) */ if ((error = do_peripheral_wait(bus, nBUSY, nBUSY))) { @@ -302,17 +308,17 @@ } /* Event 26 */ - ppb_wctr(bus, (SELECTIN | nINIT | STROBE) & ~(AUTOFEED)); + ppb_wctr(bus, (SELECTIN | nINIT | STROBE) & ~(AUTOFEED)); DELAY(1); /* Event 27 */ - ppb_wctr(bus, (SELECTIN | nINIT) & ~(STROBE | AUTOFEED)); + ppb_wctr(bus, (SELECTIN | nINIT) & ~(STROBE | AUTOFEED)); /* Event 28 - wait up to host response time (1s) */ if ((error = do_peripheral_wait(bus, nBUSY, 0))) { ppb_1284_set_error(bus, PPB_TIMEOUT, 28); goto error; } - + error: ppb_set_mode(bus, PPB_COMPATIBLE); ppb_1284_set_state(bus, PPB_FORWARD_IDLE); @@ -538,7 +544,7 @@ case PPB_REVERSE_IDLE: terminate_after_transfer = 0; break; - + default: ppb_1284_terminate(bus); if ((error = ppb_1284_negociate(bus, mode, 0))) @@ -689,9 +695,9 @@ #ifdef PERIPH_1284 /* request remote host attention */ - ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); - DELAY(1); - ppb_wctr(bus, (nINIT) & ~(STROBE | AUTOFEED | SELECTIN)); + ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); + DELAY(1); + ppb_wctr(bus, (nINIT) & ~(STROBE | AUTOFEED | SELECTIN)); #else DELAY(1); @@ -701,14 +707,14 @@ ppb_wctr(bus, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN)); #ifdef PERIPH_1284 - /* ignore the PError line, wait a bit more, remote host's + /* ignore the PError line, wait a bit more, remote host's * interrupts don't respond fast enough */ if (ppb_poll_bus(bus, 40, nACK | SELECT | nFAULT, SELECT | nFAULT, PPB_NOINTR | PPB_POLL)) { - ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2); - error = ENODEV; - goto error; - } + ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2); + error = ENODEV; + goto error; + } #else /* Event 2 - trying IEEE1284 dialog */ if (do_1284_wait(bus, nACK | PERROR | SELECT | nFAULT, @@ -770,11 +776,11 @@ #ifdef PERIPH_1284 /* ignore PError line */ if (do_1284_wait(bus, nACK | SELECT | nBUSY, - nACK | SELECT | nBUSY)) { - ppb_1284_set_error(bus, PPB_TIMEOUT, 30); - error = ENODEV; - goto error; - } + nACK | SELECT | nBUSY)) { + ppb_1284_set_error(bus, PPB_TIMEOUT, 30); + error = ENODEV; + goto error; + } #else if (do_1284_wait(bus, nACK | SELECT | PERROR | nBUSY, nACK | SELECT | PERROR | nBUSY)) { @@ -824,8 +830,8 @@ #ifdef PERIPH_1284 /* request remote host attention */ - ppb_wctr(bus, (nINIT | STROBE | SELECTIN) & ~(AUTOFEED)); - DELAY(1); + ppb_wctr(bus, (nINIT | STROBE | SELECTIN) & ~(AUTOFEED)); + DELAY(1); #endif /* PERIPH_1284 */ /* Event 22 - set nSelectin low and nAutoFeed high */ Index: dev/ppbus/vpoio.h =================================================================== --- dev/ppbus/vpoio.h (revision 187564) +++ dev/ppbus/vpoio.h (working copy) @@ -38,7 +38,7 @@ #define VP0_ECMD_TIMEOUT 2 #define VP0_ECONNECT 3 #define VP0_ESTATUS_TIMEOUT 4 -#define VP0_EDATA_OVERFLOW 5 +#define VP0_EDATA_OVERFLOW 5 #define VP0_EDISCONNECT 6 #define VP0_EPPDATA_TIMEOUT 7 #define VP0_ENEGOCIATE 8 @@ -66,7 +66,6 @@ #define VP0_MODE_EPP 0x3 struct vpoio_data { - unsigned short int vpo_unit; int vpo_mode_found; /* Mode found during init */ struct vpo_nibble vpo_nibble; @@ -77,8 +76,6 @@ device_t vpo_dev; }; -#define vpoio_set_unit(vpo,unit) ((vpo)->vpo_unit = unit) - int vpoio_probe(device_t dev, struct vpoio_data *vpo); int vpoio_attach(struct vpoio_data *vpo); Index: dev/ppbus/ppb_msq.c =================================================================== --- dev/ppbus/ppb_msq.c (revision 187564) +++ dev/ppbus/ppb_msq.c (working copy) @@ -31,6 +31,8 @@ #include #include +#include +#include #include #include @@ -55,7 +57,7 @@ static struct ppb_xfer * mode2xfer(device_t bus, struct ppb_device *ppbdev, int opcode) { - int index, epp; + int index, epp, mode; struct ppb_xfer *table; switch (opcode) { @@ -72,7 +74,8 @@ } /* retrieve the device operating mode */ - switch (ppb_get_mode(bus)) { + mode = ppb_get_mode(bus); + switch (mode) { case PPB_COMPATIBLE: index = COMPAT_MSQ; break; @@ -99,7 +102,7 @@ index = ECP_MSQ; break; default: - panic("%s: unknown mode (%d)", __func__, ppbdev->mode); + panic("%s: unknown mode (%d)", __func__, mode); } return (&table[index]); @@ -114,9 +117,13 @@ int ppb_MS_init(device_t bus, device_t dev, struct ppb_microseq *loop, int opcode) { +#ifdef INVARIANTS + struct ppb_data *ppb = device_get_softc(bus); +#endif struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev); struct ppb_xfer *xfer = mode2xfer(bus, ppbdev, opcode); + mtx_assert(ppb->ppc_lock, MA_OWNED); xfer->loop = loop; return (0); @@ -209,7 +216,7 @@ __func__, param); #if 0 - printf("%s: param = %d, ins = %d, arg = %d, type = %d\n", + printf("%s: param = %d, ins = %d, arg = %d, type = %d\n", __func__, param, ins, arg, type); #endif @@ -264,6 +271,7 @@ MS_RET(0) }; + mtx_assert(ppb->ppc_lock, MA_OWNED); if (ppb->ppb_owner != dev) return (EACCES); @@ -271,7 +279,7 @@ mi = msq; for (;;) { - switch (mi->opcode) { + switch (mi->opcode) { case MS_OP_PUT: case MS_OP_GET: @@ -314,11 +322,10 @@ INCR_PC; break; - case MS_OP_RET: + case MS_OP_RET: if (ret) *ret = mi->arg[0].i; /* return code */ return (0); - break; default: /* executing microinstructions at ppc level is Index: dev/ppbus/pps.c =================================================================== --- dev/ppbus/pps.c (revision 187564) +++ dev/ppbus/pps.c (working copy) @@ -9,7 +9,7 @@ * * This driver implements a draft-mogul-pps-api-02.txt PPS source. * - * The input pin is pin#10 + * The input pin is pin#10 * The echo output pin is pin#14 * */ @@ -18,9 +18,11 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include +#include #include #include #include @@ -43,15 +45,15 @@ device_t ppsdev; device_t ppbus; int busy; - struct callout_handle timeout; + struct callout timeout; int lastdata; - struct mtx mtx; + struct sx lock; struct resource *intr_resource; /* interrupt resource */ void *intr_cookie; /* interrupt registration cookie */ }; -static int ppsintr(void *arg); +static void ppsintr(void *arg); static void ppshcpoll(void *arg); #define DEVTOSOFTC(dev) \ @@ -77,7 +79,7 @@ device_t dev; - dev = device_find_child(parent, PPS_NAME, 0); + dev = device_find_child(parent, PPS_NAME, -1); if (!dev) BUS_ADD_CHILD(parent, 0, PPS_NAME, -1); } @@ -107,22 +109,29 @@ struct pps_data *sc = DEVTOSOFTC(dev); device_t ppbus = device_get_parent(dev); struct cdev *d; - intptr_t irq; - int i, unit, zero = 0; + int error, i, unit, rid = 0; - mtx_init(&sc->mtx, device_get_nameunit(dev), "pps", MTX_SPIN); - /* retrieve the ppbus irq */ - BUS_READ_IVAR(ppbus, dev, PPBUS_IVAR_IRQ, &irq); + /* declare our interrupt handler */ + sc->intr_resource = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_SHAREABLE); - if (irq > 0) { - /* declare our interrupt handler */ - sc->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ, - &zero, irq, irq, 1, RF_SHAREABLE); - } /* interrupts seem mandatory */ - if (sc->intr_resource == NULL) + if (sc->intr_resource == NULL) { + device_printf(dev, "Unable to allocate interrupt resource\n"); return (ENXIO); + } + error = bus_setup_intr(dev, sc->intr_resource, + INTR_TYPE_TTY | INTR_MPSAFE, NULL, ppsintr, + sc, &sc->intr_cookie); + if (error) { + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->intr_resource); + device_printf(dev, "Unable to register interrupt handler\n"); + return (error); + } + + sx_init(&sc->lock, "pps"); + ppb_init_callout(ppbus, &sc->timeout, 0); sc->ppsdev = dev; sc->ppbus = ppbus; unit = device_get_unit(ppbus); @@ -134,8 +143,11 @@ d->si_drv2 = (void*)0; pps_init(&sc->pps[0]); - if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) + ppb_lock(ppbus); + if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) { + ppb_unlock(ppbus); return (0); + } do { i = ppb_set_mode(sc->ppbus, PPB_EPP); @@ -172,6 +184,7 @@ ppstry(ppbus, 0x55, 0xff); ppstry(ppbus, 0xaa, 0xff); ppstry(ppbus, 0xff, 0xff); + ppb_unlock(ppbus); for (i = 1; i < 9; i++) { d = make_dev(&pps_cdevsw, unit + 0x10000 * i, @@ -182,9 +195,11 @@ d->si_drv2 = (void *)(intptr_t)i; pps_init(&sc->pps[i]); } + ppb_lock(ppbus); } while (0); i = ppb_set_mode(sc->ppbus, PPB_COMPATIBLE); ppb_release_bus(ppbus, dev); + ppb_unlock(ppbus); return (0); } @@ -193,22 +208,24 @@ ppsopen(struct cdev *dev, int flags, int fmt, struct thread *td) { struct pps_data *sc = dev->si_drv1; + device_t ppbus = sc->ppbus; int subdev = (intptr_t)dev->si_drv2; - int error, i; + int i; + /* + * The sx lock is here solely to serialize open()'s to close + * the race of concurrent open()'s when pps(4) doesn't own the + * ppbus. + */ + sx_xlock(&sc->lock); + ppb_lock(ppbus); if (!sc->busy) { device_t ppsdev = sc->ppsdev; - device_t ppbus = sc->ppbus; - if (ppb_request_bus(ppbus, ppsdev, PPB_WAIT|PPB_INTR)) + if (ppb_request_bus(ppbus, ppsdev, PPB_WAIT|PPB_INTR)) { + ppb_unlock(ppbus); + sx_xunlock(&sc->lock); return (EINTR); - - /* attach the interrupt handler */ - if ((error = bus_setup_intr(ppsdev, sc->intr_resource, - (INTR_TYPE_TTY | INTR_MPSAFE), ppsintr, NULL, - sc, &sc->intr_cookie))) { - ppb_release_bus(ppbus, ppsdev); - return (error); } i = ppb_set_mode(sc->ppbus, PPB_PS2); @@ -218,10 +235,13 @@ ppb_wctr(ppbus, i); } if (subdev > 0 && !(sc->busy & ~1)) { - sc->timeout = timeout(ppshcpoll, sc, 1); + /* XXX: Timeout of 1? hz/100 instead perhaps? */ + callout_reset(&sc->timeout, 1, ppshcpoll, sc); sc->lastdata = ppb_rdtr(sc->ppbus); } sc->busy |= (1 << subdev); + ppb_unlock(ppbus); + sx_xunlock(&sc->lock); return(0); } @@ -231,10 +251,12 @@ struct pps_data *sc = dev->si_drv1; int subdev = (intptr_t)dev->si_drv2; + sx_xlock(&sc->lock); sc->pps[subdev].ppsparam.mode = 0; /* PHK ??? */ + ppb_lock(sc->ppbus); sc->busy &= ~(1 << subdev); if (subdev > 0 && !(sc->busy & ~1)) - untimeout(ppshcpoll, sc, sc->timeout); + callout_stop(&sc->timeout); if (!sc->busy) { device_t ppsdev = sc->ppsdev; device_t ppbus = sc->ppbus; @@ -242,10 +264,11 @@ ppb_wdtr(ppbus, 0); ppb_wctr(ppbus, 0); - /* Note: the interrupt handler is automatically detached */ ppb_set_mode(ppbus, PPB_COMPATIBLE); ppb_release_bus(ppbus, ppsdev); } + ppb_unlock(sc->ppbus); + sx_xunlock(&sc->lock); return(0); } @@ -255,12 +278,9 @@ struct pps_data *sc = arg; int i, j, k, l; - if (!(sc->busy & ~1)) - return; - mtx_lock_spin(&sc->mtx); - sc->timeout = timeout(ppshcpoll, sc, 1); + KASSERT(sc->busy & ~1, ("pps polling w/o opened devices")); i = ppb_rdtr(sc->ppbus); - if (i == sc->lastdata) + if (i == sc->lastdata) return; l = sc->lastdata ^ i; k = 1; @@ -273,25 +293,24 @@ k += k; } sc->lastdata = i; - mtx_unlock_spin(&sc->mtx); + callout_reset(&sc->timeout, 1, ppshcpoll, sc); } -static int +static void ppsintr(void *arg) { struct pps_data *sc = (struct pps_data *)arg; + ppb_assert_locked(sc->ppbus); pps_capture(&sc->pps[0]); if (!(ppb_rstr(sc->ppbus) & nACK)) - return (FILTER_STRAY); - if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) + return; + + if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) ppb_wctr(sc->ppbus, IRQENABLE | AUTOFEED); - mtx_lock_spin(&sc->mtx); pps_event(&sc->pps[0], PPS_CAPTUREASSERT); - mtx_unlock_spin(&sc->mtx); - if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) + if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) ppb_wctr(sc->ppbus, IRQENABLE); - return (FILTER_HANDLED); } static int @@ -301,9 +320,9 @@ int subdev = (intptr_t)dev->si_drv2; int err; - mtx_lock_spin(&sc->mtx); + ppb_lock(sc->ppbus); err = pps_ioctl(cmd, data, &sc->pps[subdev]); - mtx_unlock_spin(&sc->mtx); + ppb_unlock(sc->ppbus); return (err); } Index: dev/ppbus/vpo.c =================================================================== --- dev/ppbus/vpo.c (revision 187564) +++ dev/ppbus/vpo.c (working copy) @@ -63,8 +63,7 @@ }; struct vpo_data { - unsigned short vpo_unit; - + device_t vpo_dev; int vpo_stat; int vpo_count; int vpo_error; @@ -94,7 +93,7 @@ device_t dev; - dev = device_find_child(parent, "vpo", 0); + dev = device_find_child(parent, "vpo", -1); if (!dev) BUS_ADD_CHILD(parent, 0, "vpo", -1); } @@ -105,19 +104,16 @@ static int vpo_probe(device_t dev) { + device_t ppbus = device_get_parent(dev); struct vpo_data *vpo; int error; vpo = DEVTOSOFTC(dev); + vpo->vpo_dev = dev; - /* vpo dependent initialisation */ - vpo->vpo_unit = device_get_unit(dev); - - /* low level probe */ - vpoio_set_unit(&vpo->vpo_io, vpo->vpo_unit); - /* check ZIP before ZIP+ or imm_probe() will send controls to * the printer or whatelse connected to the port */ + ppb_lock(ppbus); if ((error = vpoio_probe(dev, &vpo->vpo_io)) == 0) { vpo->vpo_isplus = 0; device_set_desc(dev, @@ -127,8 +123,10 @@ device_set_desc(dev, "Iomega Matchmaker Parallel to SCSI interface"); } else { + ppb_unlock(ppbus); return (error); } + ppb_unlock(ppbus); return (0); } @@ -140,6 +138,8 @@ vpo_attach(device_t dev) { struct vpo_data *vpo = DEVTOSOFTC(dev); + device_t ppbus = device_get_parent(dev); + struct ppb_data *ppb = device_get_softc(ppbus); /* XXX: layering */ struct cam_devq *devq; int error; @@ -162,17 +162,20 @@ return (ENXIO); vpo->sim = cam_sim_alloc(vpo_action, vpo_poll, "vpo", vpo, - device_get_unit(dev), &Giant, + device_get_unit(dev), ppb->ppc_lock, /*untagged*/1, /*tagged*/0, devq); if (vpo->sim == NULL) { cam_simq_free(devq); return (ENXIO); } + ppb_lock(ppbus); if (xpt_bus_register(vpo->sim, dev, /*bus*/0) != CAM_SUCCESS) { cam_sim_free(vpo->sim, /*free_devq*/TRUE); + ppb_unlock(ppbus); return (ENXIO); } + ppb_unlock(ppbus); /* all went ok */ @@ -184,29 +187,30 @@ static void vpo_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb) { - free(ccb, M_TEMP); + + free(ccb, M_TEMP); } static void vpo_cam_rescan(struct vpo_data *vpo) { - struct cam_path *path; - union ccb *ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO); + struct cam_path *path; + union ccb *ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO); - if (xpt_create_path(&path, xpt_periph, cam_sim_path(vpo->sim), 0, 0) - != CAM_REQ_CMP) { + if (xpt_create_path(&path, xpt_periph, cam_sim_path(vpo->sim), 0, 0) + != CAM_REQ_CMP) { /* A failure is benign as the user can do a manual rescan */ free(ccb, M_TEMP); - return; + return; } - xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/); - ccb->ccb_h.func_code = XPT_SCAN_BUS; - ccb->ccb_h.cbfcnp = vpo_cam_rescan_callback; - ccb->crcn.flags = CAM_FLAG_NONE; - xpt_action(ccb); + xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/); + ccb->ccb_h.func_code = XPT_SCAN_BUS; + ccb->ccb_h.cbfcnp = vpo_cam_rescan_callback; + ccb->crcn.flags = CAM_FLAG_NONE; + xpt_action(ccb); - /* The scan is in progress now. */ + /* The scan is in progress now. */ } /* @@ -216,13 +220,10 @@ vpo_intr(struct vpo_data *vpo, struct ccb_scsiio *csio) { int errno; /* error in errno.h */ - int s; #ifdef VP0_DEBUG int i; #endif - s = splcam(); - if (vpo->vpo_isplus) { errno = imm_do_scsi(&vpo->vpo_io, VP0_INITIATOR, csio->ccb_h.target_id, @@ -238,7 +239,7 @@ } #ifdef VP0_DEBUG - printf("vpo_do_scsi = %d, status = 0x%x, count = %d, vpo_error = %d\n", + printf("vpo_do_scsi = %d, status = 0x%x, count = %d, vpo_error = %d\n", errno, vpo->vpo_stat, vpo->vpo_count, vpo->vpo_error); /* dump of command */ @@ -251,17 +252,17 @@ if (errno) { /* connection to ppbus interrupted */ csio->ccb_h.status = CAM_CMD_TIMEOUT; - goto error; + return; } /* if a timeout occured, no sense */ if (vpo->vpo_error) { if (vpo->vpo_error != VP0_ESELECT_TIMEOUT) - printf("vpo%d: VP0 error/timeout (%d)\n", - vpo->vpo_unit, vpo->vpo_error); + device_printf(vpo->vpo_dev, "VP0 error/timeout (%d)\n", + vpo->vpo_error); csio->ccb_h.status = CAM_CMD_TIMEOUT; - goto error; + return; } /* check scsi status */ @@ -292,10 +293,10 @@ &vpo->vpo_sense.stat, &vpo->vpo_sense.count, &vpo->vpo_error); } - + #ifdef VP0_DEBUG - printf("(sense) vpo_do_scsi = %d, status = 0x%x, count = %d, vpo_error = %d\n", + printf("(sense) vpo_do_scsi = %d, status = 0x%x, count = %d, vpo_error = %d\n", errno, vpo->vpo_sense.stat, vpo->vpo_sense.count, vpo->vpo_error); #endif @@ -319,27 +320,25 @@ } } else { /* no sense */ - csio->ccb_h.status = CAM_SCSI_STATUS_ERROR; + csio->ccb_h.status = CAM_SCSI_STATUS_ERROR; } - goto error; + return; } csio->resid = csio->dxfer_len - vpo->vpo_count; csio->ccb_h.status = CAM_REQ_CMP; - -error: - splx(s); - - return; } static void vpo_action(struct cam_sim *sim, union ccb *ccb) { - struct vpo_data *vpo = (struct vpo_data *)sim->softc; +#ifdef INVARIANTS + device_t ppbus = device_get_parent(vpo->vpo_dev); + ppb_assert_locked(ppbus); +#endif switch (ccb->ccb_h.func_code) { case XPT_SCSI_IO: { @@ -348,10 +347,10 @@ csio = &ccb->csio; #ifdef VP0_DEBUG - printf("vpo%d: XPT_SCSI_IO (0x%x) request\n", - vpo->vpo_unit, csio->cdb_io.cdb_bytes[0]); + device_printf(vpo->vpo_dev, "XPT_SCSI_IO (0x%x) request\n", + csio->cdb_io.cdb_bytes[0]); #endif - + vpo_intr(vpo, csio); xpt_done(ccb); @@ -365,8 +364,7 @@ ccg = &ccb->ccg; #ifdef VP0_DEBUG - printf("vpo%d: XPT_CALC_GEOMETRY (bs=%d,vs=%jd,c=%d,h=%d,spt=%d) request\n", - vpo->vpo_unit, + device_printf(vpo->vpo_dev, "XPT_CALC_GEOMETRY (bs=%d,vs=%jd,c=%d,h=%d,spt=%d) request\n", ccg->block_size, (intmax_t)ccg->volume_size, ccg->cylinders, @@ -387,7 +385,7 @@ { #ifdef VP0_DEBUG - printf("vpo%d: XPT_RESET_BUS request\n", vpo->vpo_unit); + device_printf(vpo->vpo_dev, "XPT_RESET_BUS request\n"); #endif if (vpo->vpo_isplus) { @@ -411,9 +409,9 @@ case XPT_PATH_INQ: /* Path routing inquiry */ { struct ccb_pathinq *cpi = &ccb->cpi; - + #ifdef VP0_DEBUG - printf("vpo%d: XPT_PATH_INQ request\n", vpo->vpo_unit); + device_printf(vpo->vpo_dev, "XPT_PATH_INQ request\n"); #endif cpi->version_num = 1; /* XXX??? */ cpi->hba_inquiry = 0; @@ -445,9 +443,9 @@ static void vpo_poll(struct cam_sim *sim) -{ - /* The ZIP is actually always polled throw vpo_action() */ - return; +{ + + /* The ZIP is actually always polled throw vpo_action(). */ } static devclass_t vpo_devclass; Index: dev/ppbus/lpt.h =================================================================== --- dev/ppbus/lpt.h (revision 187564) +++ dev/ppbus/lpt.h (working copy) @@ -31,7 +31,7 @@ * * Distantly from : * @(#)lptreg.h 1.1 (Berkeley) 12/19/90 - * Id: lptreg.h,v 1.6 1997/02/22 09:36:52 peter Exp + * Id: lptreg.h,v 1.6 1997/02/22 09:36:52 peter Exp * From Id: nlpt.h,v 1.3 1999/01/10 12:04:54 nsouch Exp * * $FreeBSD$ @@ -45,7 +45,7 @@ */ #ifndef __LPT_H -#define __LPT_H +#define __LPT_H /* machine independent definitions, it shall only depend on the ppbus * parallel port model */ Index: dev/ppbus/immio.c =================================================================== --- dev/ppbus/immio.c (revision 187564) +++ dev/ppbus/immio.c (working copy) @@ -250,10 +250,10 @@ MS_CASS(0x4), /* loop: */ - MS_RASSERT_P(1, MS_REG_DTR), + MS_RASSERT_P(1, MS_REG_DTR), MS_CASS(0x5), MS_DBRA(0), /* decrement counter */ - MS_RASSERT_P(1, MS_REG_DTR), + MS_RASSERT_P(1, MS_REG_DTR), MS_CASS(0x0), MS_DBRA(-6 /* loop */), @@ -265,14 +265,14 @@ /* EPP 1.7 microsequences, ptr and len set at runtime */ static struct ppb_microseq epp17_outstr[] = { MS_CASS(0x4), - MS_RASSERT_P(MS_ACCUM, MS_REG_EPP_D), + MS_RASSERT_P(MS_ACCUM, MS_REG_EPP_D), MS_CASS(0xc), MS_RET(0), }; static struct ppb_microseq epp17_instr[] = { MS_CASS(PCD | 0x4), - MS_RFETCH_P(MS_ACCUM, MS_REG_EPP_D, MS_FETCH_ALL), + MS_RFETCH_P(MS_ACCUM, MS_REG_EPP_D, MS_FETCH_ALL), MS_CASS(PCD | 0xc), MS_RET(0), }; @@ -298,8 +298,9 @@ if ((s1 != (char)0xb8 || s2 != (char)0x18 || s3 != (char)0x38)) { if (bootverbose) - printf("imm%d: (disconnect) s1=0x%x s2=0x%x, s3=0x%x\n", - vpo->vpo_unit, s1 & 0xff, s2 & 0xff, s3 & 0xff); + device_printf(vpo->vpo_dev, + "(disconnect) s1=0x%x s2=0x%x, s3=0x%x\n", + s1 & 0xff, s2 & 0xff, s3 & 0xff); if (connected) *connected = VP0_ECONNECT; } @@ -351,8 +352,9 @@ if ((s1 != (char)0xb8 || s2 != (char)0x18 || s3 != (char)0x30)) { if (bootverbose) - printf("imm%d: (connect) s1=0x%x s2=0x%x, s3=0x%x\n", - vpo->vpo_unit, s1 & 0xff, s2 & 0xff, s3 & 0xff); + device_printf(vpo->vpo_dev, + "(connect) s1=0x%x s2=0x%x, s3=0x%x\n", + s1 & 0xff, s2 & 0xff, s3 & 0xff); if (disconnected) *disconnected = VP0_ECONNECT; } @@ -397,7 +399,8 @@ goto error; vpo->vpo_mode_found = VP0_MODE_NIBBLE; } else { - printf("imm%d: NIBBLE mode unavailable!\n", vpo->vpo_unit); + device_printf(vpo->vpo_dev, + "NIBBLE mode unavailable!\n"); goto error; } } else { @@ -413,13 +416,13 @@ /* release the bus now */ imm_disconnect(vpo, &error, 1); - /* ensure we are disconnected or daisy chained peripheral + /* ensure we are disconnected or daisy chained peripheral * may cause serious problem to the disk */ if (error) { if (bootverbose) - printf("imm%d: can't disconnect from the drive\n", - vpo->vpo_unit); + device_printf(vpo->vpo_dev, + "can't disconnect from the drive\n"); goto error; } @@ -476,7 +479,7 @@ /* initialize the select microsequence */ ppb_MS_init_msq(select_microseq, 1, SELECT_TARGET, 1 << initiator | 1 << target); - + ppb_MS_microseq(ppbus, vpo->vpo_dev, select_microseq, &ret); return (ret); @@ -511,7 +514,7 @@ ppb_MS_microseq(ppbus, vpo->vpo_dev, wait_microseq, &err); if (err) - return (0); /* command timed out */ + return (0); /* command timed out */ return(ret); } @@ -537,7 +540,7 @@ if (ret) return (VP0_ENEGOCIATE); #endif - + ppb_MS_init_msq(negociate_microseq, 1, NEGOCIATED_MODE, negociate_mode); @@ -577,7 +580,7 @@ int imm_attach(struct vpoio_data *vpo) { - DECLARE_NIBBLE_INBYTE_SUBMICROSEQ; + DECLARE_NIBBLE_INBYTE_SUBMICROSEQ; device_t ppbus = device_get_parent(vpo->vpo_dev); int error = 0; @@ -598,11 +601,12 @@ 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); + 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; @@ -611,17 +615,17 @@ case VP0_MODE_EPP: ppb_MS_GET_init(ppbus, vpo->vpo_dev, epp17_instr); ppb_MS_PUT_init(ppbus, vpo->vpo_dev, epp17_outstr); - printf("imm%d: EPP mode\n", vpo->vpo_unit); + 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); - printf("imm%d: PS2 mode\n", vpo->vpo_unit); + 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); - printf("imm%d: NIBBLE mode\n", vpo->vpo_unit); + device_printf(vpo->vpo_dev, "NIBBLE mode\n"); break; default: panic("imm: unknown mode %d", vpo->vpo_mode_found); @@ -629,6 +633,7 @@ ppb_release_bus(ppbus, vpo->vpo_dev); error: + ppb_unlock(ppbus); return (error); } @@ -663,7 +668,7 @@ * Send an SCSI command * */ -int +int imm_do_scsi(struct vpoio_data *vpo, int host, int target, char *command, int clen, char *buffer, int blen, int *result, int *count, int *ret) @@ -687,7 +692,8 @@ return (error); if (not_connected) { - *ret = VP0_ECONNECT; goto error; + *ret = VP0_ECONNECT; + goto error; } /* @@ -711,7 +717,8 @@ } if (!(r = imm_wait(vpo, VP0_LOW_SPINTMO))) { - *ret = VP0_ESTATUS_TIMEOUT; goto error; + *ret = VP0_ESTATUS_TIMEOUT; + goto error; } if ((r & 0x30) == 0x10) { @@ -722,14 +729,15 @@ negociated = 1; } - /* - * Complete transfer ... + /* + * Complete transfer ... */ *count = 0; for (;;) { if (!(r = imm_wait(vpo, VP0_LOW_SPINTMO))) { - *ret = VP0_ESTATUS_TIMEOUT; goto error; + *ret = VP0_ESTATUS_TIMEOUT; + goto error; } /* stop when the ZIP+ wants to send status */ @@ -779,13 +787,15 @@ negociated = 1; if (imm_instr(vpo, &l, 1)) { - *ret = VP0_EOTHER; goto error; + *ret = VP0_EOTHER; + goto error; } /* check if the ZIP+ wants to send more status */ if (imm_wait(vpo, VP0_FAST_SPINTMO) == (char)0xb8) if (imm_instr(vpo, &h, 1)) { - *ret = VP0_EOTHER+2; goto error; + *ret = VP0_EOTHER + 2; + goto error; } /* Experience showed that we should discard this */ Index: dev/ppbus/ppb_base.c =================================================================== --- dev/ppbus/ppb_base.c (revision 187564) +++ dev/ppbus/ppb_base.c (working copy) @@ -28,21 +28,23 @@ __FBSDID("$FreeBSD$"); #include -#include +#include #include #include +#include +#include #include #include - + #include "ppbus_if.h" #include - + MODULE_VERSION(ppbus, 1); #define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev)) - + /* * ppb_poll_bus() * @@ -54,9 +56,12 @@ ppb_poll_bus(device_t bus, int max, char mask, char status, int how) { + struct ppb_data *ppb = DEVTOSOFTC(bus); int i, j, error; char r; + mtx_assert(ppb->ppc_lock, MA_OWNED); + /* try at least up to 10ms */ for (j = 0; j < ((how & PPB_POLL) ? max : 1); j++) { for (i = 0; i < 10000; i++) { @@ -72,21 +77,11 @@ if ((ppb_rstr(bus) & mask) == status) return (0); - switch (how) { - case PPB_NOINTR: - /* wait 10 ms */ - tsleep((caddr_t)bus, PPBPRI, "ppbpoll", hz/100); - break; - - case PPB_INTR: - default: - /* wait 10 ms */ - if (((error = tsleep((caddr_t)bus, PPBPRI | PCATCH, - "ppbpoll", hz/100)) != EWOULDBLOCK) != 0) { - return (error); - } - break; - } + /* wait 10 ms */ + error = mtx_sleep((caddr_t)bus, ppb->ppc_lock, PPBPRI | + (how == PPB_NOINTR ? 0 : PCATCH), "ppbpoll", hz/100); + if (error != EWOULDBLOCK) + return (error); } } @@ -101,8 +96,12 @@ int ppb_get_epp_protocol(device_t bus) { +#ifdef INVARIANTS + struct ppb_data *ppb = DEVTOSOFTC(bus); +#endif uintptr_t protocol; + mtx_assert(ppb->ppc_lock, MA_OWNED); BUS_READ_IVAR(device_get_parent(bus), bus, PPC_IVAR_EPP_PROTO, &protocol); return (protocol); @@ -118,6 +117,7 @@ struct ppb_data *ppb = DEVTOSOFTC(bus); /* XXX yet device mode = ppbus mode = chipset mode */ + mtx_assert(ppb->ppc_lock, MA_OWNED); return (ppb->mode); } @@ -132,8 +132,9 @@ struct ppb_data *ppb = DEVTOSOFTC(bus); int old_mode = ppb_get_mode(bus); + mtx_assert(ppb->ppc_lock, MA_OWNED); if (PPBUS_SETMODE(device_get_parent(bus), mode)) - return -1; + return (-1); /* XXX yet device mode = ppbus mode = chipset mode */ ppb->mode = (mode & PPB_MASK); @@ -149,6 +150,11 @@ int ppb_write(device_t bus, char *buf, int len, int how) { +#ifdef INVARIANTS + struct ppb_data *ppb = DEVTOSOFTC(bus); +#endif + + mtx_assert(ppb->ppc_lock, MA_OWNED); return (PPBUS_WRITE(device_get_parent(bus), buf, len, how)); } @@ -160,6 +166,11 @@ int ppb_reset_epp_timeout(device_t bus) { +#ifdef INVARIANTS + struct ppb_data *ppb = DEVTOSOFTC(bus); +#endif + + mtx_assert(ppb->ppc_lock, MA_OWNED); return(PPBUS_RESET_EPP(device_get_parent(bus))); } @@ -171,6 +182,11 @@ int ppb_ecp_sync(device_t bus) { +#ifdef INVARIANTS + struct ppb_data *ppb = DEVTOSOFTC(bus); +#endif + + mtx_assert(ppb->ppc_lock, MA_OWNED); return (PPBUS_ECP_SYNC(device_get_parent(bus))); } @@ -182,8 +198,13 @@ int ppb_get_status(device_t bus, struct ppb_status *status) { +#ifdef INVARIANTS + struct ppb_data *ppb = DEVTOSOFTC(bus); +#endif register char r; + mtx_assert(ppb->ppc_lock, MA_OWNED); + r = status->status = ppb_rstr(bus); status->timeout = r & TIMEOUT; @@ -195,3 +216,45 @@ return (0); } + +void +ppb_lock(device_t bus) +{ + struct ppb_data *ppb = DEVTOSOFTC(bus); + + mtx_lock(ppb->ppc_lock); +} + +void +ppb_unlock(device_t bus) +{ + struct ppb_data *ppb = DEVTOSOFTC(bus); + + mtx_unlock(ppb->ppc_lock); +} + +void +_ppb_assert_locked(device_t bus, const char *file, int line) +{ +#ifdef INVARIANTS + struct ppb_data *ppb = DEVTOSOFTC(bus); + + _mtx_assert(ppb->ppc_lock, MA_OWNED, file, line); +#endif +} + +void +ppb_init_callout(device_t bus, struct callout *c, int flags) +{ + struct ppb_data *ppb = DEVTOSOFTC(bus); + + callout_init_mtx(c, ppb->ppc_lock, flags); +} + +int +ppb_sleep(device_t bus, void *wchan, int priority, const char *wmesg, int timo) +{ + struct ppb_data *ppb = DEVTOSOFTC(bus); + + return (mtx_sleep(wchan, ppb->ppc_lock, priority, wmesg, timo)); +} Index: dev/ppbus/lpbb.c =================================================================== --- dev/ppbus/lpbb.c (revision 187564) +++ dev/ppbus/lpbb.c (working copy) @@ -36,10 +36,12 @@ */ #include +#include +#include #include +#include +#include #include -#include -#include #include @@ -60,7 +62,7 @@ device_t dev; - dev = device_find_child(parent, "lpbb", 0); + dev = device_find_child(parent, "lpbb", -1); if (!dev) BUS_ADD_CHILD(parent, 0, "lpbb", -1); } @@ -82,7 +84,7 @@ lpbb_attach(device_t dev) { device_t bitbang; - + /* add generic bit-banging code */ bitbang = device_add_child(dev, "iicbb", -1); device_probe_and_attach(bitbang); @@ -101,12 +103,16 @@ 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: @@ -123,57 +129,90 @@ #define ALIM 0x20 #define I2CKEY 0x50 -static int lpbb_getscl(device_t dev) +/* Reset bus by setting SDA first and then SCL. */ +static void +lpbb_reset_bus(device_t dev) { - return ((ppb_rstr(device_get_parent(dev)) & SCL_in) == SCL_in); + device_t ppbus = device_get_parent(dev); + + ppb_assert_locked(ppbus); + ppb_wdtr(ppbus, (u_char)~SDA_out); + ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) | SCL_out)); } -static int lpbb_getsda(device_t dev) +static int +lpbb_getscl(device_t dev) { - return ((ppb_rstr(device_get_parent(dev)) & SDA_in) == SDA_in); + device_t ppbus = device_get_parent(dev); + int rval; + + ppb_lock(ppbus); + rval = ((ppb_rstr(ppbus) & SCL_in) == SCL_in); + ppb_unlock(ppbus); + return (rval); } -static void lpbb_setsda(device_t dev, char val) +static int +lpbb_getsda(device_t dev) { device_t ppbus = device_get_parent(dev); + int rval; - if(val==0) + ppb_lock(ppbus); + rval = ((ppb_rstr(ppbus) & SDA_in) == SDA_in); + ppb_unlock(ppbus); + return (rval); +} + +static void +lpbb_setsda(device_t dev, char val) +{ + device_t ppbus = device_get_parent(dev); + + ppb_lock(ppbus); + if (val == 0) ppb_wdtr(ppbus, (u_char)SDA_out); - else + else ppb_wdtr(ppbus, (u_char)~SDA_out); + ppb_unlock(ppbus); } -static void lpbb_setscl(device_t dev, unsigned char val) +static void +lpbb_setscl(device_t dev, unsigned char val) { device_t ppbus = device_get_parent(dev); - if(val==0) - ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus)&~SCL_out)); - else - ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus)|SCL_out)); + ppb_lock(ppbus); + if (val == 0) + ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) & ~SCL_out)); + else + ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) | SCL_out)); + ppb_unlock(ppbus); } -static int lpbb_detect(device_t dev) +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); } - /* reset bus */ - lpbb_setsda(dev, 1); - lpbb_setscl(dev, 1); + 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); } @@ -183,16 +222,17 @@ { 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); } - /* reset bus */ - lpbb_setsda(dev, 1); - lpbb_setscl(dev, 1); + lpbb_reset_bus(dev); ppb_release_bus(ppbus, dev); + ppb_unlock(ppbus); return (IIC_ENOADDR); } @@ -226,6 +266,7 @@ }; DRIVER_MODULE(lpbb, ppbus, lpbb_driver, lpbb_devclass, 0, 0); +DRIVER_MODULE(iicbb, lpbb, iicbb_driver, iicbb_devclass, 0, 0); MODULE_DEPEND(lpbb, ppbus, 1, 1, 1); MODULE_DEPEND(lpbb, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); MODULE_VERSION(lpbb, 1); Index: dev/ppbus/if_plip.c =================================================================== --- dev/ppbus/if_plip.c (revision 187564) +++ dev/ppbus/if_plip.c (working copy) @@ -78,7 +78,7 @@ /* * Update for ppbus, PLIP support only - Nicolas Souchu - */ + */ #include "opt_plip.h" @@ -110,7 +110,7 @@ #include #ifndef LPMTU /* MTU for the lp# interfaces */ -#define LPMTU 1500 +#define LPMTU 1500 #endif #ifndef LPMAXSPIN1 /* DELAY factor for the lp# interfaces */ @@ -125,19 +125,19 @@ #define LPMAXERRS 100 #endif -#define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */ +#define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */ #define CLPIP_SHAKE 0x80 /* This bit toggles between nibble reception */ -#define MLPIPHDRLEN CLPIPHDRLEN +#define MLPIPHDRLEN CLPIPHDRLEN -#define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */ +#define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */ #define LPIP_SHAKE 0x40 /* This bit toggles between nibble reception */ #if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN -#define MLPIPHDRLEN LPIPHDRLEN +#define MLPIPHDRLEN LPIPHDRLEN #endif #define LPIPTBLSIZE 256 /* Size of octet translation table */ -#define lprintf if (lptflag) printf +#define lprintf if (lptflag) printf #ifdef PLIP_DEBUG static int volatile lptflag = 1; @@ -147,39 +147,68 @@ struct lp_data { struct ifnet *sc_ifp; + device_t sc_dev; u_char *sc_ifbuf; int sc_iferrs; struct resource *res_irq; + void *sc_intr_cookie; }; +static struct mtx lp_tables_lock; +MTX_SYSINIT(lp_tables, &lp_tables_lock, "plip tables", MTX_DEF); + /* Tables for the lp# interface */ static u_char *txmith; -#define txmitl (txmith+(1*LPIPTBLSIZE)) -#define trecvh (txmith+(2*LPIPTBLSIZE)) -#define trecvl (txmith+(3*LPIPTBLSIZE)) +#define txmitl (txmith + (1 * LPIPTBLSIZE)) +#define trecvh (txmith + (2 * LPIPTBLSIZE)) +#define trecvl (txmith + (3 * LPIPTBLSIZE)) static u_char *ctxmith; -#define ctxmitl (ctxmith+(1*LPIPTBLSIZE)) -#define ctrecvh (ctxmith+(2*LPIPTBLSIZE)) -#define ctrecvl (ctxmith+(3*LPIPTBLSIZE)) +#define ctxmitl (ctxmith + (1 * LPIPTBLSIZE)) +#define ctrecvh (ctxmith + (2 * LPIPTBLSIZE)) +#define ctrecvl (ctxmith + (3 * LPIPTBLSIZE)) /* Functions for the lp# interface */ static int lpinittables(void); static int lpioctl(struct ifnet *, u_long, caddr_t); static int lpoutput(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); +static void lpstop(struct lp_data *); static void lp_intr(void *); +static int lp_module_handler(module_t, int, void *); -#define DEVTOSOFTC(dev) \ +#define DEVTOSOFTC(dev) \ ((struct lp_data *)device_get_softc(dev)) -#define UNITOSOFTC(unit) \ - ((struct lp_data *)devclass_get_softc(lp_devclass, (unit))) -#define UNITODEVICE(unit) \ - (devclass_get_device(lp_devclass, (unit))) static devclass_t lp_devclass; +static int +lp_module_handler(module_t mod, int what, void *arg) +{ + + switch (what) { + case MOD_UNLOAD: + mtx_lock(&lp_tables_lock); + if (txmith != NULL) { + free(txmith, M_DEVBUF); + txmith = NULL; + } + if (ctxmith != NULL) { + free(ctxmith, M_DEVBUF); + ctxmith = NULL; + } + mtx_unlock(&lp_tables_lock); + break; + case MOD_LOAD: + case MOD_QUIESCE: + break; + default: + return (EOPNOTSUPP); + } + return (0); +} + static void lp_identify(driver_t *driver, device_t parent) { @@ -189,51 +218,36 @@ if (!dev) BUS_ADD_CHILD(parent, 0, "plip", -1); } -/* - * lpprobe() - */ + static int lp_probe(device_t dev) { - device_t ppbus = device_get_parent(dev); - struct lp_data *lp; - int zero = 0; - uintptr_t irq; - lp = DEVTOSOFTC(dev); - - /* retrieve the ppbus irq */ - BUS_READ_IVAR(ppbus, dev, PPBUS_IVAR_IRQ, &irq); - - /* if we haven't interrupts, the probe fails */ - if (irq == -1) { - device_printf(dev, "not an interrupt driven port, failed.\n"); - return (ENXIO); - } - - /* reserve the interrupt resource, expecting irq is available to continue */ - lp->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &zero, irq, irq, 1, - RF_SHAREABLE); - if (lp->res_irq == 0) { - device_printf(dev, "cannot reserve interrupt, failed.\n"); - return (ENXIO); - } - - /* - * lp dependent initialisation. - */ - device_set_desc(dev, "PLIP network interface"); return (0); } static int -lp_attach (device_t dev) +lp_attach(device_t dev) { struct lp_data *lp = DEVTOSOFTC(dev); struct ifnet *ifp; + int error, rid = 0; + lp->sc_dev = dev; + + /* + * Reserve the interrupt resource. If we don't have one, the + * attach fails. + */ + lp->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_SHAREABLE); + if (lp->res_irq == 0) { + device_printf(dev, "cannot reserve interrupt, failed.\n"); + return (ENXIO); + } + ifp = lp->sc_ifp = if_alloc(IFT_PARA); if (ifp == NULL) { return (ENOSPC); @@ -242,8 +256,7 @@ ifp->if_softc = lp; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_mtu = LPMTU; - ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST | - IFF_NEEDSGIANT; + ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST; ifp->if_ioctl = lpioctl; ifp->if_output = lpoutput; ifp->if_hdrlen = 0; @@ -253,198 +266,250 @@ bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); + /* + * Attach our interrupt handler. It is only called while we + * own the ppbus. + */ + error = bus_setup_intr(dev, lp->res_irq, INTR_TYPE_NET | INTR_MPSAFE, + NULL, lp_intr, lp, &lp->sc_intr_cookie); + if (error) { + bpfdetach(ifp); + if_detach(ifp); + bus_release_resource(dev, SYS_RES_IRQ, 0, lp->res_irq); + device_printf(dev, "Unable to register interrupt handler\n"); + return (error); + } + return (0); } + +static int +lp_detach(device_t dev) +{ + struct lp_data *sc = device_get_softc(dev); + device_t ppbus = device_get_parent(dev); + + ppb_lock(ppbus); + lpstop(sc); + ppb_unlock(ppbus); + bpfdetach(sc->sc_ifp); + if_detach(sc->sc_ifp); + bus_teardown_intr(dev, sc->res_irq, sc->sc_intr_cookie); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->res_irq); + return (0); +} + /* * Build the translation tables for the LPIP (BSD unix) protocol. * We don't want to calculate these nasties in our tight loop, so we * precalculate them when we initialize. */ static int -lpinittables (void) +lpinittables(void) { - int i; + int i; - if (!txmith) - txmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); + mtx_lock(&lp_tables_lock); + if (txmith == NULL) + txmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); - if (!txmith) - return 1; + if (txmith == NULL) { + mtx_unlock(&lp_tables_lock); + return (1); + } - if (!ctxmith) - ctxmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); + if (ctxmith == NULL) + ctxmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); - if (!ctxmith) - return 1; + if (ctxmith == NULL) { + mtx_unlock(&lp_tables_lock); + return (1); + } - for (i=0; i < LPIPTBLSIZE; i++) { - ctxmith[i] = (i & 0xF0) >> 4; - ctxmitl[i] = 0x10 | (i & 0x0F); - ctrecvh[i] = (i & 0x78) << 1; - ctrecvl[i] = (i & 0x78) >> 3; - } + for (i = 0; i < LPIPTBLSIZE; i++) { + ctxmith[i] = (i & 0xF0) >> 4; + ctxmitl[i] = 0x10 | (i & 0x0F); + ctrecvh[i] = (i & 0x78) << 1; + ctrecvl[i] = (i & 0x78) >> 3; + } - for (i=0; i < LPIPTBLSIZE; i++) { - txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08; - txmitl[i] = ((i & 0x08) << 1) | (i & 0x07); - trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1); - trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3); - } + for (i = 0; i < LPIPTBLSIZE; i++) { + txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08; + txmitl[i] = ((i & 0x08) << 1) | (i & 0x07); + trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1); + trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3); + } + mtx_unlock(&lp_tables_lock); - return 0; + return (0); } -/* - * Process an ioctl request. - */ +static void +lpstop(struct lp_data *sc) +{ + device_t ppbus = device_get_parent(sc->sc_dev); + ppb_assert_locked(ppbus); + ppb_wctr(ppbus, 0x00); + sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + free(sc->sc_ifbuf, M_DEVBUF); + sc->sc_ifbuf = NULL; + + /* IFF_UP is not set, try to release the bus anyway */ + ppb_release_bus(ppbus, sc->sc_dev); +} + static int -lpioctl (struct ifnet *ifp, u_long cmd, caddr_t data) +lpinit_locked(struct ifnet *ifp) { - device_t dev = UNITODEVICE(ifp->if_dunit); - device_t ppbus = device_get_parent(dev); - struct lp_data *sc = DEVTOSOFTC(dev); - struct ifaddr *ifa = (struct ifaddr *)data; - struct ifreq *ifr = (struct ifreq *)data; - u_char *ptr; - void *ih; - int error; + struct lp_data *sc = ifp->if_softc; + device_t dev = sc->sc_dev; + device_t ppbus = device_get_parent(dev); + int error; - switch (cmd) { + ppb_assert_locked(ppbus); + error = ppb_request_bus(ppbus, dev, PPB_DONTWAIT); + if (error) + return (error); - case SIOCSIFDSTADDR: - case SIOCAIFADDR: - case SIOCSIFADDR: - if (ifa->ifa_addr->sa_family != AF_INET) - return EAFNOSUPPORT; + /* Now IFF_UP means that we own the bus */ + ppb_set_mode(ppbus, PPB_COMPATIBLE); - ifp->if_flags |= IFF_UP; - /* FALLTHROUGH */ - case SIOCSIFFLAGS: - if ((!(ifp->if_flags & IFF_UP)) && - (ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (lpinittables()) { + ppb_release_bus(ppbus, dev); + return (ENOBUFS); + } - ppb_wctr(ppbus, 0x00); - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - - /* IFF_UP is not set, try to release the bus anyway */ - ppb_release_bus(ppbus, dev); - break; + sc->sc_ifbuf = malloc(sc->sc_ifp->if_mtu + MLPIPHDRLEN, + M_DEVBUF, M_NOWAIT); + if (sc->sc_ifbuf == NULL) { + ppb_release_bus(ppbus, dev); + return (ENOBUFS); } - if (((ifp->if_flags & IFF_UP)) && - (!(ifp->if_drv_flags & IFF_DRV_RUNNING))) { - /* XXX - * Should the request be interruptible? - */ - if ((error = ppb_request_bus(ppbus, dev, PPB_WAIT|PPB_INTR))) - return (error); + ppb_wctr(ppbus, IRQENABLE); - /* Now IFF_UP means that we own the bus */ + ifp->if_drv_flags |= IFF_DRV_RUNNING; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + return (0); +} - ppb_set_mode(ppbus, PPB_COMPATIBLE); +/* + * Process an ioctl request. + */ +static int +lpioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + struct lp_data *sc = ifp->if_softc; + device_t dev = sc->sc_dev; + device_t ppbus = device_get_parent(dev); + struct ifaddr *ifa = (struct ifaddr *)data; + struct ifreq *ifr = (struct ifreq *)data; + u_char *ptr; + int error; - if (lpinittables()) { - ppb_release_bus(ppbus, dev); - return ENOBUFS; - } + switch (cmd) { + case SIOCSIFDSTADDR: + case SIOCAIFADDR: + case SIOCSIFADDR: + if (ifa->ifa_addr->sa_family != AF_INET) + return (EAFNOSUPPORT); - sc->sc_ifbuf = malloc(sc->sc_ifp->if_mtu + MLPIPHDRLEN, - M_DEVBUF, M_WAITOK); - if (!sc->sc_ifbuf) { - ppb_release_bus(ppbus, dev); - return ENOBUFS; - } - - /* attach our interrupt handler, later detached when the bus is released */ - if ((error = bus_setup_intr(dev, sc->res_irq, - INTR_TYPE_NET, NULL, lp_intr, dev, &ih))) { - ppb_release_bus(ppbus, dev); + ifp->if_flags |= IFF_UP; + /* FALLTHROUGH */ + case SIOCSIFFLAGS: + error = 0; + ppb_lock(ppbus); + if ((!(ifp->if_flags & IFF_UP)) && + (ifp->if_drv_flags & IFF_DRV_RUNNING)) + lpstop(sc); + else if (((ifp->if_flags & IFF_UP)) && + (!(ifp->if_drv_flags & IFF_DRV_RUNNING))) + error = lpinit_locked(ifp); + ppb_unlock(ppbus); return (error); - } - ppb_wctr(ppbus, IRQENABLE); - ifp->if_drv_flags |= IFF_DRV_RUNNING; - } - break; + case SIOCSIFMTU: + ppb_lock(ppbus); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + ptr = malloc(ifr->ifr_mtu + MLPIPHDRLEN, M_DEVBUF, + M_NOWAIT); + if (ptr == NULL) { + ppb_unlock(ppbus); + return (ENOBUFS); + } + if (sc->sc_ifbuf) + free(sc->sc_ifbuf, M_DEVBUF); + sc->sc_ifbuf = ptr; + } + sc->sc_ifp->if_mtu = ifr->ifr_mtu; + ppb_unlock(ppbus); + break; - case SIOCSIFMTU: - ptr = sc->sc_ifbuf; - sc->sc_ifbuf = malloc(ifr->ifr_mtu+MLPIPHDRLEN, M_DEVBUF, M_NOWAIT); - if (!sc->sc_ifbuf) { - sc->sc_ifbuf = ptr; - return ENOBUFS; - } - if (ptr) - free(ptr,M_DEVBUF); - sc->sc_ifp->if_mtu = ifr->ifr_mtu; - break; + case SIOCGIFMTU: + ifr->ifr_mtu = sc->sc_ifp->if_mtu; + break; - case SIOCGIFMTU: - ifr->ifr_mtu = sc->sc_ifp->if_mtu; - break; + case SIOCADDMULTI: + case SIOCDELMULTI: + if (ifr == 0) { + return (EAFNOSUPPORT); /* XXX */ + } + switch (ifr->ifr_addr.sa_family) { + case AF_INET: + break; + default: + return (EAFNOSUPPORT); + } + break; - case SIOCADDMULTI: - case SIOCDELMULTI: - if (ifr == 0) { - return EAFNOSUPPORT; /* XXX */ - } - switch (ifr->ifr_addr.sa_family) { + case SIOCGIFMEDIA: + /* + * No ifmedia support at this stage; maybe use it + * in future for eg. protocol selection. + */ + return (EINVAL); - case AF_INET: - break; - default: - return EAFNOSUPPORT; + lprintf("LP:ioctl(0x%lx)\n", cmd); + return (EINVAL); } - break; - - case SIOCGIFMEDIA: - /* - * No ifmedia support at this stage; maybe use it - * in future for eg. protocol selection. - */ - return EINVAL; - - default: - lprintf("LP:ioctl(0x%lx)\n", cmd); - return EINVAL; - } - return 0; + return (0); } static __inline int -clpoutbyte (u_char byte, int spin, device_t ppbus) +clpoutbyte(u_char byte, int spin, device_t ppbus) { + ppb_wdtr(ppbus, ctxmitl[byte]); while (ppb_rstr(ppbus) & CLPIP_SHAKE) if (--spin == 0) { - return 1; + return (1); } ppb_wdtr(ppbus, ctxmith[byte]); while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) if (--spin == 0) { - return 1; + return (1); } - return 0; + return (0); } static __inline int -clpinbyte (int spin, device_t ppbus) +clpinbyte(int spin, device_t ppbus) { u_char c, cl; - while((ppb_rstr(ppbus) & CLPIP_SHAKE)) - if(!--spin) { - return -1; - } + while ((ppb_rstr(ppbus) & CLPIP_SHAKE)) + if (!--spin) { + return (-1); + } cl = ppb_rstr(ppbus); ppb_wdtr(ppbus, 0x10); - while(!(ppb_rstr(ppbus) & CLPIP_SHAKE)) - if(!--spin) { - return -1; - } + while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) + if (!--spin) { + return (-1); + } c = ppb_rstr(ppbus); ppb_wdtr(ppbus, 0x00); @@ -455,118 +520,130 @@ lptap(struct ifnet *ifp, struct mbuf *m) { u_int32_t af = AF_INET; + bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); } static void -lp_intr (void *arg) +lp_intr(void *arg) { - device_t dev = (device_t)arg; - device_t ppbus = device_get_parent(dev); - struct lp_data *sc = DEVTOSOFTC(dev); - int len, s, j; + struct lp_data *sc = arg; + device_t ppbus = device_get_parent(sc->sc_dev); + int len, j; u_char *bp; u_char c, cl; struct mbuf *top; - s = splhigh(); - + ppb_assert_locked(ppbus); if (sc->sc_ifp->if_flags & IFF_LINK0) { - /* Ack. the request */ - ppb_wdtr(ppbus, 0x01); + /* Ack. the request */ + ppb_wdtr(ppbus, 0x01); - /* Get the packet length */ - j = clpinbyte(LPMAXSPIN2, ppbus); - if (j == -1) - goto err; - len = j; - j = clpinbyte(LPMAXSPIN2, ppbus); - if (j == -1) - goto err; - len = len + (j << 8); - if (len > sc->sc_ifp->if_mtu + MLPIPHDRLEN) - goto err; + /* Get the packet length */ + j = clpinbyte(LPMAXSPIN2, ppbus); + if (j == -1) + goto err; + len = j; + j = clpinbyte(LPMAXSPIN2, ppbus); + if (j == -1) + goto err; + len = len + (j << 8); + if (len > sc->sc_ifp->if_mtu + MLPIPHDRLEN) + goto err; - bp = sc->sc_ifbuf; - - while (len--) { - j = clpinbyte(LPMAXSPIN2, ppbus); - if (j == -1) { - goto err; - } - *bp++ = j; - } - /* Get and ignore checksum */ - j = clpinbyte(LPMAXSPIN2, ppbus); - if (j == -1) { - goto err; - } + bp = sc->sc_ifbuf; - len = bp - sc->sc_ifbuf; - if (len <= CLPIPHDRLEN) - goto err; + while (len--) { + j = clpinbyte(LPMAXSPIN2, ppbus); + if (j == -1) { + goto err; + } + *bp++ = j; + } - sc->sc_iferrs = 0; + /* Get and ignore checksum */ + j = clpinbyte(LPMAXSPIN2, ppbus); + if (j == -1) { + goto err; + } - len -= CLPIPHDRLEN; - sc->sc_ifp->if_ipackets++; - sc->sc_ifp->if_ibytes += len; - top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, sc->sc_ifp, 0); - if (top) { - if (bpf_peers_present(sc->sc_ifp->if_bpf)) - lptap(sc->sc_ifp, top); - netisr_queue(NETISR_IP, top); /* mbuf is free'd on failure. */ - } - goto done; + len = bp - sc->sc_ifbuf; + if (len <= CLPIPHDRLEN) + goto err; + + sc->sc_iferrs = 0; + + len -= CLPIPHDRLEN; + sc->sc_ifp->if_ipackets++; + sc->sc_ifp->if_ibytes += len; + top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, sc->sc_ifp, + 0); + if (top) { + ppb_unlock(ppbus); + if (bpf_peers_present(sc->sc_ifp->if_bpf)) + lptap(sc->sc_ifp, top); + + /* mbuf is free'd on failure. */ + netisr_queue(NETISR_IP, top); + ppb_lock(ppbus); + } + return; } while ((ppb_rstr(ppbus) & LPIP_SHAKE)) { - len = sc->sc_ifp->if_mtu + LPIPHDRLEN; - bp = sc->sc_ifbuf; - while (len--) { + len = sc->sc_ifp->if_mtu + LPIPHDRLEN; + bp = sc->sc_ifbuf; + while (len--) { - cl = ppb_rstr(ppbus); - ppb_wdtr(ppbus, 8); + cl = ppb_rstr(ppbus); + ppb_wdtr(ppbus, 8); - j = LPMAXSPIN2; - while((ppb_rstr(ppbus) & LPIP_SHAKE)) - if(!--j) goto err; + j = LPMAXSPIN2; + while ((ppb_rstr(ppbus) & LPIP_SHAKE)) + if (!--j) + goto err; - c = ppb_rstr(ppbus); - ppb_wdtr(ppbus, 0); + c = ppb_rstr(ppbus); + ppb_wdtr(ppbus, 0); - *bp++= trecvh[cl] | trecvl[c]; + *bp++= trecvh[cl] | trecvl[c]; - j = LPMAXSPIN2; - while (!((cl=ppb_rstr(ppbus)) & LPIP_SHAKE)) { - if (cl != c && - (((cl = ppb_rstr(ppbus)) ^ 0xb8) & 0xf8) == - (c & 0xf8)) - goto end; - if (!--j) goto err; + j = LPMAXSPIN2; + while (!((cl = ppb_rstr(ppbus)) & LPIP_SHAKE)) { + if (cl != c && + (((cl = ppb_rstr(ppbus)) ^ 0xb8) & 0xf8) == + (c & 0xf8)) + goto end; + if (!--j) + goto err; + } } - } end: - len = bp - sc->sc_ifbuf; - if (len <= LPIPHDRLEN) - goto err; + len = bp - sc->sc_ifbuf; + if (len <= LPIPHDRLEN) + goto err; - sc->sc_iferrs = 0; + sc->sc_iferrs = 0; - len -= LPIPHDRLEN; - sc->sc_ifp->if_ipackets++; - sc->sc_ifp->if_ibytes += len; - top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, sc->sc_ifp, 0); - if (top) { - if (bpf_peers_present(sc->sc_ifp->if_bpf)) - lptap(sc->sc_ifp, top); - netisr_queue(NETISR_IP, top); /* mbuf is free'd on failure. */ - } + len -= LPIPHDRLEN; + sc->sc_ifp->if_ipackets++; + sc->sc_ifp->if_ibytes += len; + top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, sc->sc_ifp, + 0); + if (top) { + ppb_unlock(ppbus); + if (bpf_peers_present(sc->sc_ifp->if_bpf)) + lptap(sc->sc_ifp, top); + + /* mbuf is free'd on failure. */ + netisr_queue(NETISR_IP, top); + ppb_lock(ppbus); + } } - goto done; + return; - err: +err: ppb_wdtr(ppbus, 0); lprintf("R"); sc->sc_ifp->if_ierrors++; @@ -577,181 +654,179 @@ * so stop wasting our time */ if (sc->sc_iferrs > LPMAXERRS) { - printf("lp%d: Too many errors, Going off-line.\n", device_get_unit(dev)); - ppb_wctr(ppbus, 0x00); - sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - sc->sc_iferrs=0; + if_printf(sc->sc_ifp, "Too many errors, Going off-line.\n"); + ppb_wctr(ppbus, 0x00); + sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + sc->sc_iferrs = 0; } - - done: - splx(s); - return; } static __inline int -lpoutbyte (u_char byte, int spin, device_t ppbus) +lpoutbyte(u_char byte, int spin, device_t ppbus) { - ppb_wdtr(ppbus, txmith[byte]); - while (!(ppb_rstr(ppbus) & LPIP_SHAKE)) - if (--spin == 0) - return 1; - ppb_wdtr(ppbus, txmitl[byte]); - while (ppb_rstr(ppbus) & LPIP_SHAKE) - if (--spin == 0) - return 1; - return 0; + + ppb_wdtr(ppbus, txmith[byte]); + while (!(ppb_rstr(ppbus) & LPIP_SHAKE)) + if (--spin == 0) + return (1); + ppb_wdtr(ppbus, txmitl[byte]); + while (ppb_rstr(ppbus) & LPIP_SHAKE) + if (--spin == 0) + return (1); + return (0); } static int -lpoutput (struct ifnet *ifp, struct mbuf *m, - struct sockaddr *dst, struct rtentry *rt) +lpoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, + struct rtentry *rt) { - device_t dev = UNITODEVICE(ifp->if_dunit); - device_t ppbus = device_get_parent(dev); - int s, err; - struct mbuf *mm; - u_char *cp = "\0\0"; - u_char chksum = 0; - int count = 0; - int i, len, spin; + struct lp_data *sc = ifp->if_softc; + device_t dev = sc->sc_dev; + device_t ppbus = device_get_parent(dev); + int err; + struct mbuf *mm; + u_char *cp = "\0\0"; + u_char chksum = 0; + int count = 0; + int i, len, spin; - /* We need a sensible value if we abort */ - cp++; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + /* We need a sensible value if we abort */ + cp++; + ppb_lock(ppbus); + ifp->if_drv_flags |= IFF_DRV_OACTIVE; - err = 1; /* assume we're aborting because of an error */ + err = 1; /* assume we're aborting because of an error */ - s = splhigh(); + /* Suspend (on laptops) or receive-errors might have taken us offline */ + ppb_wctr(ppbus, IRQENABLE); - /* Suspend (on laptops) or receive-errors might have taken us offline */ - ppb_wctr(ppbus, IRQENABLE); + if (ifp->if_flags & IFF_LINK0) { + if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { + lprintf("&"); + lp_intr(sc); + } - if (ifp->if_flags & IFF_LINK0) { + /* Alert other end to pending packet */ + spin = LPMAXSPIN1; + ppb_wdtr(ppbus, 0x08); + while ((ppb_rstr(ppbus) & 0x08) == 0) + if (--spin == 0) { + goto nend; + } - if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { - lprintf("&"); - lp_intr(dev); - } + /* Calculate length of packet, then send that */ - /* Alert other end to pending packet */ - spin = LPMAXSPIN1; - ppb_wdtr(ppbus, 0x08); - while ((ppb_rstr(ppbus) & 0x08) == 0) - if (--spin == 0) { + count += 14; /* Ethernet header len */ + + mm = m; + for (mm = m; mm; mm = mm->m_next) { + count += mm->m_len; + } + if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus)) goto nend; + if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus)) + goto nend; + + /* Send dummy ethernet header */ + for (i = 0; i < 12; i++) { + if (clpoutbyte(i, LPMAXSPIN1, ppbus)) + goto nend; + chksum += i; } - /* Calculate length of packet, then send that */ + if (clpoutbyte(0x08, LPMAXSPIN1, ppbus)) + goto nend; + if (clpoutbyte(0x00, LPMAXSPIN1, ppbus)) + goto nend; + chksum += 0x08 + 0x00; /* Add into checksum */ - count += 14; /* Ethernet header len */ + mm = m; + do { + cp = mtod(mm, u_char *); + len = mm->m_len; + while (len--) { + chksum += *cp; + if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus)) + goto nend; + } + } while ((mm = mm->m_next)); - mm = m; - for (mm = m; mm; mm = mm->m_next) { - count += mm->m_len; + /* Send checksum */ + if (clpoutbyte(chksum, LPMAXSPIN2, ppbus)) + goto nend; + + /* Go quiescent */ + ppb_wdtr(ppbus, 0); + + err = 0; /* No errors */ + + nend: + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + if (err) { /* if we didn't timeout... */ + ifp->if_oerrors++; + lprintf("X"); + } else { + ifp->if_opackets++; + ifp->if_obytes += m->m_pkthdr.len; + if (bpf_peers_present(ifp->if_bpf)) + lptap(ifp, m); + } + + m_freem(m); + + if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { + lprintf("^"); + lp_intr(sc); + } + ppb_unlock(ppbus); + return (0); } - if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus)) - goto nend; - if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus)) - goto nend; - /* Send dummy ethernet header */ - for (i = 0; i < 12; i++) { - if (clpoutbyte(i, LPMAXSPIN1, ppbus)) - goto nend; - chksum += i; + if (ppb_rstr(ppbus) & LPIP_SHAKE) { + lprintf("&"); + lp_intr(sc); } - if (clpoutbyte(0x08, LPMAXSPIN1, ppbus)) - goto nend; - if (clpoutbyte(0x00, LPMAXSPIN1, ppbus)) - goto nend; - chksum += 0x08 + 0x00; /* Add into checksum */ + if (lpoutbyte(0x08, LPMAXSPIN1, ppbus)) + goto end; + if (lpoutbyte(0x00, LPMAXSPIN2, ppbus)) + goto end; mm = m; do { cp = mtod(mm, u_char *); len = mm->m_len; - while (len--) { - chksum += *cp; - if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus)) - goto nend; - } + while (len--) + if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus)) + goto end; } while ((mm = mm->m_next)); - /* Send checksum */ - if (clpoutbyte(chksum, LPMAXSPIN2, ppbus)) - goto nend; + err = 0; /* no errors were encountered */ - /* Go quiescent */ - ppb_wdtr(ppbus, 0); +end: + --cp; + ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17); - err = 0; /* No errors */ - - nend: - if (err) { /* if we didn't timeout... */ + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + if (err) { /* if we didn't timeout... */ ifp->if_oerrors++; lprintf("X"); } else { ifp->if_opackets++; ifp->if_obytes += m->m_pkthdr.len; if (bpf_peers_present(ifp->if_bpf)) - lptap(ifp, m); + lptap(ifp, m); } m_freem(m); - if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { + if (ppb_rstr(ppbus) & LPIP_SHAKE) { lprintf("^"); - lp_intr(dev); + lp_intr(sc); } - (void) splx(s); - return 0; - } - if (ppb_rstr(ppbus) & LPIP_SHAKE) { - lprintf("&"); - lp_intr(dev); - } - - if (lpoutbyte(0x08, LPMAXSPIN1, ppbus)) - goto end; - if (lpoutbyte(0x00, LPMAXSPIN2, ppbus)) - goto end; - - mm = m; - do { - cp = mtod(mm,u_char *); - len = mm->m_len; - while (len--) - if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus)) - goto end; - } while ((mm = mm->m_next)); - - err = 0; /* no errors were encountered */ - - end: - --cp; - ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17); - - if (err) { /* if we didn't timeout... */ - ifp->if_oerrors++; - lprintf("X"); - } else { - ifp->if_opackets++; - ifp->if_obytes += m->m_pkthdr.len; - if (bpf_peers_present(ifp->if_bpf)) - lptap(ifp, m); - } - - m_freem(m); - - if (ppb_rstr(ppbus) & LPIP_SHAKE) { - lprintf("^"); - lp_intr(dev); - } - - (void) splx(s); - return 0; + ppb_unlock(ppbus); + return (0); } static device_method_t lp_methods[] = { @@ -759,15 +834,16 @@ DEVMETHOD(device_identify, lp_identify), DEVMETHOD(device_probe, lp_probe), DEVMETHOD(device_attach, lp_attach), + DEVMETHOD(device_detach, lp_detach), { 0, 0 } }; static driver_t lp_driver = { - "plip", - lp_methods, - sizeof(struct lp_data), + "plip", + lp_methods, + sizeof(struct lp_data), }; -DRIVER_MODULE(plip, ppbus, lp_driver, lp_devclass, 0, 0); +DRIVER_MODULE(plip, ppbus, lp_driver, lp_devclass, lp_module_handler, 0); MODULE_DEPEND(plip, ppbus, 1, 1, 1); Index: dev/ppbus/pcfclock.c =================================================================== --- dev/ppbus/pcfclock.c (revision 187564) +++ dev/ppbus/pcfclock.c (working copy) @@ -9,7 +9,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY SASCHA SCHUMANN ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -52,16 +52,10 @@ #define PCFCLOCK_NAME "pcfclock" struct pcfclock_data { - int count; + device_t dev; + struct cdev *cdev; }; -#define DEVTOSOFTC(dev) \ - ((struct pcfclock_data *)device_get_softc(dev)) -#define UNITOSOFTC(unit) \ - ((struct pcfclock_data *)devclass_get_softc(pcfclock_devclass, (unit))) -#define UNITODEVICE(unit) \ - (devclass_get_device(pcfclock_devclass, (unit))) - static devclass_t pcfclock_devclass; static d_open_t pcfclock_open; @@ -70,7 +64,6 @@ static struct cdevsw pcfclock_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = pcfclock_open, .d_close = pcfclock_close, .d_read = pcfclock_read, @@ -110,7 +103,7 @@ NR(buf, 2) <= 59) #define PCFCLOCK_BATTERY_STATUS_LOW(buf) (buf[8] & 4) - + #define PCFCLOCK_CMD_TIME 0 /* send current time */ #define PCFCLOCK_CMD_COPY 7 /* copy received signal to PC */ @@ -120,7 +113,7 @@ device_t dev; - dev = device_find_child(parent, PCFCLOCK_NAME, 0); + dev = device_find_child(parent, PCFCLOCK_NAME, -1); if (!dev) BUS_ADD_CHILD(parent, 0, PCFCLOCK_NAME, -1); } @@ -128,60 +121,59 @@ static int pcfclock_probe(device_t dev) { - struct pcfclock_data *sc; device_set_desc(dev, "PCF-1.0"); - - sc = DEVTOSOFTC(dev); - return (0); } static int pcfclock_attach(device_t dev) { + struct pcfclock_data *sc = device_get_softc(dev); int unit; - + unit = device_get_unit(dev); - make_dev(&pcfclock_cdevsw, unit, + sc->dev = dev; + sc->cdev = make_dev(&pcfclock_cdevsw, unit, UID_ROOT, GID_WHEEL, 0400, PCFCLOCK_NAME "%d", unit); + if (sc->cdev == NULL) { + device_printf(dev, "Failed to create character device\n"); + return (ENXIO); + } + sc->cdev->si_drv1 = sc; return (0); } -static int +static int pcfclock_open(struct cdev *dev, int flag, int fms, struct thread *td) { - u_int unit = minor(dev); - struct pcfclock_data *sc = UNITOSOFTC(unit); - device_t pcfclockdev = UNITODEVICE(unit); + struct pcfclock_data *sc = dev->si_drv1; + device_t pcfclockdev = sc->dev; 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); + ppb_lock(ppbus); + res = ppb_request_bus(ppbus, pcfclockdev, + (flag & O_NONBLOCK) ? PPB_DONTWAIT : PPB_WAIT); + ppb_unlock(ppbus); + return (res); } static int pcfclock_close(struct cdev *dev, int flags, int fmt, struct thread *td) { - u_int unit = minor(dev); - struct pcfclock_data *sc = UNITOSOFTC(unit); - device_t pcfclockdev = UNITODEVICE(unit); + struct pcfclock_data *sc = dev->si_drv1; + device_t pcfclockdev = sc->dev; device_t ppbus = device_get_parent(pcfclockdev); - sc->count--; - if (sc->count == 0) - ppb_release_bus(ppbus, pcfclockdev); + ppb_lock(ppbus); + ppb_release_bus(ppbus, pcfclockdev); + ppb_unlock(ppbus); return (0); } @@ -189,12 +181,12 @@ static void pcfclock_write_cmd(struct cdev *dev, unsigned char command) { - u_int unit = minor(dev); - device_t ppidev = UNITODEVICE(unit); - device_t ppbus = device_get_parent(ppidev); + struct pcfclock_data *sc = dev->si_drv1; + device_t pcfclockdev = sc->dev; + device_t ppbus = device_get_parent(pcfclockdev); unsigned char ctr = 14; char i; - + for (i = 0; i <= 7; i++) { ppb_wdtr(ppbus, i); AUTOFEED_CLOCK(i & 1 ? AFC_HI : AFC_LO); @@ -207,9 +199,9 @@ } static void -pcfclock_display_data(struct cdev *dev, char buf[18]) +pcfclock_display_data(struct cdev *dev, char buf[18]) { - u_int unit = minor(dev); + struct pcfclock_data *sc = dev->si_drv1; #ifdef PCFCLOCK_VERBOSE int year; @@ -217,44 +209,42 @@ if (year < 70) year += 100; - printf(PCFCLOCK_NAME "%d: %02d.%02d.%4d %02d:%02d:%02d, " + device_printf(sc->dev, "%02d.%02d.%4d %02d:%02d:%02d, " "battery status: %s\n", - unit, NR(buf, 10), NR(buf, 12), 1900 + year, NR(buf, 6), NR(buf, 4), NR(buf, 2), PCFCLOCK_BATTERY_STATUS_LOW(buf) ? "LOW" : "ok"); #else if (PCFCLOCK_BATTERY_STATUS_LOW(buf)) - printf(PCFCLOCK_NAME "%d: BATTERY STATUS LOW ON\n", - unit); + device_printf(sc->dev, "BATTERY STATUS LOW ON\n"); #endif } -static int +static int pcfclock_read_data(struct cdev *dev, char *buf, ssize_t bits) { - u_int unit = minor(dev); - device_t ppidev = UNITODEVICE(unit); - device_t ppbus = device_get_parent(ppidev); + struct pcfclock_data *sc = dev->si_drv1; + device_t pcfclockdev = sc->dev; + device_t ppbus = device_get_parent(pcfclockdev); int i; char waitfor; int offset; /* one byte per four bits */ bzero(buf, ((bits + 3) >> 2) + 1); - + waitfor = 100; for (i = 0; i <= bits; i++) { /* wait for clock, maximum (waitfor*100) usec */ - while(!CLOCK_OK && --waitfor > 0) + while (!CLOCK_OK && --waitfor > 0) DELAY(100); /* timed out? */ - if (!waitfor) + if (!waitfor) return (EIO); - + waitfor = 100; /* reload */ - + /* give it some time */ DELAY(500); @@ -269,12 +259,12 @@ return (0); } -static int -pcfclock_read_dev(struct cdev *dev, char *buf, int maxretries) +static int +pcfclock_read_dev(struct cdev *dev, char *buf, int maxretries) { - u_int unit = minor(dev); - device_t ppidev = UNITODEVICE(unit); - device_t ppbus = device_get_parent(ppidev); + struct pcfclock_data *sc = dev->si_drv1; + device_t pcfclockdev = sc->dev; + device_t ppbus = device_get_parent(pcfclockdev); int error = 0; ppb_set_mode(ppbus, PPB_COMPATIBLE); @@ -283,7 +273,7 @@ pcfclock_write_cmd(dev, PCFCLOCK_CMD_TIME); if (pcfclock_read_data(dev, buf, 68)) continue; - + if (!PCFCLOCK_CORRECT_SYNC(buf)) continue; @@ -295,30 +285,34 @@ if (!maxretries) error = EIO; - + return (error); } static int pcfclock_read(struct cdev *dev, struct uio *uio, int ioflag) { - u_int unit = minor(dev); + struct pcfclock_data *sc = dev->si_drv1; + device_t ppbus; char buf[18]; int error = 0; if (uio->uio_resid < 18) return (ERANGE); + ppbus = device_get_parent(sc->dev); + ppb_lock(ppbus); error = pcfclock_read_dev(dev, buf, PCFCLOCK_MAX_RETRIES); - + ppb_unlock(ppbus); + if (error) { - printf(PCFCLOCK_NAME "%d: no PCF found\n", unit); + device_printf(sc->dev, "no PCF found\n"); } else { pcfclock_display_data(dev, buf); - + uiomove(buf, 18, uio); } - + return (error); } Index: dev/ppbus/ppbconf.c =================================================================== --- dev/ppbus/ppbconf.c (revision 187564) +++ dev/ppbus/ppbconf.c (working copy) @@ -33,7 +33,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -44,31 +46,34 @@ #include #include "ppbus_if.h" - + #define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev)) - + static MALLOC_DEFINE(M_PPBUSDEV, "ppbusdev", "Parallel Port bus device"); +static int ppbus_intr(void *arg); + /* * Device methods */ -static void +static int ppbus_print_child(device_t bus, device_t dev) { struct ppb_device *ppbdev; + int retval; - bus_print_child_header(bus, dev); + retval = bus_print_child_header(bus, dev); ppbdev = (struct ppb_device *)device_get_ivars(dev); if (ppbdev->flags != 0) - printf(" flags 0x%x", ppbdev->flags); + retval += printf(" flags 0x%x", ppbdev->flags); - printf(" on %s%d\n", device_get_name(bus), device_get_unit(bus)); + retval += bus_print_child_footer(bus, dev); - return; + return (retval); } static int @@ -89,12 +94,12 @@ { struct ppb_device *ppbdev; device_t child; - + /* allocate ivars for the new ppbus child */ ppbdev = malloc(sizeof(struct ppb_device), M_PPBUSDEV, M_NOWAIT | M_ZERO); if (!ppbdev) - return NULL; + return (NULL); /* initialize the ivars */ ppbdev->name = name; @@ -104,50 +109,40 @@ child = device_add_child_ordered(dev, order, name, unit); device_set_ivars(child, ppbdev); - return child; + return (child); } static int ppbus_read_ivar(device_t bus, device_t dev, int index, uintptr_t* val) { - struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev); - + switch (index) { case PPBUS_IVAR_MODE: /* XXX yet device mode = ppbus mode = chipset mode */ *val = (u_long)ppb_get_mode(bus); - ppbdev->mode = (u_short)*val; break; - case PPBUS_IVAR_AVM: - *val = (u_long)ppbdev->avm; - break; - case PPBUS_IVAR_IRQ: - BUS_READ_IVAR(device_get_parent(bus), bus, PPC_IVAR_IRQ, val); - break; default: return (ENOENT); } - + return (0); } - + static int -ppbus_write_ivar(device_t bus, device_t dev, int index, u_long val) +ppbus_write_ivar(device_t bus, device_t dev, int index, uintptr_t val) { - struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev); switch (index) { case PPBUS_IVAR_MODE: /* XXX yet device mode = ppbus mode = chipset mode */ - ppb_set_mode(bus,val); - ppbdev->mode = ppb_get_mode(bus); + ppb_set_mode(bus, val); break; default: return (ENOENT); } return (0); - } +} #define PPB_PNP_PRINTER 0 #define PPB_PNP_MODEM 1 @@ -215,16 +210,15 @@ int i, len, error; int class_id = -1; char str[PPB_PnP_STRING_SIZE+1]; - int unit = device_get_unit(bus); - printf("Probing for PnP devices on ppbus%d:\n", unit); - + device_printf(bus, "Probing for PnP devices:\n"); + if ((error = ppb_1284_read_id(bus, PPB_NIBBLE, str, PPB_PnP_STRING_SIZE, &len))) goto end_detect; #ifdef DEBUG_1284 - printf("ppb: %d characters: ", len); + device_printf(bus, " %d characters: ", len); for (i = 0; i < len; i++) printf("%c(0x%x) ", str[i], str[i]); printf("\n"); @@ -236,10 +230,10 @@ if ((token = search_token(str, len, "MFG")) != NULL || (token = search_token(str, len, "MANUFACTURER")) != NULL) - printf("ppbus%d: <%s", unit, + device_printf(bus, "<%s", search_token(token, UNKNOWN_LENGTH, ":") + 1); else - printf("ppbus%d: ppc_lock); + if (error) { + device_printf(dev, "Unable to fetch parent's lock\n"); + return (error); + } - if (irq > 0) { - rid = 0; - ppb->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq, - irq, 1, RF_SHAREABLE); - if (ppb->irq_res != NULL) { - error = bus_setup_intr(dev, ppb->irq_res, - INTR_TYPE_TTY | INTR_MPSAFE, NULL, ppbus_dummy_intr, - ppb, &ppb->intr_cookie); - if (error) { - device_printf(dev, - "failed to setup interrupt handler\n"); - bus_release_resource(dev, SYS_RES_IRQ, 0, - ppb->irq_res); - return (error); - } + rid = 0; + ppb->ppc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_SHAREABLE); + if (ppb->ppc_irq_res != NULL) { + error = BUS_WRITE_IVAR(device_get_parent(dev), dev, + PPC_IVAR_INTR_HANDLER, (uintptr_t)&ppbus_intr); + if (error) { + device_printf(dev, "Unable to set interrupt handler\n"); + return (error); } } @@ -421,58 +406,76 @@ #ifndef DONTPROBE_1284 /* detect IEEE1284 compliant devices */ + mtx_lock(ppb->ppc_lock); ppb_scan_bus(dev); + mtx_unlock(ppb->ppc_lock); #endif /* !DONTPROBE_1284 */ - /* launch attachement of the added children */ + /* launch attachment of the added children */ bus_generic_attach(dev); - return 0; + return (0); } static int ppbus_detach(device_t dev) { - struct ppb_data *ppb = (struct ppb_data *)device_get_softc(dev); - device_t *children; - int nchildren, i; + device_t *children; + int error, nchildren, i; + error = bus_generic_detach(dev); + if (error) + return (error); + /* detach & delete all children */ if (!device_get_children(dev, &children, &nchildren)) { for (i = 0; i < nchildren; i++) if (children[i]) device_delete_child(dev, children[i]); free(children, M_TEMP); - } - - if (ppb->irq_res != NULL) { - bus_teardown_intr(dev, ppb->irq_res, ppb->intr_cookie); - bus_release_resource(dev, SYS_RES_IRQ, 0, ppb->irq_res); } + return (0); } static int +ppbus_intr(void *arg) +{ + struct ppb_device *ppbdev; + struct ppb_data *ppb = arg; + + mtx_assert(ppb->ppc_lock, MA_OWNED); + if (ppb->ppb_owner == NULL) + return (ENOENT); + + ppbdev = device_get_ivars(ppb->ppb_owner); + if (ppbdev->intr_hook == NULL) + return (ENOENT); + + ppbdev->intr_hook(ppbdev->intr_arg); + return (0); +} + +static int ppbus_setup_intr(device_t bus, device_t child, struct resource *r, int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep) { - int error; - struct ppb_data *ppb = DEVTOSOFTC(bus); struct ppb_device *ppbdev = device_get_ivars(child); + struct ppb_data *ppb = DEVTOSOFTC(bus); - /* a device driver must own the bus to register an interrupt */ - if (ppb->ppb_owner != child) + /* We do not support filters. */ + if (filt != NULL || ihand == NULL) return (EINVAL); - if ((error = BUS_SETUP_INTR(device_get_parent(bus), child, r, flags, - filt, ihand, arg, cookiep))) - return (error); + /* Can only attach handlers to the parent device's resource. */ + if (ppb->ppc_irq_res != r) + return (EINVAL); - /* store the resource and the cookie for eventually forcing - * handler unregistration - */ - ppbdev->intr_cookie = *cookiep; - ppbdev->intr_resource = r; + mtx_lock(ppb->ppc_lock); + ppbdev->intr_hook = ihand; + ppbdev->intr_arg = arg; + *cookiep = ppbdev; + mtx_unlock(ppb->ppc_lock); return (0); } @@ -480,19 +483,19 @@ static int ppbus_teardown_intr(device_t bus, device_t child, struct resource *r, void *ih) { + struct ppb_device *ppbdev = device_get_ivars(child); struct ppb_data *ppb = DEVTOSOFTC(bus); - struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(child); - - /* a device driver must own the bus to unregister an interrupt */ - if ((ppb->ppb_owner != child) || (ppbdev->intr_cookie != ih) || - (ppbdev->intr_resource != r)) + + mtx_lock(ppb->ppc_lock); + if (ppbdev != ih || ppb->ppc_irq_res != r) { + mtx_unlock(ppb->ppc_lock); return (EINVAL); + } - ppbdev->intr_cookie = 0; - ppbdev->intr_resource = 0; + ppbdev->intr_hook = NULL; + mtx_unlock(ppb->ppc_lock); - /* pass unregistration to the upper layer */ - return (BUS_TEARDOWN_INTR(device_get_parent(bus), child, r, ih)); + return (0); } /* @@ -505,27 +508,26 @@ int ppb_request_bus(device_t bus, device_t dev, int how) { - int s, error = 0; struct ppb_data *ppb = DEVTOSOFTC(bus); struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev); + int error = 0; + mtx_assert(ppb->ppc_lock, MA_OWNED); while (!error) { - s = splhigh(); if (ppb->ppb_owner) { - splx(s); - switch (how) { - case (PPB_WAIT | PPB_INTR): - error = tsleep(ppb, PPBPRI|PCATCH, "ppbreq", 0); + case PPB_WAIT | PPB_INTR: + error = mtx_sleep(ppb, ppb->ppc_lock, + PPBPRI | PCATCH, "ppbreq", 0); break; - case (PPB_WAIT | PPB_NOINTR): - error = tsleep(ppb, PPBPRI, "ppbreq", 0); + case PPB_WAIT | PPB_NOINTR: + error = mtx_sleep(ppb, ppb->ppc_lock, PPBPRI, + "ppbreq", 0); break; default: return (EWOULDBLOCK); - break; } } else { @@ -534,13 +536,12 @@ /* restore the context of the device * The first time, ctx.valid is certainly false * then do not change anything. This is usefull for - * drivers that do not set there operating mode + * drivers that do not set there operating mode * during attachement */ if (ppbdev->ctx.valid) ppb_set_mode(bus, ppbdev->ctx.mode); - splx(s); return (0); } } @@ -556,31 +557,21 @@ int ppb_release_bus(device_t bus, device_t dev) { - int s, error; struct ppb_data *ppb = DEVTOSOFTC(bus); struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev); - if (ppbdev->intr_resource != 0) - /* force interrupt handler unregistration when the ppbus is released */ - if ((error = BUS_TEARDOWN_INTR(bus, dev, ppbdev->intr_resource, - ppbdev->intr_cookie))) - return (error); - - s = splhigh(); - if (ppb->ppb_owner != dev) { - splx(s); + mtx_assert(ppb->ppc_lock, MA_OWNED); + if (ppb->ppb_owner != dev) return (EACCES); - } - ppb->ppb_owner = 0; - splx(s); - /* save the context of the device */ ppbdev->ctx.mode = ppb_get_mode(bus); /* ok, now the context of the device is valid */ ppbdev->ctx.valid = 1; + ppb->ppb_owner = 0; + /* wakeup waiting processes */ wakeup(ppb); @@ -590,26 +581,27 @@ static devclass_t ppbus_devclass; static device_method_t ppbus_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, ppbus_probe), - DEVMETHOD(device_attach, ppbus_attach), - DEVMETHOD(device_detach, ppbus_detach), - - /* bus interface */ + /* device interface */ + DEVMETHOD(device_probe, ppbus_probe), + DEVMETHOD(device_attach, ppbus_attach), + DEVMETHOD(device_detach, ppbus_detach), + + /* bus interface */ DEVMETHOD(bus_add_child, ppbus_add_child), DEVMETHOD(bus_print_child, ppbus_print_child), - DEVMETHOD(bus_read_ivar, ppbus_read_ivar), - DEVMETHOD(bus_write_ivar, ppbus_write_ivar), + DEVMETHOD(bus_read_ivar, ppbus_read_ivar), + DEVMETHOD(bus_write_ivar, ppbus_write_ivar), DEVMETHOD(bus_setup_intr, ppbus_setup_intr), DEVMETHOD(bus_teardown_intr, ppbus_teardown_intr), - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), - { 0, 0 } + { 0, 0 } }; static driver_t ppbus_driver = { - "ppbus", - ppbus_methods, - sizeof(struct ppb_data), + "ppbus", + ppbus_methods, + sizeof(struct ppb_data), }; DRIVER_MODULE(ppbus, ppc, ppbus_driver, ppbus_devclass, 0, 0); Index: dev/ppbus/ppi.c =================================================================== --- dev/ppbus/ppi.c (revision 187564) +++ dev/ppbus/ppi.c (working copy) @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include @@ -59,13 +61,12 @@ #define BUFSIZE 512 struct ppi_data { - - int ppi_unit; + device_t ppi_device; + struct cdev *ppi_cdev; + struct sx ppi_lock; int ppi_flags; #define HAVE_PPBUS (1<<0) -#define HAD_PPBUS (1<<1) - int ppi_count; int ppi_mode; /* IEEE1284 mode */ char ppi_buffer[BUFSIZE]; @@ -77,10 +78,6 @@ #define DEVTOSOFTC(dev) \ ((struct ppi_data *)device_get_softc(dev)) -#define UNITOSOFTC(unit) \ - ((struct ppi_data *)devclass_get_softc(ppi_devclass, (unit))) -#define UNITODEVICE(unit) \ - (devclass_get_device(ppi_devclass, (unit))) static devclass_t ppi_devclass; @@ -92,7 +89,6 @@ static struct cdevsw ppi_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = ppiopen, .d_close = ppiclose, .d_read = ppiread, @@ -119,7 +115,7 @@ ppi_disable_intr(device_t ppidev) { char r; - device_t ppbus = device_get_parent(ppidev); + device_t ppbus = device_get_parent(ppidev); r = ppb_rctr(ppbus); ppb_wctr(ppbus, r & ~IRQENABLE); @@ -162,27 +158,59 @@ static int ppi_attach(device_t dev) { + struct ppi_data *ppi = DEVTOSOFTC(dev); #ifdef PERIPH_1284 - uintptr_t irq; - int zero = 0; - struct ppi_data *ppi = DEVTOSOFTC(dev); + int rid = 0; - /* retrive the irq */ - BUS_READ_IVAR(device_get_parent(dev), dev, PPBUS_IVAR_IRQ, &irq); - /* declare our interrupt handler */ - ppi->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ, - &zero, irq, irq, 1, RF_ACTIVE); + ppi->intr_resource = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (ppi->intr_resource) { + /* register our interrupt handler */ + error = bus_setup_intr(dev, ppi->intr_resource, + INTR_TYPE_TTY | INTR_MPSAFE, NULL, ppiintr, dev, + &ppi->intr_cookie); + if (error) { + bus_release_resource(dev, SYS_RES_IRQ, rid, + ppi->intr_resource); + device_printf(dev, + "Unable to register interrupt handler\n"); + return (error); + } + } #endif /* PERIPH_1284 */ - make_dev(&ppi_cdevsw, device_get_unit(dev), /* XXX cleanup */ + sx_init(&ppi->ppi_lock, "ppi"); + ppi->ppi_cdev = make_dev(&ppi_cdevsw, device_get_unit(dev), UID_ROOT, GID_WHEEL, 0600, "ppi%d", device_get_unit(dev)); + if (ppi->ppi_cdev == NULL) { + device_printf(dev, "Failed to create character device\n"); + return (ENXIO); + } + ppi->ppi_cdev->si_drv1 = ppi; + ppi->ppi_device = dev; return (0); } +static int +ppi_detach(device_t dev) +{ + struct ppi_data *ppi = DEVTOSOFTC(dev); + + destroy_dev(ppi->ppi_cdev); #ifdef PERIPH_1284 + if (ppi->intr_resource != NULL) { + bus_teardown_intr(dev, ppi->intr_resource, ppi->intr_cookie); + bus_release_resource(dev, SYS_RES_IRQ, 0, ppi->intr_resource); + } +#endif + sx_destroy(&ppi->ppi_lock); + return (0); +} + +#ifdef PERIPH_1284 /* * Cable * ----- @@ -199,9 +227,10 @@ ppiintr(void *arg) { device_t ppidev = (device_t)arg; - device_t ppbus = device_get_parent(ppidev); + device_t ppbus = device_get_parent(ppidev); struct ppi_data *ppi = DEVTOSOFTC(ppidev); + ppb_assert_locked(ppbus); ppi_disable_intr(ppidev); switch (ppb_1284_get_state(ppbus)) { @@ -256,33 +285,25 @@ static int ppiopen(struct cdev *dev, int flags, int fmt, struct thread *td) { - u_int unit = minor(dev); - struct ppi_data *ppi = UNITOSOFTC(unit); - device_t ppidev = UNITODEVICE(unit); - device_t ppbus = device_get_parent(ppidev); + struct ppi_data *ppi = dev->si_drv1; + device_t ppidev = ppi->ppi_device; + device_t ppbus = device_get_parent(ppidev); int res; - if (!ppi) - return (ENXIO); - + sx_xlock(&ppi->ppi_lock); if (!(ppi->ppi_flags & HAVE_PPBUS)) { - if ((res = ppb_request_bus(ppbus, ppidev, - (flags & O_NONBLOCK) ? PPB_DONTWAIT : - (PPB_WAIT | PPB_INTR)))) + ppb_lock(ppbus); + res = ppb_request_bus(ppbus, ppidev, + (flags & O_NONBLOCK) ? PPB_DONTWAIT : PPB_WAIT | PPB_INTR); + ppb_unlock(ppbus); + if (res) { + sx_xunlock(&ppi->ppi_lock); return (res); + } ppi->ppi_flags |= HAVE_PPBUS; - -#ifdef PERIPH_1284 - if (ppi->intr_resource) { - /* register our interrupt handler */ - bus_setup_intr(ppidev, ppi->intr_resource, - INTR_TYPE_TTY, NULL, ppiintr, dev, - &ppi->intr_cookie); - } -#endif /* PERIPH_1284 */ } - ppi->ppi_count += 1; + sx_xunlock(&ppi->ppi_lock); return (0); } @@ -290,33 +311,32 @@ static int ppiclose(struct cdev *dev, int flags, int fmt, struct thread *td) { - u_int unit = minor(dev); - struct ppi_data *ppi = UNITOSOFTC(unit); - device_t ppidev = UNITODEVICE(unit); - device_t ppbus = device_get_parent(ppidev); + struct ppi_data *ppi = dev->si_drv1; + device_t ppidev = ppi->ppi_device; + device_t ppbus = device_get_parent(ppidev); - ppi->ppi_count --; - if (!ppi->ppi_count) { - + sx_xlock(&ppi->ppi_lock); + ppb_lock(ppbus); #ifdef PERIPH_1284 - switch (ppb_1284_get_state(ppbus)) { - case PPB_PERIPHERAL_IDLE: - ppb_peripheral_terminate(ppbus, 0); - break; - case PPB_REVERSE_IDLE: - case PPB_EPP_IDLE: - case PPB_ECP_FORWARD_IDLE: - default: - ppb_1284_terminate(ppbus); - break; - } + switch (ppb_1284_get_state(ppbus)) { + case PPB_PERIPHERAL_IDLE: + ppb_peripheral_terminate(ppbus, 0); + break; + case PPB_REVERSE_IDLE: + case PPB_EPP_IDLE: + case PPB_ECP_FORWARD_IDLE: + default: + ppb_1284_terminate(ppbus); + break; + } #endif /* PERIPH_1284 */ - /* unregistration of interrupt forced by release */ - ppb_release_bus(ppbus, ppidev); + /* unregistration of interrupt forced by release */ + ppb_release_bus(ppbus, ppidev); + ppb_unlock(ppbus); - ppi->ppi_flags &= ~HAVE_PPBUS; - } + ppi->ppi_flags &= ~HAVE_PPBUS; + sx_xunlock(&ppi->ppi_lock); return (0); } @@ -333,12 +353,15 @@ ppiread(struct cdev *dev, struct uio *uio, int ioflag) { #ifdef PERIPH_1284 - u_int unit = minor(dev); - struct ppi_data *ppi = UNITOSOFTC(unit); - device_t ppidev = UNITODEVICE(unit); - device_t ppbus = device_get_parent(ppidev); + struct ppi_data *ppi = dev->si_drv1; + device_t ppidev = ppi->ppi_device; + device_t ppbus = device_get_parent(ppidev); int len, error = 0; + char *buffer; + buffer = malloc(BUFSIZE, M_DEVBUF, M_WAITOK); + + ppb_lock(ppbus); switch (ppb_1284_get_state(ppbus)) { case PPB_PERIPHERAL_IDLE: ppb_peripheral_terminate(ppbus, 0); @@ -354,11 +377,14 @@ /* XXX Wait 2 seconds to let the remote host some * time to terminate its interrupt */ - tsleep(ppi, PPBPRI, "ppiread", 2*hz); - + ppb_sleep(ppb, ppi, PPBPRI, "ppiread", 2*hz); + if ((error = ppb_1284_negociate(ppbus, - ppi->ppi_mode = PPB_BYTE, 0))) + ppi->ppi_mode = PPB_BYTE, 0))) { + ppb_unlock(ppbus); + free(buffer, M_DEVBUF); return (error); + } } break; @@ -375,11 +401,11 @@ /* read data */ len = 0; while (uio->uio_resid) { - if ((error = ppb_1284_read(ppbus, ppi->ppi_mode, - ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid), - &len))) { + error = ppb_1284_read(ppbus, ppi->ppi_mode, + buffer, min(BUFSIZE, uio->uio_resid), &len); + ppb_unlock(ppbus); + if (error) goto error; - } if (!len) goto error; /* no more data */ @@ -387,12 +413,14 @@ #ifdef DEBUG_1284 printf("d"); #endif - if ((error = uiomove(ppi->ppi_buffer, len, uio))) + if ((error = uiomove(buffer, len, uio))) goto error; + ppb_lock(ppbus); } + ppb_unlock(ppbus); error: - + free(buffer, M_DEVBUF); #else /* PERIPH_1284 */ int error = ENODEV; #endif @@ -417,11 +445,11 @@ ppiwrite(struct cdev *dev, struct uio *uio, int ioflag) { #ifdef PERIPH_1284 - u_int unit = minor(dev); - struct ppi_data *ppi = UNITOSOFTC(unit); - device_t ppidev = UNITODEVICE(unit); - device_t ppbus = device_get_parent(ppidev); + struct ppi_data *ppi = dev->si_drv1; + device_t ppidev = ppi->ppi_device; + device_t ppbus = device_get_parent(ppidev); int len, error = 0, sent; + char *buffer; #if 0 int ret; @@ -434,18 +462,26 @@ MS_RET(0) }; + buffer = malloc(BUFSIZE, M_DEVBUF, M_WAITOK); + ppb_lock(ppbus); + /* negotiate ECP mode */ if (ppb_1284_negociate(ppbus, PPB_ECP, 0)) { printf("ppiwrite: ECP negotiation failed\n"); } while (!error && (len = min(uio->uio_resid, BUFSIZE))) { - uiomove(ppi->ppi_buffer, len, uio); + ppb_unlock(ppbus); + uiomove(buffer, len, uio); - ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len); + ppb_MS_init_msq(msq, 2, ADDRESS, buffer, LENGTH, len); + ppb_lock(ppbus); error = ppb_MS_microseq(ppbus, msq, &ret); } +#else + buffer = malloc(BUFSIZE, M_DEVBUF, M_WAITOK); + ppb_lock(ppbus); #endif /* we have to be peripheral to be able to send data, so @@ -463,7 +499,7 @@ ppi_enable_intr(ppidev); /* sleep until IEEE1284 negotiation starts */ - error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0); + error = ppb_sleep(ppb, ppi, PCATCH | PPBPRI, "ppiwrite", 0); switch (error) { case 0: @@ -482,9 +518,11 @@ /* negotiation done, write bytes to master host */ while ((len = min(uio->uio_resid, BUFSIZE)) != 0) { - uiomove(ppi->ppi_buffer, len, uio); + ppb_unlock(ppbus); + uiomove(buffer, len, uio); + ppb_lock(ppbus); if ((error = byte_peripheral_write(ppbus, - ppi->ppi_buffer, len, &sent))) + buffer, len, &sent))) goto error; #ifdef DEBUG_1284 printf("d"); @@ -492,7 +530,8 @@ } error: - + ppb_unlock(ppbus); + free(buffer, M_DEVBUF); #else /* PERIPH_1284 */ int error = ENODEV; #endif @@ -503,12 +542,13 @@ static int ppiioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) { - u_int unit = minor(dev); - device_t ppidev = UNITODEVICE(unit); - device_t ppbus = device_get_parent(ppidev); + struct ppi_data *ppi = dev->si_drv1; + device_t ppidev = ppi->ppi_device; + device_t ppbus = device_get_parent(ppidev); int error = 0; u_int8_t *val = (u_int8_t *)data; + ppb_lock(ppbus); switch (cmd) { case PPIGDATA: /* get data register */ @@ -557,7 +597,8 @@ error = ENOTTY; break; } - + ppb_unlock(ppbus); + return (error); } @@ -566,6 +607,7 @@ DEVMETHOD(device_identify, ppi_identify), DEVMETHOD(device_probe, ppi_probe), DEVMETHOD(device_attach, ppi_attach), + DEVMETHOD(device_detach, ppi_detach), { 0, 0 } }; Index: dev/ppbus/ppbconf.h =================================================================== --- dev/ppbus/ppbconf.h (revision 187564) +++ dev/ppbus/ppbconf.h (working copy) @@ -178,8 +178,6 @@ * List of IVARS available to ppb device drivers */ #define PPBUS_IVAR_MODE 0 -#define PPBUS_IVAR_AVM 1 -#define PPBUS_IVAR_IRQ 2 /* other fields are reserved to the ppbus internals */ @@ -187,9 +185,6 @@ const char *name; /* name of the device */ - u_short mode; /* current mode of the device */ - u_short avm; /* available IEEE1284 modes of - * the device */ u_int flags; /* flags */ struct ppb_context ctx; /* context of the device */ @@ -203,21 +198,20 @@ * IEEE1284 code is used */ struct ppb_xfer put_xfer[PPB_MAX_XFER]; - - struct resource *intr_resource; - void *intr_cookie; - void *drv1, *drv2; /* drivers private data */ + driver_intr_t *intr_hook; + void *intr_arg; }; /* EPP standards */ #define EPP_1_9 0x0 /* default */ #define EPP_1_7 0x1 - + /* Parallel Port Chipset IVARS */ /* elsewhere XXX */ #define PPC_IVAR_EPP_PROTO 0 -#define PPC_IVAR_IRQ 1 - +#define PPC_IVAR_LOCK 1 +#define PPC_IVAR_INTR_HANDLER 2 + /* * Maximum size of the PnP info string */ @@ -247,18 +241,27 @@ int mode; /* IEEE 1284-1994 mode * NIBBLE, PS2, EPP or ECP */ - void *ppb_owner; /* device which owns the bus */ + device_t ppb_owner; /* device which owns the bus */ - struct resource *irq_res; - void *intr_cookie; + struct mtx *ppc_lock; /* lock of parent device */ + struct resource *ppc_irq_res; }; +struct callout; + +typedef int (*ppc_intr_handler)(void *); + #ifdef _KERNEL extern int ppb_attach_device(device_t); extern int ppb_request_bus(device_t, device_t, int); extern int ppb_release_bus(device_t, device_t); /* bus related functions */ +extern void ppb_lock(device_t); +extern void ppb_unlock(device_t); +extern void _ppb_assert_locked(device_t, const char *, int); +extern void ppb_init_callout(device_t, struct callout *, int); +extern int ppb_sleep(device_t, void *, int, const char *, int); extern int ppb_get_status(device_t, struct ppb_status *); extern int ppb_poll_bus(device_t, int, char, char, int); extern int ppb_reset_epp_timeout(device_t); @@ -267,13 +270,12 @@ extern int ppb_set_mode(device_t, int); /* returns old mode */ extern int ppb_get_mode(device_t); /* returns current mode */ extern int ppb_write(device_t, char *, int, int); + +#ifdef INVARIANTS +#define ppb_assert_locked(dev) _ppb_assert_locked(dev, __FILE__, __LINE__) +#else +#define ppb_assert_locked(dev) +#endif #endif /* _KERNEL */ -/* - * These are defined as macros for speedup. -#define ppb_get_base_addr(dev) ((dev)->ppb->ppb_link->base) -#define ppb_get_epp_protocol(dev) ((dev)->ppb->ppb_link->epp_protocol) -#define ppb_get_irq(dev) ((dev)->ppb->ppb_link->id_irq) - */ - -#endif +#endif /* !__PPBCONF_H */ Index: dev/ppbus/vpoio.c =================================================================== --- dev/ppbus/vpoio.c (revision 187564) +++ dev/ppbus/vpoio.c (working copy) @@ -218,7 +218,7 @@ static struct ppb_microseq spp_outbyte_submicroseq[] = { /* loop: */ - MS_RASSERT_P(1, MS_REG_DTR), + MS_RASSERT_P(1, MS_REG_DTR), MS_CASS(H_nAUTO | H_nSELIN | H_INIT | H_STROBE), MS_CASS( H_AUTO | H_nSELIN | H_INIT | H_STROBE), MS_DELAY(VP0_PULSE), @@ -233,7 +233,7 @@ MS_CASS(H_AUTO | H_SELIN | H_INIT | H_STROBE), /* loop: */ - MS_RASSERT_P(1, MS_REG_EPP_D), + MS_RASSERT_P(1, MS_REG_EPP_D), MS_BRSET(TIMEOUT, 3 /* error */), /* EPP timeout? */ MS_DBRA(-3 /* loop */), @@ -248,7 +248,7 @@ MS_CASS(PCD | H_AUTO | H_SELIN | H_INIT | H_STROBE), /* loop: */ - MS_RFETCH_P(1, MS_REG_EPP_D, MS_FETCH_ALL), + MS_RFETCH_P(1, MS_REG_EPP_D, MS_FETCH_ALL), MS_BRSET(TIMEOUT, 3 /* error */), /* EPP timeout? */ MS_DBRA(-3 /* loop */), @@ -297,7 +297,7 @@ #ifdef VP0_DEBUG printf("%s: can't request bus!\n", __func__); #endif - return error; + return (error); } if (PPB_IN_EPP_MODE(ppbus)) @@ -314,7 +314,7 @@ * SCSI reset signal, the drive must be in disk mode */ static void -vpoio_reset (struct vpoio_data *vpo) +vpoio_reset(struct vpoio_data *vpo) { device_t ppbus = device_get_parent(vpo->vpo_dev); int ret; @@ -363,7 +363,7 @@ /* allocate the bus, then apply microsequences */ if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_DONTWAIT))) - return (error); + return (error); /* Force disconnection */ ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); @@ -399,8 +399,8 @@ if (!vpoio_in_disk_mode(vpo)) { vpo->vpo_mode_found = VP0_MODE_UNDEFINED; if (bootverbose) - printf("vpo%d: can't connect to the drive\n", - vpo->vpo_unit); + 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, @@ -416,12 +416,12 @@ ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); - /* ensure we are disconnected or daisy chained peripheral + /* ensure we are disconnected or daisy chained peripheral * may cause serious problem to the disk */ if (vpoio_in_disk_mode(vpo)) { if (bootverbose) - printf("vpo%d: can't disconnect from the drive\n", - vpo->vpo_unit); + device_printf(vpo->vpo_dev, + "can't disconnect from the drive\n"); goto error; } @@ -499,7 +499,7 @@ ppb_MS_init_msq(select_microseq, 2, SELECT_TARGET, 1 << target, SELECT_INITIATOR, 1 << initiator); - + ppb_MS_microseq(ppbus, vpo->vpo_dev, select_microseq, &ret); if (ret) @@ -545,7 +545,7 @@ ppb_MS_microseq(ppbus, vpo->vpo_dev, wait_microseq, &err); if (err) - return (0); /* command timed out */ + return (0); /* command timed out */ return(ret); } @@ -586,7 +586,7 @@ int vpoio_attach(struct vpoio_data *vpo) { - DECLARE_NIBBLE_INBYTE_SUBMICROSEQ; + DECLARE_NIBBLE_INBYTE_SUBMICROSEQ; device_t ppbus = device_get_parent(vpo->vpo_dev); int error = 0; @@ -604,11 +604,12 @@ 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); + 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; @@ -617,17 +618,17 @@ 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); - printf("vpo%d: EPP mode\n", vpo->vpo_unit); + 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); - printf("vpo%d: PS2 mode\n", vpo->vpo_unit); + 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); - printf("vpo%d: NIBBLE mode\n", vpo->vpo_unit); + device_printf(vpo->vpo_dev, "NIBBLE mode\n"); break; default: panic("vpo: unknown mode %d", vpo->vpo_mode_found); @@ -636,6 +637,7 @@ ppb_release_bus(ppbus, vpo->vpo_dev); error: + ppb_unlock(ppbus); return (error); } @@ -672,7 +674,7 @@ * Send an SCSI command * */ -int +int vpoio_do_scsi(struct vpoio_data *vpo, int host, int target, char *command, int clen, char *buffer, int blen, int *result, int *count, int *ret) @@ -695,7 +697,8 @@ return (error); if (!vpoio_in_disk_mode(vpo)) { - *ret = VP0_ECONNECT; goto error; + *ret = VP0_ECONNECT; + goto error; } if ((*ret = vpoio_select(vpo,host,target))) @@ -719,15 +722,16 @@ } } - /* - * Completion ... + /* + * Completion ... */ *count = 0; for (;;) { if (!(r = vpoio_wait(vpo, VP0_LOW_SPINTMO))) { - *ret = VP0_ESTATUS_TIMEOUT; goto error; + *ret = VP0_ESTATUS_TIMEOUT; + goto error; } /* stop when the ZIP wants to send status */ @@ -763,13 +767,15 @@ } if (vpoio_instr(vpo, &l, 1)) { - *ret = VP0_EOTHER; goto error; + *ret = VP0_EOTHER; + goto error; } /* check if the ZIP wants to send more status */ if (vpoio_wait(vpo, VP0_FAST_SPINTMO) == (char)0xf0) if (vpoio_instr(vpo, &h, 1)) { - *ret = VP0_EOTHER+2; goto error; + *ret = VP0_EOTHER + 2; + goto error; } *result = ((int) h << 8) | ((int) l & 0xff); Index: dev/ppbus/ppi.h =================================================================== --- dev/ppbus/ppi.h (revision 187564) +++ dev/ppbus/ppi.h (working copy) @@ -27,7 +27,7 @@ * */ #ifndef __PPI_H -#define __PPI_H +#define __PPI_H #ifndef _KERNEL # include Property changes on: dev/cxgb ___________________________________________________________________ Modified: svn:mergeinfo Merged /head/sys/dev/cxgb:r182013-182014,182016,183053,184130,184164,184176,184896,185003 Property changes on: dev/ath/ath_hal ___________________________________________________________________ Modified: svn:mergeinfo Merged /head/sys/dev/ath/ath_hal:r182013-182014,182016,183053,184130,184164,184176,184896,185003 Property changes on: contrib/pf ___________________________________________________________________ Modified: svn:mergeinfo Merged /head/sys/contrib/pf:r182013-182014,182016,183053,184130,184164,184176,184896,185003