bt_pci.c revision 119418
124750Sbde/*-
215903Swosch * Product specific probe and attach routines for:
315903Swosch *      Buslogic BT946, BT948, BT956, BT958 SCSI controllers
415903Swosch *
515903Swosch * Copyright (c) 1995, 1997, 1998 Justin T. Gibbs
615903Swosch * All rights reserved.
715903Swosch *
815903Swosch * Redistribution and use in source and binary forms, with or without
915903Swosch * modification, are permitted provided that the following conditions
1015903Swosch * are met:
1115903Swosch * 1. Redistributions of source code must retain the above copyright
1215903Swosch *    notice, this list of conditions, and the following disclaimer,
1315903Swosch *    without modification, immediately at the beginning of the file.
1415903Swosch * 2. The name of the author may not be used to endorse or promote products
1515903Swosch *    derived from this software without specific prior written permission.
1615903Swosch *
1715903Swosch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1815903Swosch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1915903Swosch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2015903Swosch * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
2115903Swosch * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2215903Swosch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2315903Swosch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2415903Swosch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2515903Swosch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2615903Swosch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2715903Swosch * SUCH DAMAGE.
2815903Swosch */
291845Swollman
3015903Swosch#include <sys/cdefs.h>
3114986Swosch__FBSDID("$FreeBSD: head/sys/dev/buslogic/bt_pci.c 119418 2003-08-24 17:55:58Z obrien $");
3214986Swosch
3314986Swosch#include <sys/param.h>
341845Swollman#include <sys/systm.h>
351845Swollman#include <sys/kernel.h>
3616663Sjkh#include <sys/lock.h>
371845Swollman#include <sys/mutex.h>
3814986Swosch#include <sys/bus.h>
3914986Swosch
4014986Swosch#include <dev/pci/pcireg.h>
4114986Swosch#include <dev/pci/pcivar.h>
4214986Swosch
4314986Swosch#include <machine/bus_memio.h>
4414986Swosch#include <machine/bus_pio.h>
4514986Swosch#include <machine/bus.h>
4614986Swosch#include <machine/resource.h>
4714986Swosch#include <sys/rman.h>
4814986Swosch
4914986Swosch#include <dev/buslogic/btreg.h>
5014986Swosch
5114986Swosch#define BT_PCI_IOADDR	PCIR_MAPS
5214986Swosch#define BT_PCI_MEMADDR	PCIR_MAPS + 4
5314986Swosch
5414986Swosch#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER	0x1040104Bul
5514986Swosch#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC	0x0140104Bul
5614986Swosch#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT	0x8130104Bul
5714986Swosch
5814986Swoschstatic int
5924750Sbdebt_pci_alloc_resources(device_t dev)
6024750Sbde{
6124750Sbde	int		command, type = 0, rid, zero;
6214986Swosch	struct resource *regs = 0;
631845Swollman	struct resource *irq = 0;
6416663Sjkh
651845Swollman	command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1);
661845Swollman#if 0
671845Swollman	/* XXX Memory Mapped I/O seems to cause problems */
681845Swollman	if (command & PCIM_CMD_MEMEN) {
691845Swollman		type = SYS_RES_MEMORY;
701845Swollman		rid = BT_PCI_MEMADDR;
711845Swollman		regs = bus_alloc_resource(dev, type, &rid,
721845Swollman					  0, ~0, 1, RF_ACTIVE);
731845Swollman	}
741845Swollman#else
751845Swollman	if (!regs && (command & PCIM_CMD_PORTEN)) {
7616663Sjkh		type = SYS_RES_IOPORT;
771845Swollman		rid = BT_PCI_IOADDR;
781845Swollman		regs = bus_alloc_resource(dev, type, &rid,
791845Swollman					  0, ~0, 1, RF_ACTIVE);
8016663Sjkh	}
811845Swollman#endif
821845Swollman	if (!regs)
831845Swollman		return (ENOMEM);
841845Swollman
8516663Sjkh	zero = 0;
8616663Sjkh	irq = bus_alloc_resource(dev, SYS_RES_IRQ, &zero,
8716663Sjkh				 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
8816663Sjkh	if (!irq) {
8916663Sjkh		bus_release_resource(dev, type, rid, regs);
9016663Sjkh		return (ENOMEM);
9116663Sjkh	}
9216663Sjkh
9316663Sjkh	bt_init_softc(dev, regs, irq, 0);
9416663Sjkh
9516663Sjkh	return (0);
9616663Sjkh}
9716663Sjkh
9816663Sjkhstatic void
9916663Sjkhbt_pci_release_resources(device_t dev)
10016663Sjkh{
10116663Sjkh	struct bt_softc *bt = device_get_softc(dev);
10216663Sjkh
103	if (bt->port)
104		/* XXX can't cope with memory registers anyway */
105		bus_release_resource(dev, SYS_RES_IOPORT,
106				     BT_PCI_IOADDR, bt->port);
107	if (bt->irq)
108		bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq);
109	bt_free_softc(dev);
110}
111
112static int
113bt_pci_probe(device_t dev)
114{
115	switch (pci_get_devid(dev)) {
116		case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER:
117		case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC:
118		{
119			struct bt_softc   *bt = device_get_softc(dev);
120			pci_info_data_t pci_info;
121			int error;
122
123			error = bt_pci_alloc_resources(dev);
124			if (error)
125				return (error);
126
127			/*
128			 * Determine if an ISA compatible I/O port has been
129			 * enabled.  If so, record the port so it will not
130			 * be probed by our ISA probe.  If the PCI I/O port
131			 * was not set to the compatibility port, disable it.
132			 */
133			error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO,
134				       /*param*/NULL, /*paramlen*/0,
135				       (u_int8_t*)&pci_info, sizeof(pci_info),
136				       DEFAULT_CMD_TIMEOUT);
137			if (error == 0
138			 && pci_info.io_port < BIO_DISABLED) {
139				bt_mark_probed_bio(pci_info.io_port);
140				if (rman_get_start(bt->port) !=
141				    bt_iop_from_bio(pci_info.io_port)) {
142					u_int8_t new_addr;
143
144					new_addr = BIO_DISABLED;
145					bt_cmd(bt, BOP_MODIFY_IO_ADDR,
146					       /*param*/&new_addr,
147					       /*paramlen*/1, /*reply_buf*/NULL,
148					       /*reply_len*/0,
149					       DEFAULT_CMD_TIMEOUT);
150				}
151			}
152			bt_pci_release_resources(dev);
153			device_set_desc(dev, "Buslogic Multi-Master SCSI Host Adapter");
154			return (0);
155		}
156		default:
157			break;
158	}
159
160	return (ENXIO);
161}
162
163static int
164bt_pci_attach(device_t dev)
165{
166	struct bt_softc   *bt = device_get_softc(dev);
167	int		   opri;
168	int		   error;
169
170	/* Initialize softc */
171	error = bt_pci_alloc_resources(dev);
172	if (error) {
173		device_printf(dev, "can't allocate resources in bt_pci_attach\n");
174		return error;
175	}
176
177	/* Allocate a dmatag for our CCB DMA maps */
178	/* XXX Should be a child of the PCI bus dma tag */
179	if (bus_dma_tag_create(	/* parent	*/ NULL,
180				/* alignemnt	*/ 1,
181				/* boundary	*/ 0,
182				/* lowaddr	*/ BUS_SPACE_MAXADDR_32BIT,
183				/* highaddr	*/ BUS_SPACE_MAXADDR,
184				/* filter	*/ NULL,
185				/* filterarg	*/ NULL,
186				/* maxsize	*/ BUS_SPACE_MAXSIZE_32BIT,
187				/* nsegments	*/ ~0,
188				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
189				/* flags	*/ 0,
190				/* lockfunc	*/ busdma_lock_mutex,
191				/* lockarg	*/ &Giant,
192				&bt->parent_dmat) != 0) {
193		bt_pci_release_resources(dev);
194		return (ENOMEM);
195	}
196
197	/*
198	 * Protect ourself from spurrious interrupts during
199	 * intialization and attach.  We should really rely
200	 * on interrupts during attach, but we don't have
201	 * access to our interrupts during ISA probes, so until
202	 * that changes, we mask our interrupts during attach
203	 * too.
204	 */
205	opri = splcam();
206
207	if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) {
208		bt_pci_release_resources(dev);
209		splx(opri);
210		return (ENXIO);
211	}
212
213	error = bt_attach(dev);
214	splx(opri);
215
216	if (error) {
217		bt_pci_release_resources(dev);
218		return (error);
219	}
220
221	return (0);
222}
223
224static device_method_t bt_pci_methods[] = {
225	/* Device interface */
226	DEVMETHOD(device_probe,		bt_pci_probe),
227	DEVMETHOD(device_attach,	bt_pci_attach),
228
229	{ 0, 0 }
230};
231
232static driver_t bt_pci_driver = {
233	"bt",
234	bt_pci_methods,
235	sizeof(struct bt_softc),
236};
237
238static devclass_t bt_devclass;
239
240DRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, 0, 0);
241