siop_pci_common.c revision 1.2
1/*	$OpenBSD: siop_pci_common.c,v 1.2 2001/02/20 00:32:30 krw Exp $ */
2/*	$NetBSD: siop_pci_common.c,v 1.6 2001/01/10 15:50:20 thorpej Exp $	*/
3
4/*
5 * Copyright (c) 2000 Manuel Bouyer.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Manuel Bouyer
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/* SYM53c8xx PCI-SCSI I/O Processors driver: PCI front-end */
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/device.h>
38#include <sys/malloc.h>
39#include <sys/buf.h>
40#include <sys/kernel.h>
41
42#include <machine/endian.h>
43
44#include <dev/pci/pcireg.h>
45#include <dev/pci/pcivar.h>
46#include <dev/pci/pcidevs.h>
47
48#include <scsi/scsi_all.h>
49#include <scsi/scsiconf.h>
50
51#include <dev/ic/siopreg.h>
52#include <dev/ic/siopvar.h>
53#include <dev/pci/siop_pci_common.h>
54
55/* List (array, really :) of chips we know how to handle */
56const struct siop_product_desc siop_products[] = {
57	{ PCI_PRODUCT_SYMBIOS_810,
58	0x00,
59	SF_PCI_RL | SF_CHIP_LS,
60	4, 8, 3, 250, 0
61	},
62	{ PCI_PRODUCT_SYMBIOS_810,
63	0x10,
64	SF_PCI_RL | SF_PCI_BOF | SF_CHIP_PF | SF_CHIP_LS,
65	4, 8, 3, 250, 0
66	},
67	{ PCI_PRODUCT_SYMBIOS_815,
68	0x00,
69	SF_PCI_RL | SF_PCI_BOF,
70	4, 8, 3, 250, 0
71	},
72	{ PCI_PRODUCT_SYMBIOS_820,
73	0x00,
74	SF_PCI_RL | SF_CHIP_LS | SF_BUS_WIDE,
75	4, 8, 3, 250, 0
76	},
77	{ PCI_PRODUCT_SYMBIOS_825,
78	0x00,
79	SF_PCI_RL | SF_PCI_BOF | SF_BUS_WIDE,
80	4, 8, 3, 250, 0
81	},
82	{ PCI_PRODUCT_SYMBIOS_825,
83	0x10,
84	SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM |
85	SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_LS | SF_CHIP_10REGS |
86	SF_BUS_WIDE,
87	7, 8, 3, 250, 4096
88	},
89	{ PCI_PRODUCT_SYMBIOS_860,
90	0x00,
91	SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM |
92	SF_CHIP_PF | SF_CHIP_LS |
93	SF_BUS_ULTRA,
94	4, 8, 5, 125, 0
95	},
96	{ PCI_PRODUCT_SYMBIOS_875,
97	0x00,
98	SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM |
99	SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_LS | SF_CHIP_10REGS |
100	SF_BUS_ULTRA | SF_BUS_WIDE,
101	7, 16, 5, 125, 4096
102	},
103	{ PCI_PRODUCT_SYMBIOS_875,
104	0x02,
105	SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM |
106	SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_DBLR |
107	SF_CHIP_LS | SF_CHIP_10REGS |
108	SF_BUS_ULTRA | SF_BUS_WIDE,
109	7, 16, 5, 125, 4096
110	},
111	{ PCI_PRODUCT_SYMBIOS_875J,
112	0x00,
113	SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM |
114	SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_DBLR |
115	SF_CHIP_LS | SF_CHIP_10REGS |
116	SF_BUS_ULTRA | SF_BUS_WIDE,
117	7, 16, 5, 125, 4096
118	},
119	{ PCI_PRODUCT_SYMBIOS_885,
120	0x00,
121	SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM |
122	SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_DBLR |
123	SF_CHIP_LS | SF_CHIP_10REGS |
124	SF_BUS_ULTRA | SF_BUS_WIDE,
125	7, 16, 5, 125, 4096
126	},
127	{ PCI_PRODUCT_SYMBIOS_895,
128	0x00,
129	SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM |
130	SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD |
131	SF_CHIP_LS | SF_CHIP_10REGS |
132	SF_BUS_ULTRA2 | SF_BUS_WIDE,
133	7, 31, 7, 62, 4096
134	},
135	{ PCI_PRODUCT_SYMBIOS_896,
136	0x00,
137	SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM |
138	SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD |
139	SF_CHIP_LS | SF_CHIP_10REGS |
140	SF_BUS_ULTRA2 | SF_BUS_WIDE,
141	7, 31, 7, 62, 8192
142	},
143	{ PCI_PRODUCT_SYMBIOS_895A,
144	0x00,
145	SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM |
146	SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD |
147	SF_CHIP_LS | SF_CHIP_10REGS |
148	SF_BUS_ULTRA2 | SF_BUS_WIDE,
149	7, 31, 7, 62, 8192
150	},
151	{ PCI_PRODUCT_SYMBIOS_1510D,
152	0x00,
153	SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM |
154	SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD |
155	SF_CHIP_LS | SF_CHIP_10REGS |
156	SF_BUS_ULTRA2 | SF_BUS_WIDE,
157	7, 31, 7, 62, 4096
158	},
159	{ 0,
160	0x00,
161	0x00,
162	0, 0, 0, 0, 0
163	},
164};
165
166const struct siop_product_desc *
167siop_lookup_product(id, rev)
168	u_int32_t id;
169	int rev;
170{
171	const struct siop_product_desc *pp;
172	const struct siop_product_desc *rp = NULL;
173
174	if (PCI_VENDOR(id) != PCI_VENDOR_SYMBIOS)
175		return NULL;
176
177	for (pp = siop_products; pp->product != 0; pp++) {
178		if (PCI_PRODUCT(id) == pp->product && pp->revision <= rev)
179			if (rp == NULL || pp->revision > rp->revision)
180				rp = pp;
181	}
182	return rp;
183}
184
185int
186siop_pci_attach_common(sc, pa)
187	struct siop_pci_softc *sc;
188	struct pci_attach_args *pa;
189{
190	pci_chipset_tag_t pc = pa->pa_pc;
191	pcitag_t tag = pa->pa_tag;
192	const char *intrstr;
193	pci_intr_handle_t intrhandle;
194	bus_space_tag_t iot, memt;
195	bus_space_handle_t ioh, memh;
196	pcireg_t memtype;
197	int memh_valid, ioh_valid;
198	bus_addr_t ioaddr, memaddr;
199
200	sc->sc_pp = siop_lookup_product(pa->pa_id, PCI_REVISION(pa->pa_class));
201	if (sc->sc_pp == NULL) {
202		printf("sym: broken match/attach!!\n");
203		return 0;
204	}
205	/* copy interesting infos about the chip */
206	sc->siop.features = sc->sc_pp->features;
207	sc->siop.maxburst = sc->sc_pp->maxburst;
208	sc->siop.maxoff = sc->sc_pp->maxoff;
209	sc->siop.clock_div = sc->sc_pp->clock_div;
210	sc->siop.clock_period = sc->sc_pp->clock_period;
211	sc->siop.ram_size = sc->sc_pp->ram_size;
212
213	sc->siop.sc_reset = siop_pci_reset;
214	sc->sc_pc = pc;
215	sc->sc_tag = tag;
216	sc->siop.sc_dmat = pa->pa_dmat;
217
218	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, 0x14);
219	switch (memtype) {
220	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
221	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
222		memh_valid = (pci_mapreg_map(pa, 0x14, memtype, 0,
223		    &memt, &memh, &memaddr, NULL) == 0);
224		break;
225	default:
226		memh_valid = 0;
227	}
228
229	ioh_valid = (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0,
230	    &iot, &ioh, &ioaddr, NULL) == 0);
231
232	if (memh_valid) {
233		sc->siop.sc_rt = memt;
234		sc->siop.sc_rh = memh;
235		sc->siop.sc_raddr = memaddr;
236	} else if (ioh_valid) {
237		sc->siop.sc_rt = iot;
238		sc->siop.sc_rh = ioh;
239		sc->siop.sc_raddr = ioaddr;
240	} else {
241		printf("\n%s: unable to map device registers\n",
242		    sc->siop.sc_dev.dv_xname);
243		return 0;
244	}
245
246	if (sc->siop.features & SF_CHIP_RAM) {
247		int bar;
248		switch (memtype) {
249		case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
250			bar = 0x18;
251			break;
252		case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
253			bar = 0x1c;
254			break;
255		}
256		if (pci_mapreg_map(pa, bar, memtype, 0,
257                    &sc->siop.sc_ramt, &sc->siop.sc_ramh,
258		    &sc->siop.sc_scriptaddr, NULL) != 0)
259			sc->siop.features &= ~SF_CHIP_RAM;
260	}
261
262	if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
263			 pa->pa_intrline, &intrhandle)) {
264		printf("\n%s: couldn't map interrupt\n",
265		    sc->siop.sc_dev.dv_xname);
266		return 0;
267	}
268	intrstr = pci_intr_string(pa->pa_pc, intrhandle);
269	sc->sc_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO,
270	    siop_intr, &sc->siop, sc->siop.sc_dev.dv_xname);
271	if (sc->sc_ih != NULL)
272		printf(": %s, ", (intrstr != NULL) ? intrstr : "irq ?");
273	else {
274		printf("\n%s: couldn't establish interrupt",
275		    sc->siop.sc_dev.dv_xname);
276		if (intrstr != NULL)
277			printf(" at %s", intrstr);
278		printf("\n");
279		return 0;
280	}
281
282	if (sc->siop.features & SF_CHIP_RAM)
283		printf("has RAM\n");
284
285	return 1;
286}
287
288void
289siop_pci_reset(sc)
290	struct siop_softc *sc;
291{
292	int dmode;
293
294	dmode = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DMODE);
295	if (sc->features & SF_PCI_RL)
296		dmode |= DMODE_ERL;
297	if (sc->features & SF_PCI_RM)
298		dmode |= DMODE_ERMP;
299	if (sc->features & SF_PCI_BOF)
300		dmode |= DMODE_BOF;
301	if (sc->features & SF_PCI_CLS)
302		bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL,
303		    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL) |
304		    DCNTL_CLSE);
305	if (sc->features & SF_PCI_WRI)
306		bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3,
307		    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3) |
308		    CTEST3_WRIE);
309	if (sc->maxburst) {
310		int ctest5 = bus_space_read_1(sc->sc_rt, sc->sc_rh,
311		    SIOP_CTEST5);
312		bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4,
313		    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4) &
314		    ~CTEST4_BDIS);
315		dmode &= ~DMODE_BL_MASK;
316		dmode |= ((sc->maxburst - 1) << DMODE_BL_SHIFT) & DMODE_BL_MASK;
317		ctest5 &= ~CTEST5_BBCK;
318		ctest5 |= (sc->maxburst - 1) & CTEST5_BBCK;
319		bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST5, ctest5);
320	} else {
321		bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4,
322		    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4) |
323		    CTEST4_BDIS);
324	}
325	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DMODE, dmode);
326}
327