bt_pci.c revision 39223
1/*
2 * Product specific probe and attach routines for:
3 *      Buslogic BT946, BT948, BT956, BT958 SCSI controllers
4 *
5 * Copyright (c) 1995, 1997, 1998 Justin T. Gibbs
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions, and the following disclaimer,
13 *    without modification, immediately at the beginning of the file.
14 * 2. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 *	$Id$
30 */
31
32#include "pci.h"
33#if NPCI > 0
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/kernel.h>
37
38#include <pci/pcireg.h>
39#include <pci/pcivar.h>
40
41#include <machine/bus_memio.h>
42#include <machine/bus_pio.h>
43#include <machine/bus.h>
44
45#include <dev/buslogic/btreg.h>
46
47#define BT_PCI_IOADDR	PCIR_MAPS
48#define BT_PCI_MEMADDR	PCIR_MAPS + 4
49
50#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER	0x1040104Bul
51#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC	0x0140104Bul
52#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT	0x8130104Bul
53
54static int btpcideterminebusspace(pcici_t config_id, bus_space_tag_t* tagp,
55				  bus_space_handle_t* bshp);
56static char* bt_pci_probe(pcici_t tag, pcidi_t type);
57static void bt_pci_attach(pcici_t config_id, int unit);
58
59static struct  pci_device bt_pci_driver = {
60	"bt",
61        bt_pci_probe,
62        bt_pci_attach,
63        &bt_unit,
64	NULL
65};
66
67DATA_SET (pcidevice_set, bt_pci_driver);
68
69static int
70btpcideterminebusspace(pcici_t config_id, bus_space_tag_t* tagp,
71		       bus_space_handle_t* bshp)
72{
73	vm_offset_t	vaddr;
74	vm_offset_t	paddr;
75	u_int16_t	io_port;
76	int		command;
77
78	vaddr = 0;
79	paddr = 0;
80	command = pci_cfgread(config_id, PCIR_COMMAND, /*bytes*/1);
81	/* XXX Memory Mapped I/O seems to cause problems */
82#if 0
83	if ((command & PCIM_CMD_MEMEN) == 0
84	 || (pci_map_mem(config_id, BT_PCI_MEMADDR, &vaddr, &paddr)) == 0)
85#endif
86		if ((command & PCIM_CMD_PORTEN) == 0
87		 || (pci_map_port(config_id, BT_PCI_IOADDR, &io_port)) == 0)
88			return (-1);
89
90	if (vaddr != 0) {
91		*tagp = I386_BUS_SPACE_MEM;
92		*bshp = vaddr;
93	} else {
94		*tagp = I386_BUS_SPACE_IO;
95		*bshp = io_port;
96	}
97
98	return (0);
99}
100
101static  char*
102bt_pci_probe (pcici_t config_id, pcidi_t type)
103{
104	switch(type) {
105		case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER:
106		case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC:
107		{
108			struct bt_softc   *bt;
109			bus_space_tag_t	   tag;
110		        bus_space_handle_t bsh;
111			pci_info_data_t pci_info;
112			int error;
113			u_int8_t new_addr;
114
115			if (btpcideterminebusspace(config_id, &tag, &bsh) != 0)
116				break;
117
118			bt = bt_alloc(BT_TEMP_UNIT, tag, bsh);
119			if (bt == NULL)
120				break;
121
122			/*
123			 * Determine if an ISA compatible I/O port has been
124			 * enabled.  If so, record the port so it will not
125			 * be probed by our ISA probe, and disable the port.
126			 */
127			error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO,
128				       /*param*/NULL, /*paramlen*/0,
129				       (u_int8_t*)&pci_info, sizeof(pci_info),
130				       DEFAULT_CMD_TIMEOUT);
131			if (error == 0
132			 && pci_info.io_port < BIO_DISABLED) {
133				bt_mark_probed_bio(pci_info.io_port);
134			}
135
136			new_addr = BIO_DISABLED;
137			bt_cmd(bt, BOP_MODIFY_IO_ADDR, /*param*/&new_addr,
138			       /*paramlen*/1, /*reply_buf*/NULL, /*reply_len*/0,
139			       DEFAULT_CMD_TIMEOUT);
140			bt_free(bt);
141			return ("Buslogic Multimaster SCSI host adapter");
142			break;
143		}
144		default:
145			break;
146	}
147
148	return (NULL);
149}
150
151static void
152bt_pci_attach(pcici_t config_id, int unit)
153{
154	struct bt_softc   *bt;
155	bus_space_tag_t	   tag;
156        bus_space_handle_t bsh;
157	int		   opri;
158
159	if (btpcideterminebusspace(config_id, &tag, &bsh) != 0)
160		return;
161
162	if ((bt = bt_alloc(unit, tag, bsh)) == NULL)
163		return;  /* XXX PCI code should take return status */
164
165	/* Allocate a dmatag for our CCB DMA maps */
166	/* XXX Should be a child of the PCI bus dma tag */
167	if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0,
168			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
169			       /*highaddr*/BUS_SPACE_MAXADDR,
170			       /*filter*/NULL, /*filterarg*/NULL,
171			       /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
172			       /*nsegments*/BUS_SPACE_UNRESTRICTED,
173			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
174			       /*flags*/0, &bt->parent_dmat) != 0) {
175		bt_free(bt);
176		return;
177	}
178
179	if ((pci_map_int(config_id, bt_intr, (void *)bt, &cam_imask)) == 0) {
180		bt_free(bt);
181		return;
182	}
183	/*
184	 * Protect ourself from spurrious interrupts during
185	 * intialization and attach.  We should really rely
186	 * on interrupts during attach, but we don't have
187	 * access to our interrupts during ISA probes, so until
188	 * that changes, we mask our interrupts during attach
189	 * too.
190	 */
191	opri = splcam();
192
193	if (bt_probe(bt) || bt_fetch_adapter_info(bt) || bt_init(bt)) {
194		bt_free(bt);
195		splx(opri);
196		return; /* XXX PCI code should take return status */
197	}
198
199	bt_attach(bt);
200
201	splx(opri);
202	return;
203}
204
205#endif /* NPCI > 0 */
206