si_eisa.c revision 56505
1/*
2 * Device driver for Specialix range (SI/XIO) of serial line multiplexors.
3 *
4 * Copyright (C) 2000, Peter Wemm <peter@netplex.com.au>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notices, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notices, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHORS BE LIABLE.
19 *
20 * $FreeBSD: head/sys/dev/si/si_eisa.c 56505 2000-01-24 07:24:02Z peter $
21 */
22
23#include <sys/param.h>
24#include <sys/systm.h>
25#include <sys/proc.h>
26#include <sys/kernel.h>
27#include <sys/bus.h>
28#include <machine/bus.h>
29#include <sys/rman.h>
30#include <machine/resource.h>
31
32#include <dev/si/sireg.h>
33#include <dev/si/sivar.h>
34
35#include <dev/eisa/eisaconf.h>
36
37static int
38si_eisa_probe(device_t dev)
39{
40	u_long iobase;
41	u_long maddr;
42	int irq;
43
44	if (eisa_get_id(dev) != SIEISADEVID)
45		return ENXIO;
46
47	device_set_desc(dev, "Specialix SI/XIO EISA host card");
48
49	iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + SIEISABASE;
50	eisa_add_iospace(dev, iobase, SIEISAIOSIZE, RESVADDR_NONE);
51
52	maddr = (inb(iobase+1) << 24) | (inb(iobase) << 16);
53	eisa_add_mspace(dev, maddr, SIEISA_MEMSIZE, RESVADDR_NONE);
54
55	irq  = ((inb(iobase+2) >> 4) & 0xf);
56	eisa_add_intr(dev, irq, EISA_TRIGGER_LEVEL);	/* XXX shared? */
57
58	return (0);
59}
60
61static int
62si_eisa_attach(device_t dev)
63{
64	struct si_softc *sc;
65	void *ih;
66	int error;
67
68	error = 0;
69	ih = NULL;
70	sc = device_get_softc(dev);
71
72	sc->sc_type = SIEISA;
73
74	sc->sc_port_rid = 0;
75	sc->sc_port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
76					     &sc->sc_port_rid,
77					     0, ~0, 1, RF_ACTIVE);
78	if (!sc->sc_port_res) {
79		device_printf(dev, "couldn't allocate ioports\n");
80		goto fail;
81	}
82	sc->sc_iobase = rman_get_start(sc->sc_port_res);
83
84	sc->sc_mem_rid = 0;
85	sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
86					    &sc->sc_mem_rid,
87					    0, ~0, 1, RF_ACTIVE);
88	if (!sc->sc_mem_res) {
89		device_printf(dev, "couldn't allocate iomemory");
90		goto fail;
91	}
92	sc->sc_paddr = (caddr_t)rman_get_start(sc->sc_mem_res);
93	sc->sc_maddr = rman_get_virtual(sc->sc_mem_res);
94
95	sc->sc_irq_rid = 0;
96	sc->sc_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_irq_rid,
97					    0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
98	if (!sc->sc_irq_res) {
99		device_printf(dev, "couldn't allocate interrupt");
100		goto fail;
101	}
102	sc->sc_irq = rman_get_start(sc->sc_irq_res);
103	error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY,
104			       si_intr, sc,&ih);
105	if (error) {
106		device_printf(dev, "couldn't activate interrupt");
107		goto fail;
108	}
109
110	error = siattach(dev);
111	if (error)
112		goto fail;
113	return (0);		/* success */
114
115fail:
116	if (error == 0)
117		error = ENXIO;
118	if (sc->sc_irq_res) {
119		if (ih)
120			bus_teardown_intr(dev, sc->sc_irq_res, ih);
121		bus_release_resource(dev, SYS_RES_IRQ,
122				     sc->sc_irq_rid, sc->sc_irq_res);
123		sc->sc_irq_res = 0;
124	}
125	if (sc->sc_mem_res) {
126		bus_release_resource(dev, SYS_RES_MEMORY,
127				     sc->sc_mem_rid, sc->sc_mem_res);
128		sc->sc_mem_res = 0;
129	}
130	if (sc->sc_port_res) {
131		bus_release_resource(dev, SYS_RES_IOPORT,
132				     sc->sc_port_rid, sc->sc_port_res);
133		sc->sc_port_res = 0;
134	}
135	return (error);
136}
137
138static device_method_t si_eisa_methods[] = {
139	/* Device interface */
140	DEVMETHOD(device_probe,		si_eisa_probe),
141	DEVMETHOD(device_attach,	si_eisa_attach),
142
143	{ 0, 0 }
144};
145
146static driver_t si_eisa_driver = {
147	"si",
148	si_eisa_methods,
149	sizeof(struct si_softc),
150};
151
152DRIVER_MODULE(si, eisa, si_eisa_driver, si_devclass, 0, 0);
153