Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 Aug 2000 12:19:22 +0400 (MSD)
From:      vak@cronyx.ru
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/20338: [patch] sio driver, support for PCI multiport cards, part 3/4
Message-ID:  <200008010819.MAA01755@hanoi.cronyx.ru>

next in thread | raw e-mail | index | archive | help

>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 <vak@cronyx.ru>
+ *
+ * Supports:
+ *	Cronyx Omega-PCI adapter, by Serge Vakulenko <vak@cronyx.ru>
+ *
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/timepps.h>
+#include <sys/tty.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/bus.h>
+#ifndef SMP
+#include <machine/lock.h>
+#endif
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <pci/pcivar.h>
+#if __FreeBSD_version >= 400000
+#include <isa/siovar.h>
+#include <isa/sioreg.h>
+#else
+#include <sys/malloc.h>
+#include <sys/interrupt.h>
+#include <i386/isa/siovar.h>
+#include <i386/isa/sioreg.h>
+#endif
+#include <isa/ic/ns16550.h>
+
+#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; com<d->com+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; com<d->com+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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200008010819.MAA01755>