From owner-freebsd-bugs Tue May 21 4:50:49 2002 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id A929737B40C for ; Tue, 21 May 2002 04:50:02 -0700 (PDT) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id g4LBo2i37430; Tue, 21 May 2002 04:50:02 -0700 (PDT) (envelope-from gnats) Received: from argos.cerberus.ch (argos.cerberus.ch [193.5.45.1]) by hub.freebsd.org (Postfix) with ESMTP id 4A35137B40D; Tue, 21 May 2002 04:48:11 -0700 (PDT) Received: from localhost (localhost [[UNIX: localhost]]) by argos.cerberus.ch (8.11.0/8.11.0) with SMTP id g4LBT1109381; Tue, 21 May 2002 13:29:04 +0200 (MET DST) Received: from a0028.cerberus.ch (a0028.cerberus.ch [143.99.72.18]) by chmanappl08.man.ch.cerberus.ch (Build 98 8.9.3/NT-8.9.3) with ESMTP id MAA15536; Tue, 21 May 2002 12:26:32 +0100 Received: by a0028.cerberus.ch (Postfix, from userid 1001) id 4DD61A80D; Tue, 21 May 2002 13:27:57 +0200 (CEST) Message-Id: <20020521112757.4DD61A80D@a0028.cerberus.ch> Date: Tue, 21 May 2002 13:27:57 +0200 (CEST) From: Thomas Brupbacher Reply-To: Thomas Brupbacher To: FreeBSD-gnats-submit@FreeBSD.org Cc: John Hay , Nicolas Souchu X-Send-Pr-Version: 3.113 Subject: kern/38372: patch for puc(4) to support parallel ports Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >Number: 38372 >Category: kern >Synopsis: patch for puc(4) to support parallel ports >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue May 21 04:50:02 PDT 2002 >Closed-Date: >Last-Modified: >Originator: Thomas Brupbacher >Release: FreeBSD 4.6-RC i386 >Organization: Siemens Building Technologies >Environment: System: FreeBSD a0028.cerberus.ch 4.6-RC FreeBSD 4.6-RC #31: Tue May 21 12:58:40 CEST 2002 brp@a0028.cerberus.ch:/usr/src/sys/compile/a0028 i386 >Description: The puc(4) driver supports only serial ports so far, the attached patch adds support for parallel ports. The patch below is good enough to print the apsfilter test.ps on my old LaserJet via the Oxford OX12PCI840 based card. The Oxford puc cards use a second IOPORT for the ECP area. This gives rise to two questions: a) the code in puc.c should probably deal with that, maybe one could provide a "generic" puc_attach that deals with most cards (the code that is present now), and additionally add an entry in pucdata.c that contains a pointer to a card specific puc_attach. This would move us away from NetBSD though. I could see something like (not certain about the syntax...) struct puc_device_description { const char *name; uint32_t rval[4]; uint32_t rmask[4]; (int) __P(device_t)) *attach; struct { int type; int bar; int offset; u_int serialfreq; } ports[PUC_MAX_PORTS]; }; b) The code in ppc.c assumes that ECP can be accessed by just adding 0x400 to the base IOPORT. I have no idea what the best way would be to solve that (to enable the full feature set of the puc card). >How-To-Repeat: >Fix: --- /usr/src/sys/dev/puc/puc.c Mon Apr 29 18:59:48 2002 +++ /usr/home/brp/puc/200205211000/puc.c Tue May 21 12:48:26 2002 @@ -122,7 +122,11 @@ struct puc_device { struct resource_list resources; + u_int type; /* the type of the port: PUC_TYPE_NONE, _COM, + * _LPT */ u_int serialfreq; + u_int ppc_capabilities; /* flags for the LPT */ + u_int baserid;/* address of base register for LPT */ }; static int puc_pci_probe(device_t dev); @@ -151,6 +155,32 @@ static void puc_print_resource_list(struct resource_list *); #endif + +/* allocate the a second IOPORT for LPT devices that need it */ +static void +puc_alloc_ECP(device_t dev, struct puc_softc * sc, int xrid) +{ + struct resource *res; + int rid, bidx; + + rid = xrid; + bidx = PUC_PORT_BAR_INDEX(rid); + if (sc->sc_bar_mappings[bidx].res != NULL) + return; + res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0ul, ~0ul, 1, RF_ACTIVE); + if (res == NULL) { + printf("could not get resource\n"); + return; + } + sc->sc_bar_mappings[bidx].res = res; +#ifdef PUC_DEBUG + printf("port bst %x, start %x, end %x\n", + (u_int) rman_get_bustag(res), (u_int) rman_get_start(res), + (u_int) rman_get_end(res)); +#endif +} + static int puc_pci_probe(device_t dev) { @@ -236,8 +267,15 @@ sc->sc_bar_mappings[bidx].res = res; #ifdef PUC_DEBUG printf("port bst %x, start %x, end %x\n", - (u_int)rman_get_bustag(res), (u_int)rman_get_start(res), - (u_int)rman_get_end(res)); + (u_int) rman_get_bustag(res), (u_int) rman_get_start(res), + (u_int) rman_get_end(res)); +#endif +#if 0 + /* for an LPT we allocate a second region */ + if ((sc->sc_desc->ports[i].type == PUC_PORT_TYPE_LPT) + && (sc->sc_desc->ports[i].serialfreq != 0x00)) { + puc_alloc_ECP(dev, sc, 0x14); + } #endif } @@ -251,7 +289,8 @@ switch (sc->sc_desc->ports[i].type) { case PUC_PORT_TYPE_COM: - typestr = "sio"; + break; + case PUC_PORT_TYPE_LPT: break; default: continue; @@ -286,7 +326,40 @@ free(pdev, M_DEVBUF); return (ENOMEM); } + rle->res->r_start = rman_get_start(res) + + sc->sc_desc->ports[i].offset; + rle->res->r_end = rle->res->r_start + 8 - 1; + rle->res->r_bustag = rman_get_bustag(res); + bus_space_subregion(rle->res->r_bustag, + rman_get_bushandle(res), + sc->sc_desc->ports[i].offset, 8, + &rle->res->r_bushandle); + } +#if 0 + /* + * if it is an LPT and we have a second IOPORT for ECP + * allocated, then also copy it to the list + */ + if ((sc->sc_desc->ports[i].type == PUC_PORT_TYPE_LPT) + && (sc->sc_desc->ports[i].type != 0x00)) { + + /* Now fake an IOPORT resource */ + res = sc->sc_bar_mappings[bidx].res; + resource_list_add(&pdev->resources, SYS_RES_IOPORT, 1, + rman_get_start(res) + sc->sc_desc->ports[i].offset, + rman_get_end(res) + sc->sc_desc->ports[i].offset + 8 - 1, + 8); + rle = resource_list_find(&pdev->resources, SYS_RES_IOPORT, 1); + if (sc->barmuxed == 0) { + rle->res = sc->sc_bar_mappings[bidx].res; + } else { + rle->res = malloc(sizeof(struct resource), M_DEVBUF, + M_WAITOK | M_ZERO); + if (rle->res == NULL) { + free(pdev, M_DEVBUF); + return (ENOMEM); + } rle->res->r_start = rman_get_start(res) + sc->sc_desc->ports[i].offset; rle->res->r_end = rle->res->r_start + 8 - 1; @@ -296,9 +369,21 @@ sc->sc_desc->ports[i].offset, 8, &rle->res->r_bushandle); } + } +#endif + pdev->type = sc->sc_desc->ports[i].type; + switch (pdev->type) { + case PUC_PORT_TYPE_COM: + typestr = "sio"; pdev->serialfreq = sc->sc_desc->ports[i].serialfreq; - + break; + case PUC_PORT_TYPE_LPT: + typestr = "ppc"; + pdev->ppc_capabilities = sc->sc_desc->ports[i].serialfreq; + pdev->baserid = sc->sc_desc->ports[i].bar; + break; + } childunit = puc_find_free_unit(typestr); sc->sc_ports[i].dev = device_add_child(dev, typestr, childunit); if (sc->sc_ports[i].dev == NULL) { @@ -320,7 +405,7 @@ sc->sc_desc->ports[i].type, sc->sc_desc->ports[i].bar, sc->sc_desc->ports[i].offset); - print_resource_list(&pdev->resources); + puc_print_resource_list(&pdev->resources); #endif if (device_probe_and_attach(sc->sc_ports[i].dev) != 0) { if (sc->barmuxed) { @@ -343,8 +428,8 @@ * This is just an brute force interrupt handler. It just calls all the * registered handlers sequencially. * - * Later on we should maybe have a different handler for boards that can - * tell us which device generated the interrupt. + * Later on we should maybe have a different handler for boards that can tell us + * which device generated the interrupt. */ static void puc_intr(void *arg) @@ -515,7 +598,8 @@ #undef rdspio #undef wrspio -static int puc_find_free_unit(char *name) +static int +puc_find_free_unit(char *name) { devclass_t dc; int start; @@ -543,10 +627,10 @@ { struct resource_list_entry *rle; - printf("print_resource_list: rl %p\n", rl); + printf("puc_print_resource_list: rl %p\n", rl); SLIST_FOREACH(rle, rl, link) printf("type %x, rid %x\n", rle->type, rle->rid); - printf("print_resource_list: end.\n"); + printf("puc_print_resource_list: end.\n"); } #endif @@ -676,6 +760,18 @@ case PUC_IVAR_FREQ: *result = pdev->serialfreq; break; + case PUC_IVAR_TYPE: + *result = pdev->type; + break; + case PUC_IVAR_BASERID: + *result = pdev->baserid; + break; + /* + * case PUC_IVAR_EXTREG: result = pdev->extreg; break; + */ + case PUC_IVAR_PPCCAP: + *result = pdev->ppc_capabilities; + break; default: return (ENOENT); } --- /usr/src/sys/dev/puc/pucdata.c Mon Apr 29 19:00:33 2002 +++ /usr/home/brp/puc/200205211000/pucdata.c Tue May 21 10:11:16 2002 @@ -39,11 +39,15 @@ */ #include +#include +#include #include #include #include +#include #include +#include #define COM_FREQ DEFAULT_RCLK @@ -686,6 +690,15 @@ { PUC_PORT_TYPE_LPT, 0x10, 0x00, 0x00 }, }, }, + + /* Oxford Semiconductor OX12PCI840 PCI Parallel port */ + { "Qxford Semiconductor OX12PCI840 Parallel port", + { 0x1415, 0x8403, 0, 0 }, + { 0xffff, 0xffff, 0, 0 }, + { + { PUC_PORT_TYPE_LPT, 0x10, 0x00, 0x00 }, + }, + }, /* NetMos 2S1P PCI 16C650 : 2S, 1P */ { "NetMos NM9835 Dual UART and 1284 Printer port", --- /usr/src/sys/dev/puc/pucvar.h Thu Mar 7 18:48:57 2002 +++ /usr/home/brp/puc/200205211000/pucvar.h Tue May 21 10:11:27 2002 @@ -74,7 +74,7 @@ int type; int bar; int offset; - u_int serialfreq; + u_int serialfreq; /* for LPT devices: capabilities of lpt */ } ports[PUC_MAX_PORTS]; }; @@ -94,7 +94,11 @@ #define PUC_MAX_BAR 6 enum puc_device_ivars { - PUC_IVAR_FREQ + PUC_IVAR_FREQ, + PUC_IVAR_TYPE, + PUC_IVAR_BASERID, + PUC_IVAR_EXTREG, + PUC_IVAR_PPCCAP }; extern const struct puc_device_description puc_devices[]; --- /usr/src/sys/isa/ppc.c Tue Oct 2 07:21:45 2001 +++ /usr/home/brp/puc/200205211000/ppc.c Tue May 21 11:29:16 2002 @@ -2162,3 +2162,144 @@ } DRIVER_MODULE(ppc, isa, ppc_driver, ppc_devclass, 0, 0); + +#ifdef __i386__ +#include "puc.h" +#endif + +#if NPUC <= 0 +#error NPUC not defined +#endif + +#if NPUC > 0 +#include + +static int ppc_puc_probe(device_t dev); +static int ppc_puc_attach(device_t dev); + + +static device_method_t ppc_puc_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, ppc_puc_probe), + DEVMETHOD(device_attach, ppc_puc_attach), + + /* bus interface */ + DEVMETHOD(bus_read_ivar, ppc_read_ivar), + DEVMETHOD(bus_setup_intr, ppc_setup_intr), + DEVMETHOD(bus_teardown_intr, ppc_teardown_intr), + + /* ppbus interface */ + DEVMETHOD(ppbus_io, ppc_io), + DEVMETHOD(ppbus_exec_microseq, ppc_exec_microseq), + DEVMETHOD(ppbus_reset_epp, ppc_reset_epp), + DEVMETHOD(ppbus_setmode, ppc_setmode), + DEVMETHOD(ppbus_ecp_sync, ppc_ecp_sync), + DEVMETHOD(ppbus_read, ppc_read), + DEVMETHOD(ppbus_write, ppc_write), + + { 0, 0 } + }; + +static driver_t ppc_puc_driver = { + "ppc", + ppc_puc_methods, + sizeof(struct ppc_data), +}; + +static int ppc_puc_probe(device_t dev) +{ + u_int type; + + if (BUS_READ_IVAR(device_get_parent(dev), dev, PUC_IVAR_TYPE, + &type) != 0) + type = PUC_PORT_TYPE_NONE; + if (type != PUC_PORT_TYPE_LPT) + return 1; + + return (0); +} + +static int ppc_puc_attach(device_t dev) +{ + struct ppc_data *ppc; + + device_t ppbus; + + /* + * Allocate the ppc_data structure. + */ + ppc = DEVTOSOFTC(dev); + bzero(ppc, sizeof(struct ppc_data)); + + ppc->rid_irq = ppc->rid_drq = ppc->rid_ioport = 0; + ppc->res_irq = ppc->res_drq = ppc->res_ioport = 0; + + /* IO port is mandatory */ + ppc->rid_ioport = 0; + ppc->res_ioport = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &ppc->rid_ioport, 0, ~0, + 1, RF_ACTIVE); + 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); + + BUS_READ_IVAR(device_get_parent(dev), dev, PUC_IVAR_PPCCAP, + &ppc->ppc_avm); + + /* 0x20 enable interrupt */ + ppc->ppc_flags = PPB_SPP | 0x20; + + ppc->rid_irq = 0; + ppc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &ppc->rid_irq, + 0ul, ~0ul, 1, RF_SHAREABLE); + + if (ppc->res_irq) + { + ppc->ppc_irq = rman_get_start(ppc->res_irq); + } + + if (ppc->res_drq) + ppc->ppc_dmachan = rman_get_start(ppc->res_drq); + + ppc->ppc_unit = device_get_unit(dev); + ppc->ppc_model = GENERIC; + + ppc->ppc_mode = PPB_COMPATIBLE; + ppc->ppc_epp = (ppc->ppc_flags & 0x10) >> 4; + + ppc->ppc_type = PPC_TYPE_GENERIC; + + + device_printf(dev, "puc chipset (%s) in %s mode%s\n", + 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 0 +/* if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_dmachan > 0)) { */ + /* acquire the DMA channel forever */ /* XXX */ +/* isa_dma_acquire(ppc->ppc_dmachan); */ + isa_dmainit(ppc->ppc_dmachan, 1024); /* nlpt.BUFSIZE */ +/* } */ +#endif + + /* add ppbus as a child of this isa to parallel bridge */ + ppbus = device_add_child(dev, "ppbus", -1); + + /* + * Probe the ppbus and attach devices found. + */ + device_probe_and_attach(ppbus); + + return (0); +} + + +DRIVER_MODULE(ppc, puc, ppc_puc_driver, ppc_devclass, 0, 0); +#endif --- /usr/src/share/man/man4/puc.4 Thu Mar 7 18:48:38 2002 +++ /usr/home/brp/puc/200205211000/puc.4 Tue May 21 12:39:07 2002 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD: src/share/man/man4/puc.4,v 1.1.2.1 2002/03/07 17:48:38 jhay Exp $ .\" -.Dd February 7, 2002 +.Dd 21 May 2002 .Dt PUC 4 .Os .Sh NAME @@ -34,11 +34,13 @@ .Cd device pci .Cd device puc .Cd device sio +.Cd device ppc .Cd options PUC_FASTINTR .Sh DESCRIPTION This driver acts as a shim to connect pci serial ports to the .Xr sio 4 -driver. +driver and to connect pci parallel ports to the +.Xr ppc 4 driver. .Pp The list of supported devices is in .Em src/sys/dev/puc/pucdata.c. @@ -51,8 +53,15 @@ .Em silo overflow errors. It cannot be used if the interrupt is shared. +.Pp +The parallel port driver hooks into the +.Xr ppc 4 +layer and therefore allows the port to be used by all devices that +interact with the parallel bus device. .Sh SEE ALSO .Xr sio 4 +.Xr ppc 4 +.Xr ppbus 4 .Sh HISTORY This driver took the idea from the .Nx @@ -60,9 +69,4 @@ driver and still use the same structure to describe cards to ease exchanging card info. .Sh BUGS -Only serial ports are supported through the -.Xr sio 4 -driver at the moment. -Someone should write support for parallel ports using the -.Xr lpt 4 -driver. +Parallel ports are only supported in compatibility mode. >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message