From owner-freebsd-bugs Tue Aug 1 1:20:42 2000 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id 9DD1637BE3D for ; Tue, 1 Aug 2000 01:20:03 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id BAA73593; Tue, 1 Aug 2000 01:20:03 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from hanoi.cronyx.ru (hanoi.cronyx.ru [144.206.181.53]) by hub.freebsd.org (Postfix) with ESMTP id 8E36C37BB5F for ; Tue, 1 Aug 2000 01:15:06 -0700 (PDT) (envelope-from root@crox.cronyx.ru) Received: from crox.cronyx.ru by hanoi.cronyx.ru with ESMTP id MAA01755; (8.9.3/vak/2.1) Tue, 1 Aug 2000 12:19:22 +0400 (MSD) Received: (from root@localhost) by crox.cronyx.ru (8.9.3/8.9.3) id MAA02970; Tue, 1 Aug 2000 12:04:14 +0400 (MSD) (envelope-from root) Message-Id: <200008010819.MAA01755@hanoi.cronyx.ru> Date: Tue, 1 Aug 2000 12:19:22 +0400 (MSD) From: vak@cronyx.ru To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: kern/20338: [patch] sio driver, support for PCI multiport cards, part 3/4 Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 20338 >Category: kern >Synopsis: Support for PCI multiport cards for sio driver >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue Aug 01 01:20:03 PDT 2000 >Closed-Date: >Last-Modified: >Originator: Serge Vakulenko >Release: FreeBSD 4.0-RELEASE i386 >Organization: Cronyx Engineering Ltd. >Environment: FreeBSD 4.0, Cronyx-Omega-PCI serial multiport adapters. >Description: To handle non-intelligent multiport async adapters, the sio driver lacks the PCI detection and attachment routines. Some rearrangment of the sio.c is also required. The patch consists of four parts: 1) sys/isa/siovar.h (new file) 2) sys/isa/sio.c (patch) 3) sys/pci/sio_pci.c (new file) 4) sys/conf/files.i386 (patch) >How-To-Repeat: >Fix: Part 3 of 4. --- /dev/null Tue Aug 1 10:55:27 2000 +++ sio_pci.c Tue Aug 1 11:38:12 2000 @@ -0,0 +1,277 @@ +/* + * Serial driver for non-intelligent PCI multiport adapters. + * Implements the probe, attach and interrupt dispatcher, + * and uses sio.c for the most part of work. + * The PCI ports get unit numbers _after_ the ISA sio ports. + * Option COM_MULTIPORT is not necessary. + * + * Copyright (C) 2000 Cronyx Engineering Ltd. + * Author: Serge Vakulenko + * + * Supports: + * Cronyx Omega-PCI adapter, by Serge Vakulenko + * + * This software is distributed with NO WARRANTIES, not even the implied + * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Authors grant any other persons or organisations permission to use + * or modify this software as long as this message is kept with the software, + * all derivative works or modified versions. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef SMP +#include +#endif +#include +#include +#include +#include +#if __FreeBSD_version >= 400000 +#include +#include +#else +#include +#include +#include +#include +#endif +#include + +#include "sio.h" + +#define MAXCHAN 8 + +#ifndef __i386__ +#define disable_intr() +#define enable_intr() +#endif + +#ifdef SMP +#define disable_intr() COM_DISABLE_INTR() +#define enable_intr() COM_ENABLE_INTR() +#endif /* SMP */ + +typedef struct _sio_pci_t { + int nchan; + int fifo_size; + int base_reg; + int hw_rts_cts; + Port_t iobase; + Port_t iostep; + struct resource *res; + struct resource *irq; + void *intrhand; + struct com_s com [MAXCHAN]; +} sio_pci_t; + +static void sio_pci_intr __P((void *arg)); + +static int sio_pci_numunits = NSIO; + +#if __FreeBSD_version >= 400000 +/* + * FreeBSD version 4.x + */ +static int sio_pci_probe __P((device_t)); +static int sio_pci_attach __P((device_t)); + +static devclass_t siopci_devclass; + +static device_method_t sio_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, sio_pci_probe), + DEVMETHOD(device_attach, sio_pci_attach), + { 0, 0 } +}; + +static driver_t sio_pci_driver = { + "siopci", + sio_pci_methods, + sizeof(sio_pci_t) +}; +DRIVER_MODULE(sio_pci, pci, sio_pci_driver, siopci_devclass, 0, 0); + +#else +/* + * FreeBSD version 3.x + */ +static const char *sio_pci_probe __P((pcici_t, pcidi_t)); +static void sio_pci_attach __P((pcici_t, int)); + +static u_long sio_pci_count; + +static struct pci_device sio_pci_device = { + "siopci", + sio_pci_probe, + sio_pci_attach, + &sio_pci_count, + NULL +}; +DATA_SET(pcidevice_set, sio_pci_device); + +#endif /* __FreeBSD_version >= 400000 */ + +#if __FreeBSD_version >= 400000 +static int +sio_pci_probe(dev) + device_t dev; +{ + u_long device_id = pci_get_vendor(dev) | pci_get_device(dev) << 16; +#else +static const char * +sio_pci_probe(config_id, device_id) + pcici_t config_id; + pcidi_t device_id; +{ +#endif + const char *desc = 0; + + if (device_id == 0xc00110b5) + desc = "Cronyx-Omega-PCI Serial Adapter"; +#ifdef notyet + /* Add your device here. */ + else if (device_id == 0xXXXXXXXX) + desc = "XXX"; +#endif + +#if __FreeBSD_version >= 400000 + if (! desc) + return ENXIO; + device_set_desc(dev, desc); + return 0; +#else + return desc; +#endif +} + +#if __FreeBSD_version >= 400000 +static int +sio_pci_attach(dev) + device_t dev; +{ + u_long device_id = pci_get_vendor(dev) | + pci_get_device(dev) << 16; + sio_pci_t *d = device_get_softc(dev); + int rid; +#define PCI_READ_CONFIG(reg) pci_read_config(dev, reg, 4) +#else +static void +sio_pci_attach(config_id, unit) + pcici_t config_id; + int unit; +{ + u_long device_id = config_id->vendor | config_id->device << 16; + sio_pci_t *d = malloc(sizeof *d, M_DEVBUF, M_WAITOK); +#define PCI_READ_CONFIG(reg) pci_conf_read(config_id, reg) +#endif + struct com_s *com; + int s, err = 0; + + bzero((char*)d, sizeof(*d)); + s = splimp(); + + /* Default values. */ + d->nchan = 8; /* channels per adapter */ + d->iostep = 8; /* addresses per channel */ + d->base_reg = 0x18; /* pci register: base addr2 */ + + /* Device dependent values. */ + if (device_id == 0xc00110b5) { + d->fifo_size = 64; /* fifo size in bytes */ + d->hw_rts_cts = 1; /* hardware rts/cts support */ + } +#ifdef notyet + else if (device_id == 0xXXXXXXXX) { + /* Add your device here. */ + } +#endif + +#if __FreeBSD_version >= 400000 + /* Allocate i/o region. */ + rid = d->base_reg; + d->res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, + RF_ACTIVE); + if (! d->res) { + printf("sio%d: couldn't map ports/memory\n", sio_pci_numunits); + err = ENXIO; + goto fail; + } + + /* Allocate interrupt. */ + rid = 0; + d->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (! d->irq) { + printf("sio%d: couldn't map interrupt\n", sio_pci_numunits); + err = ENXIO; + goto fail; + } + + /* Register the interrupt handler. */ + err = bus_setup_intr(dev, d->irq, INTR_TYPE_TTY | INTR_TYPE_FAST, + sio_pci_intr, d, &d->intrhand); +#else + err = ! pci_map_int_right(config_id, sio_pci_intr, d, &tty_imask, + INTR_FAST); +#endif + if (err) { + printf("sio%d: couldn't set up irq\n", sio_pci_numunits); +#if __FreeBSD_version >= 400000 +fail: if (d->res) + bus_release_resource(dev, SYS_RES_IOPORT, + d->base_reg, d->res); + if (d->irq) + bus_release_resource(dev, SYS_RES_IRQ, 0, d->irq); +#endif + goto done; + } + + /* Attach sio ports. */ + d->iobase = PCI_READ_CONFIG (d->base_reg) & ~3; + for (com=d->com; comcom+d->nchan; ++com) { + com->iobase = d->iobase + (com - d->com) * d->iostep; + + /* Interrupt enable, do it _before_ sio_attach_unit. */ + outb(com->iobase + com_mcr, MCR_IENABLE); + + if (sio_attach_unit(com, sio_pci_numunits++, com->iobase, + d->fifo_size << 24, 0) != 0) + printf("sio%d: cannot attach\n", sio_pci_numunits); + + /* Must do this _after_ sio_attach_unit. */ + com->st16650a = d->hw_rts_cts; + } +done: + splx (s); +#if __FreeBSD_version >= 400000 + return err; +#endif +} + +static void +sio_pci_intr(arg) + void *arg; +{ + sio_pci_t *d = arg; + struct com_s *com; + bool_t possibly_more_intrs; + + disable_intr(); + do { + possibly_more_intrs = FALSE; + for (com=d->com; comcom+d->nchan; ++com) { + if ((inb(com->int_id_port) & IIR_IMASK) != IIR_NOPEND) { + siointr1(com); + possibly_more_intrs = TRUE; + } + } + } while (possibly_more_intrs); + enable_intr(); +} >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message