sio_pci.c revision 90010
1258945Sroberto/*
2258945Sroberto * Copyright (c) 2001 M. Warner Losh.  All rights reserved.
3258945Sroberto *
4285612Sdelphij * Redistribution and use in source and binary forms, with or without
5258945Sroberto * modification, are permitted provided that the following conditions
6258945Sroberto * are met:
7258945Sroberto * 1. Redistributions of source code must retain the above copyright
8258945Sroberto *    notice, this list of conditions and the following disclaimer.
9258945Sroberto * 2. Redistributions in binary form must reproduce the above copyright
10258945Sroberto *    notice, this list of conditions and the following disclaimer in the
11258945Sroberto *    documentation and/or other materials provided with the distribution.
12258945Sroberto *
13258945Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14258945Sroberto * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15258945Sroberto * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16258945Sroberto * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17258945Sroberto * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18258945Sroberto * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19258945Sroberto * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20258945Sroberto * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21258945Sroberto * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22258945Sroberto * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23258945Sroberto *
24258945Sroberto * $FreeBSD: head/sys/dev/sio/sio_pci.c 90010 2002-01-31 08:24:36Z nyan $
25258945Sroberto */
26258945Sroberto
27258945Sroberto#include <sys/param.h>
28258945Sroberto#include <sys/systm.h>
29258945Sroberto#include <sys/bus.h>
30258945Sroberto#include <sys/conf.h>
31258945Sroberto#include <sys/kernel.h>
32258945Sroberto#include <sys/lock.h>
33258945Sroberto#include <sys/malloc.h>
34258945Sroberto#include <sys/mutex.h>
35258945Sroberto#include <sys/module.h>
36258945Sroberto#include <sys/tty.h>
37258945Sroberto#include <machine/bus_pio.h>
38258945Sroberto#include <machine/bus.h>
39258945Sroberto#include <sys/timepps.h>
40258945Sroberto
41258945Sroberto#include <dev/sio/siovar.h>
42258945Sroberto
43258945Sroberto#include <pci/pcivar.h>
44258945Sroberto
45258945Srobertostatic	int	sio_pci_attach __P((device_t dev));
46258945Srobertostatic	void	sio_pci_kludge_unit __P((device_t dev));
47258945Srobertostatic	int	sio_pci_probe __P((device_t dev));
48258945Sroberto
49258945Srobertostatic device_method_t sio_pci_methods[] = {
50258945Sroberto	/* Device interface */
51258945Sroberto	DEVMETHOD(device_probe,		sio_pci_probe),
52258945Sroberto	DEVMETHOD(device_attach,	sio_pci_attach),
53258945Sroberto
54258945Sroberto	{ 0, 0 }
55258945Sroberto};
56258945Sroberto
57258945Srobertostatic driver_t sio_pci_driver = {
58258945Sroberto	sio_driver_name,
59258945Sroberto	sio_pci_methods,
60258945Sroberto	0,
61258945Sroberto};
62258945Sroberto
63258945Srobertostruct pci_ids {
64258945Sroberto	u_int32_t	type;
65258945Sroberto	const char	*desc;
66258945Sroberto	int		rid;
67258945Sroberto};
68258945Sroberto
69258945Srobertostatic struct pci_ids pci_ids[] = {
70258945Sroberto	{ 0x100812b9, "3COM PCI FaxModem", 0x10 },
71258945Sroberto	{ 0x2000131f, "CyberSerial (1-port) 16550", 0x10 },
72258945Sroberto	{ 0x01101407, "Koutech IOFLEX-2S PCI Dual Port Serial", 0x10 },
73258945Sroberto	{ 0x01111407, "Koutech IOFLEX-2S PCI Dual Port Serial", 0x10 },
74258945Sroberto	{ 0x048011c1, "Lucent kermit based PCI Modem", 0x14 },
75258945Sroberto	{ 0x95211415, "Oxford Semiconductor PCI Dual Port Serial", 0x10 },
76258945Sroberto	{ 0x0000151f, "SmartLink 5634PCV SurfRider", 0x10 },
77258945Sroberto	/* { 0xXXXXXXXX, "Xircom Cardbus modem", 0x10 }, */
78258945Sroberto	{ 0x00000000, NULL, 0 }
79258945Sroberto};
80258945Sroberto
81258945Srobertostatic int
82258945Srobertosio_pci_attach(dev)
83258945Sroberto	device_t	dev;
84258945Sroberto{
85258945Sroberto	u_int32_t	type;
86258945Sroberto	struct pci_ids	*id;
87258945Sroberto
88258945Sroberto	type = pci_get_devid(dev);
89258945Sroberto	id = pci_ids;
90258945Sroberto	while (id->type && id->type != type)
91258945Sroberto		id++;
92258945Sroberto	if (id->desc == NULL)
93258945Sroberto		return (ENXIO);
94258945Sroberto	sio_pci_kludge_unit(dev);
95258945Sroberto	return (sioattach(dev, id->rid, 0UL));
96258945Sroberto}
97258945Sroberto
98258945Sroberto/*
99258945Sroberto * Don't cut and paste this to other drivers.  It is a horrible kludge
100258945Sroberto * which will fail to work and also be unnecessary in future versions.
101258945Sroberto */
102258945Srobertostatic void
103258945Srobertosio_pci_kludge_unit(dev)
104258945Sroberto	device_t dev;
105258945Sroberto{
106258945Sroberto	devclass_t	dc;
107258945Sroberto	int		err;
108258945Sroberto	int		start;
109258945Sroberto	int		unit;
110258945Sroberto
111258945Sroberto	unit = 0;
112258945Sroberto	start = 0;
113258945Sroberto	while (resource_int_value("sio", unit, "port", &start) == 0 &&
114258945Sroberto	    start > 0)
115258945Sroberto		unit++;
116258945Sroberto	if (device_get_unit(dev) < unit) {
117258945Sroberto		dc = device_get_devclass(dev);
118258945Sroberto		while (devclass_get_device(dc, unit))
119258945Sroberto			unit++;
120258945Sroberto		device_printf(dev, "moving to sio%d\n", unit);
121258945Sroberto		err = device_set_unit(dev, unit);	/* EVIL DO NOT COPY */
122258945Sroberto		if (err)
123258945Sroberto			device_printf(dev, "error moving device %d\n", err);
124258945Sroberto	}
125258945Sroberto}
126258945Sroberto
127258945Srobertostatic int
128258945Srobertosio_pci_probe(dev)
129258945Sroberto	device_t	dev;
130258945Sroberto{
131258945Sroberto	u_int32_t	type;
132258945Sroberto	struct pci_ids	*id;
133258945Sroberto
134258945Sroberto	type = pci_get_devid(dev);
135258945Sroberto	id = pci_ids;
136258945Sroberto	while (id->type && id->type != type)
137258945Sroberto		id++;
138258945Sroberto	if (id->desc == NULL)
139258945Sroberto		return (ENXIO);
140258945Sroberto	device_set_desc(dev, id->desc);
141258945Sroberto#ifdef PC98
142258945Sroberto	SET_FLAG(dev, SET_IFTYPE(COM_IF_NS16550));
143258945Sroberto#endif
144258945Sroberto	return (sioprobe(dev, id->rid, 0UL, 0));
145258945Sroberto}
146258945Sroberto
147258945SrobertoDRIVER_MODULE(sio, pci, sio_pci_driver, sio_devclass, 0, 0);
148258945SrobertoDRIVER_MODULE(sio, cardbus, sio_pci_driver, sio_devclass, 0, 0);
149258945Sroberto