1/*-
2 * PCI specific probe and attach routines for LSI Fusion Adapters
3 * FreeBSD Version.
4 *
5 * Copyright (c) 2000, 2001 by Greg Ansley
6 * Partially derived from Matt Jacob's ISP driver.
7 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002 by Matthew Jacob
8 * Feral Software
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice immediately at the beginning of the file, without modification,
16 *    this list of conditions, and the following disclaimer.
17 * 2. The name of the author may not be used to endorse or promote products
18 *    derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32/*-
33 * Copyright (c) 2002, 2006 by Matthew Jacob
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions are
38 * met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
42 *    substantially similar to the "NO WARRANTY" disclaimer below
43 *    ("Disclaimer") and any redistribution must be conditioned upon including
44 *    a substantially similar Disclaimer requirement for further binary
45 *    redistribution.
46 * 3. Neither the names of the above listed copyright holders nor the names
47 *    of any contributors may be used to endorse or promote products derived
48 *    from this software without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
51 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
54 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
60 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *
62 * Support from Chris Ellsworth in order to make SAS adapters work
63 * is gratefully acknowledged.
64 *
65 * Support from LSI-Logic has also gone a great deal toward making this a
66 * workable subsystem and is gratefully acknowledged.
67 */
68/*
69 * Copyright (c) 2004, Avid Technology, Inc. and its contributors.
70 * Copyright (c) 2005, WHEEL Sp. z o.o.
71 * Copyright (c) 2004, 2005 Justin T. Gibbs
72 * All rights reserved.
73 *
74 * Redistribution and use in source and binary forms, with or without
75 * modification, are permitted provided that the following conditions are
76 * met:
77 * 1. Redistributions of source code must retain the above copyright
78 *    notice, this list of conditions and the following disclaimer.
79 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
80 *    substantially similar to the "NO WARRANTY" disclaimer below
81 *    ("Disclaimer") and any redistribution must be conditioned upon including
82 *    a substantially similar Disclaimer requirement for further binary
83 *    redistribution.
84 * 3. Neither the names of the above listed copyright holders nor the names
85 *    of any contributors may be used to endorse or promote products derived
86 *    from this software without specific prior written permission.
87 *
88 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
89 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
90 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
91 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
92 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
93 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
94 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
95 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
96 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
97 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
98 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
99 */
100
101#include <sys/cdefs.h>
102__FBSDID("$FreeBSD: stable/11/sys/dev/mpt/mpt_pci.c 315808 2017-03-23 06:34:15Z mav $");
103
104#include <dev/mpt/mpt.h>
105#include <dev/mpt/mpt_cam.h>
106#include <dev/mpt/mpt_raid.h>
107
108/*
109 * XXX it seems no other MPT driver knows about the following chips.
110 */
111
112#ifndef	MPI_MANUFACTPAGE_DEVICEID_FC909_FB
113#define	MPI_MANUFACTPAGE_DEVICEID_FC909_FB	0x0620
114#endif
115
116#ifndef	MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB
117#define	MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB	0x0625
118#endif
119
120#ifndef	MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB
121#define	MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB	0x0623
122#endif
123
124#ifndef	MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB
125#define	MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB	0x0627
126#endif
127
128#ifndef	MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB
129#define	MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB	0x0629
130#endif
131
132#ifndef MPI_MANUFACTPAGE_DEVID_SAS1068A_FB
133#define MPI_MANUFACTPAGE_DEVID_SAS1068A_FB	0x0055
134#endif
135
136#ifndef	MPI_MANUFACTPAGE_DEVID_SAS1068E_FB
137#define	MPI_MANUFACTPAGE_DEVID_SAS1068E_FB	0x0059
138#endif
139
140#ifndef	MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB
141#define	MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB	0x007C
142#endif
143
144static int mpt_pci_probe(device_t);
145static int mpt_pci_attach(device_t);
146static void mpt_free_bus_resources(struct mpt_softc *mpt);
147static int mpt_pci_detach(device_t);
148static int mpt_pci_shutdown(device_t);
149static int mpt_dma_mem_alloc(struct mpt_softc *mpt);
150static void mpt_dma_mem_free(struct mpt_softc *mpt);
151#if 0
152static void mpt_read_config_regs(struct mpt_softc *mpt);
153static void mpt_set_config_regs(struct mpt_softc *mpt);
154#endif
155static void mpt_pci_intr(void *);
156
157static device_method_t mpt_methods[] = {
158	/* Device interface */
159	DEVMETHOD(device_probe,		mpt_pci_probe),
160	DEVMETHOD(device_attach,	mpt_pci_attach),
161	DEVMETHOD(device_detach,	mpt_pci_detach),
162	DEVMETHOD(device_shutdown,	mpt_pci_shutdown),
163	DEVMETHOD_END
164};
165
166static driver_t mpt_driver = {
167	"mpt", mpt_methods, sizeof(struct mpt_softc)
168};
169
170static devclass_t mpt_devclass;
171DRIVER_MODULE(mpt, pci, mpt_driver, mpt_devclass, NULL, NULL);
172MODULE_DEPEND(mpt, pci, 1, 1, 1);
173MODULE_VERSION(mpt, 1);
174
175static int
176mpt_pci_probe(device_t dev)
177{
178	const char *desc;
179	int rval;
180
181	if (pci_get_vendor(dev) != MPI_MANUFACTPAGE_VENDORID_LSILOGIC)
182		return (ENXIO);
183
184	rval = BUS_PROBE_DEFAULT;
185	switch (pci_get_device(dev)) {
186	case MPI_MANUFACTPAGE_DEVICEID_FC909_FB:
187		desc = "LSILogic FC909 FC Adapter";
188		break;
189	case MPI_MANUFACTPAGE_DEVICEID_FC909:
190		desc = "LSILogic FC909A FC Adapter";
191		break;
192	case MPI_MANUFACTPAGE_DEVICEID_FC919:
193		desc = "LSILogic FC919 FC Adapter";
194		break;
195	case MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB:
196		desc = "LSILogic FC919 LAN Adapter";
197		break;
198	case MPI_MANUFACTPAGE_DEVICEID_FC929:
199		desc = "Dual LSILogic FC929 FC Adapter";
200		break;
201	case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB:
202		desc = "Dual LSILogic FC929 LAN Adapter";
203		break;
204	case MPI_MANUFACTPAGE_DEVICEID_FC919X:
205		desc = "LSILogic FC919 FC PCI-X Adapter";
206		break;
207	case MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB:
208		desc = "LSILogic FC919 LAN PCI-X Adapter";
209		break;
210	case MPI_MANUFACTPAGE_DEVICEID_FC929X:
211		desc = "Dual LSILogic FC929X 2Gb/s FC PCI-X Adapter";
212		break;
213	case MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB:
214		desc = "Dual LSILogic FC929X LAN PCI-X Adapter";
215		break;
216	case MPI_MANUFACTPAGE_DEVICEID_FC949E:
217		desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-Express Adapter";
218		break;
219	case MPI_MANUFACTPAGE_DEVICEID_FC949X:
220		desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-X Adapter";
221		break;
222	case MPI_MANUFACTPAGE_DEVID_53C1030:
223	case MPI_MANUFACTPAGE_DEVID_53C1030ZC:
224		desc = "LSILogic 1030 Ultra4 Adapter";
225		break;
226	case MPI_MANUFACTPAGE_DEVID_SAS1068E_FB:
227		/*
228		 * Allow mfi(4) to claim this device in case it's in MegaRAID
229		 * mode.
230		 */
231		rval = BUS_PROBE_LOW_PRIORITY;
232		/* FALLTHROUGH */
233	case MPI_MANUFACTPAGE_DEVID_SAS1064:
234	case MPI_MANUFACTPAGE_DEVID_SAS1064A:
235	case MPI_MANUFACTPAGE_DEVID_SAS1064E:
236	case MPI_MANUFACTPAGE_DEVID_SAS1066:
237	case MPI_MANUFACTPAGE_DEVID_SAS1066E:
238	case MPI_MANUFACTPAGE_DEVID_SAS1068:
239	case MPI_MANUFACTPAGE_DEVID_SAS1068A_FB:
240	case MPI_MANUFACTPAGE_DEVID_SAS1068E:
241	case MPI_MANUFACTPAGE_DEVID_SAS1078:
242	case MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB:
243		desc = "LSILogic SAS/SATA Adapter";
244		break;
245	default:
246		return (ENXIO);
247	}
248
249	device_set_desc(dev, desc);
250	return (rval);
251}
252
253static void
254mpt_set_options(struct mpt_softc *mpt)
255{
256	int tval;
257
258	tval = 0;
259	if (resource_int_value(device_get_name(mpt->dev),
260	    device_get_unit(mpt->dev), "debug", &tval) == 0 && tval != 0) {
261		mpt->verbose = tval;
262	}
263	tval = -1;
264	if (resource_int_value(device_get_name(mpt->dev),
265	    device_get_unit(mpt->dev), "role", &tval) == 0 && tval >= 0 &&
266	    tval <= 3) {
267		mpt->cfg_role = tval;
268		mpt->do_cfg_role = 1;
269	}
270	tval = 0;
271	mpt->msi_enable = 0;
272	if (mpt->is_sas)
273		mpt->msi_enable = 1;
274	if (resource_int_value(device_get_name(mpt->dev),
275	    device_get_unit(mpt->dev), "msi_enable", &tval) == 0) {
276		mpt->msi_enable = tval;
277	}
278}
279
280#if 0
281static void
282mpt_link_peer(struct mpt_softc *mpt)
283{
284	struct mpt_softc *mpt2;
285
286	if (mpt->unit == 0) {
287		return;
288	}
289	/*
290	 * XXX: depends on probe order
291	 */
292	mpt2 = (struct mpt_softc *)devclass_get_softc(mpt_devclass,mpt->unit-1);
293
294	if (mpt2 == NULL) {
295		return;
296	}
297	if (pci_get_vendor(mpt2->dev) != pci_get_vendor(mpt->dev)) {
298		return;
299	}
300	if (pci_get_device(mpt2->dev) != pci_get_device(mpt->dev)) {
301		return;
302	}
303	mpt->mpt2 = mpt2;
304	mpt2->mpt2 = mpt;
305	if (mpt->verbose >= MPT_PRT_DEBUG) {
306		mpt_prt(mpt, "linking with peer (mpt%d)\n",
307		    device_get_unit(mpt2->dev));
308	}
309}
310
311static void
312mpt_unlink_peer(struct mpt_softc *mpt)
313{
314
315	if (mpt->mpt2) {
316		mpt->mpt2->mpt2 = NULL;
317	}
318}
319#endif
320
321static int
322mpt_pci_attach(device_t dev)
323{
324	struct mpt_softc *mpt;
325	int		  iqd;
326	uint32_t	  val;
327	int		  mpt_io_bar, mpt_mem_bar;
328
329	mpt  = (struct mpt_softc*)device_get_softc(dev);
330
331	switch (pci_get_device(dev)) {
332	case MPI_MANUFACTPAGE_DEVICEID_FC909_FB:
333	case MPI_MANUFACTPAGE_DEVICEID_FC909:
334	case MPI_MANUFACTPAGE_DEVICEID_FC919:
335	case MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB:
336	case MPI_MANUFACTPAGE_DEVICEID_FC929:
337	case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB:
338	case MPI_MANUFACTPAGE_DEVICEID_FC929X:
339	case MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB:
340	case MPI_MANUFACTPAGE_DEVICEID_FC919X:
341	case MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB:
342	case MPI_MANUFACTPAGE_DEVICEID_FC949E:
343	case MPI_MANUFACTPAGE_DEVICEID_FC949X:
344		mpt->is_fc = 1;
345		break;
346	case MPI_MANUFACTPAGE_DEVID_SAS1078:
347	case MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB:
348		mpt->is_1078 = 1;
349		/* FALLTHROUGH */
350	case MPI_MANUFACTPAGE_DEVID_SAS1064:
351	case MPI_MANUFACTPAGE_DEVID_SAS1064A:
352	case MPI_MANUFACTPAGE_DEVID_SAS1064E:
353	case MPI_MANUFACTPAGE_DEVID_SAS1066:
354	case MPI_MANUFACTPAGE_DEVID_SAS1066E:
355	case MPI_MANUFACTPAGE_DEVID_SAS1068:
356	case MPI_MANUFACTPAGE_DEVID_SAS1068A_FB:
357	case MPI_MANUFACTPAGE_DEVID_SAS1068E:
358	case MPI_MANUFACTPAGE_DEVID_SAS1068E_FB:
359		mpt->is_sas = 1;
360		break;
361	default:
362		mpt->is_spi = 1;
363		break;
364	}
365	mpt->dev = dev;
366	mpt->unit = device_get_unit(dev);
367	mpt->raid_resync_rate = MPT_RAID_RESYNC_RATE_DEFAULT;
368	mpt->raid_mwce_setting = MPT_RAID_MWCE_DEFAULT;
369	mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT;
370	mpt->verbose = MPT_PRT_NONE;
371	mpt->role = MPT_ROLE_NONE;
372	mpt->mpt_ini_id = MPT_INI_ID_NONE;
373#ifdef __sparc64__
374	if (mpt->is_spi)
375		mpt->mpt_ini_id = OF_getscsinitid(dev);
376#endif
377	mpt_set_options(mpt);
378	if (mpt->verbose == MPT_PRT_NONE) {
379		mpt->verbose = MPT_PRT_WARN;
380		/* Print INFO level (if any) if bootverbose is set */
381		mpt->verbose += (bootverbose != 0)? 1 : 0;
382	}
383
384	/*
385	 * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set.
386	 */
387	val = pci_read_config(dev, PCIR_COMMAND, 2);
388	val |= PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN |
389	    PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
390	pci_write_config(dev, PCIR_COMMAND, val, 2);
391
392	/*
393	 * Make sure we've disabled the ROM.
394	 */
395	val = pci_read_config(dev, PCIR_BIOS, 4);
396	val &= ~PCIM_BIOS_ENABLE;
397	pci_write_config(dev, PCIR_BIOS, val, 4);
398
399#if 0
400	/*
401	 * Is this part a dual?
402	 * If so, link with our partner (around yet)
403	 */
404	switch (pci_get_device(dev)) {
405	case MPI_MANUFACTPAGE_DEVICEID_FC929:
406	case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB:
407	case MPI_MANUFACTPAGE_DEVICEID_FC949E:
408	case MPI_MANUFACTPAGE_DEVICEID_FC949X:
409	case MPI_MANUFACTPAGE_DEVID_53C1030:
410	case MPI_MANUFACTPAGE_DEVID_53C1030ZC:
411		mpt_link_peer(mpt);
412		break;
413	default:
414		break;
415	}
416#endif
417
418	/*
419	 * Figure out which are the I/O and MEM Bars
420	 */
421	val = pci_read_config(dev, PCIR_BAR(0), 4);
422	if (PCI_BAR_IO(val)) {
423		/* BAR0 is IO, BAR1 is memory */
424		mpt_io_bar = 0;
425		mpt_mem_bar = 1;
426	} else {
427		/* BAR0 is memory, BAR1 is IO */
428		mpt_mem_bar = 0;
429		mpt_io_bar = 1;
430	}
431
432	/*
433	 * Set up register access.  PIO mode is required for
434	 * certain reset operations (but must be disabled for
435	 * some cards otherwise).
436	 */
437	mpt_io_bar = PCIR_BAR(mpt_io_bar);
438	mpt->pci_pio_reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
439	    &mpt_io_bar, RF_ACTIVE);
440	if (mpt->pci_pio_reg == NULL) {
441		if (bootverbose) {
442			device_printf(dev,
443			    "unable to map registers in PIO mode\n");
444		}
445	} else {
446		mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg);
447		mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg);
448	}
449
450	mpt_mem_bar = PCIR_BAR(mpt_mem_bar);
451	mpt->pci_reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
452	    &mpt_mem_bar, RF_ACTIVE);
453	if (mpt->pci_reg == NULL) {
454		if (bootverbose || mpt->is_sas || mpt->pci_pio_reg == NULL) {
455			device_printf(dev,
456			    "Unable to memory map registers.\n");
457		}
458		if (mpt->is_sas || mpt->pci_pio_reg == NULL) {
459			device_printf(dev, "Giving Up.\n");
460			goto bad;
461		}
462		if (bootverbose) {
463			device_printf(dev, "Falling back to PIO mode.\n");
464		}
465		mpt->pci_st = mpt->pci_pio_st;
466		mpt->pci_sh = mpt->pci_pio_sh;
467	} else {
468		mpt->pci_st = rman_get_bustag(mpt->pci_reg);
469		mpt->pci_sh = rman_get_bushandle(mpt->pci_reg);
470	}
471
472	/* Get a handle to the interrupt */
473	iqd = 0;
474	if (mpt->msi_enable) {
475		/*
476		 * First try to alloc an MSI-X message.  If that
477		 * fails, then try to alloc an MSI message instead.
478		 */
479		val = 1;
480		if (pci_alloc_msix(dev, &val) == 0)
481			iqd = 1;
482		val = 1;
483		if (iqd == 0 && pci_alloc_msi(dev, &val) == 0)
484			iqd = 1;
485	}
486	mpt->pci_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
487	    RF_ACTIVE | (iqd != 0 ? 0 : RF_SHAREABLE));
488	if (mpt->pci_irq == NULL) {
489		device_printf(dev, "could not allocate interrupt\n");
490		goto bad;
491	}
492
493	MPT_LOCK_SETUP(mpt);
494
495	/* Disable interrupts at the part */
496	mpt_disable_ints(mpt);
497
498	/* Register the interrupt handler */
499	if (bus_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, NULL, mpt_pci_intr,
500	    mpt, &mpt->ih)) {
501		device_printf(dev, "could not setup interrupt\n");
502		goto bad;
503	}
504
505	/* Allocate dma memory */
506	if (mpt_dma_mem_alloc(mpt)) {
507		mpt_prt(mpt, "Could not allocate DMA memory\n");
508		goto bad;
509	}
510
511#if 0
512	/*
513	 * Save the PCI config register values
514 	 *
515	 * Hard resets are known to screw up the BAR for diagnostic
516	 * memory accesses (Mem1).
517	 *
518	 * Using Mem1 is known to make the chip stop responding to
519	 * configuration space transfers, so we need to save it now
520	 */
521
522	mpt_read_config_regs(mpt);
523#endif
524
525	/*
526	 * Disable PIO until we need it
527	 */
528	if (mpt->is_sas) {
529		pci_disable_io(dev, SYS_RES_IOPORT);
530	}
531
532	/* Initialize the hardware */
533	if (mpt->disabled == 0) {
534		if (mpt_attach(mpt) != 0) {
535			goto bad;
536		}
537	} else {
538		mpt_prt(mpt, "device disabled at user request\n");
539		goto bad;
540	}
541
542	mpt->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, mpt_pci_shutdown,
543	    dev, SHUTDOWN_PRI_LAST);
544
545	if (mpt->eh == NULL) {
546		mpt_prt(mpt, "shutdown event registration failed\n");
547		mpt_disable_ints(mpt);
548		(void) mpt_detach(mpt);
549		mpt_reset(mpt, /*reinit*/FALSE);
550		mpt_raid_free_mem(mpt);
551		goto bad;
552	}
553	return (0);
554
555bad:
556	mpt_dma_mem_free(mpt);
557	mpt_free_bus_resources(mpt);
558#if 0
559	mpt_unlink_peer(mpt);
560#endif
561
562	MPT_LOCK_DESTROY(mpt);
563
564	/*
565	 * but return zero to preserve unit numbering
566	 */
567	return (0);
568}
569
570/*
571 * Free bus resources
572 */
573static void
574mpt_free_bus_resources(struct mpt_softc *mpt)
575{
576
577	if (mpt->ih) {
578		bus_teardown_intr(mpt->dev, mpt->pci_irq, mpt->ih);
579		mpt->ih = NULL;
580	}
581
582	if (mpt->pci_irq) {
583		bus_release_resource(mpt->dev, SYS_RES_IRQ,
584		    rman_get_rid(mpt->pci_irq), mpt->pci_irq);
585		pci_release_msi(mpt->dev);
586		mpt->pci_irq = NULL;
587	}
588
589	if (mpt->pci_pio_reg) {
590		bus_release_resource(mpt->dev, SYS_RES_IOPORT,
591		    rman_get_rid(mpt->pci_pio_reg), mpt->pci_pio_reg);
592		mpt->pci_pio_reg = NULL;
593	}
594
595	if (mpt->pci_reg) {
596		bus_release_resource(mpt->dev, SYS_RES_MEMORY,
597		    rman_get_rid(mpt->pci_reg), mpt->pci_reg);
598		mpt->pci_reg = NULL;
599	}
600}
601
602/*
603 * Disconnect ourselves from the system.
604 */
605static int
606mpt_pci_detach(device_t dev)
607{
608	struct mpt_softc *mpt;
609
610	mpt  = (struct mpt_softc*)device_get_softc(dev);
611
612	if (mpt) {
613		mpt_disable_ints(mpt);
614		mpt_detach(mpt);
615		mpt_reset(mpt, /*reinit*/FALSE);
616		mpt_raid_free_mem(mpt);
617		mpt_dma_mem_free(mpt);
618		mpt_free_bus_resources(mpt);
619#if 0
620		mpt_unlink_peer(mpt);
621#endif
622		if (mpt->eh != NULL) {
623                        EVENTHANDLER_DEREGISTER(shutdown_post_sync, mpt->eh);
624		}
625		MPT_LOCK_DESTROY(mpt);
626	}
627	return(0);
628}
629
630/*
631 * Disable the hardware
632 */
633static int
634mpt_pci_shutdown(device_t dev)
635{
636	struct mpt_softc *mpt;
637
638	mpt = (struct mpt_softc *)device_get_softc(dev);
639	if (mpt)
640		return (mpt_shutdown(mpt));
641	return(0);
642}
643
644static int
645mpt_dma_mem_alloc(struct mpt_softc *mpt)
646{
647	size_t len;
648	struct mpt_map_info mi;
649
650	/* Check if we alreay have allocated the reply memory */
651	if (mpt->reply_phys != 0) {
652		return 0;
653	}
654
655	len = sizeof (request_t) * MPT_MAX_REQUESTS(mpt);
656	mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK|M_ZERO);
657
658	/*
659	 * Create a parent dma tag for this device.
660	 *
661	 * Align at byte boundaries,
662	 * Limit to 32-bit addressing for request/reply queues.
663	 */
664	if (mpt_dma_tag_create(mpt, /*parent*/bus_get_dma_tag(mpt->dev),
665	    /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR,
666	    /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL,
667	    /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
668	    /*nsegments*/BUS_SPACE_UNRESTRICTED,
669	    /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, /*flags*/0,
670	    &mpt->parent_dmat) != 0) {
671		mpt_prt(mpt, "cannot create parent dma tag\n");
672		return (1);
673	}
674
675	/* Create a child tag for reply buffers */
676	if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0,
677	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
678	    NULL, NULL, 2 * PAGE_SIZE, 1, BUS_SPACE_MAXSIZE_32BIT, 0,
679	    &mpt->reply_dmat) != 0) {
680		mpt_prt(mpt, "cannot create a dma tag for replies\n");
681		return (1);
682	}
683
684	/* Allocate some DMA accessible memory for replies */
685	if (bus_dmamem_alloc(mpt->reply_dmat, (void **)&mpt->reply,
686	    BUS_DMA_NOWAIT, &mpt->reply_dmap) != 0) {
687		mpt_prt(mpt, "cannot allocate %lu bytes of reply memory\n",
688		    (u_long) (2 * PAGE_SIZE));
689		return (1);
690	}
691
692	mi.mpt = mpt;
693	mi.error = 0;
694
695	/* Load and lock it into "bus space" */
696	bus_dmamap_load(mpt->reply_dmat, mpt->reply_dmap, mpt->reply,
697	    2 * PAGE_SIZE, mpt_map_rquest, &mi, 0);
698
699	if (mi.error) {
700		mpt_prt(mpt, "error %d loading dma map for DMA reply queue\n",
701		    mi.error);
702		return (1);
703	}
704	mpt->reply_phys = mi.phys;
705
706	return (0);
707}
708
709/* Deallocate memory that was allocated by mpt_dma_mem_alloc
710 */
711static void
712mpt_dma_mem_free(struct mpt_softc *mpt)
713{
714
715        /* Make sure we aren't double destroying */
716        if (mpt->reply_dmat == 0) {
717		mpt_lprt(mpt, MPT_PRT_DEBUG, "already released dma memory\n");
718		return;
719        }
720
721	bus_dmamap_unload(mpt->reply_dmat, mpt->reply_dmap);
722	bus_dmamem_free(mpt->reply_dmat, mpt->reply, mpt->reply_dmap);
723	bus_dma_tag_destroy(mpt->reply_dmat);
724	bus_dma_tag_destroy(mpt->parent_dmat);
725	mpt->reply_dmat = NULL;
726	free(mpt->request_pool, M_DEVBUF);
727	mpt->request_pool = NULL;
728}
729
730#if 0
731/* Reads modifiable (via PCI transactions) config registers */
732static void
733mpt_read_config_regs(struct mpt_softc *mpt)
734{
735
736	mpt->pci_cfg.Command = pci_read_config(mpt->dev, PCIR_COMMAND, 2);
737	mpt->pci_cfg.LatencyTimer_LineSize =
738	    pci_read_config(mpt->dev, PCIR_CACHELNSZ, 2);
739	mpt->pci_cfg.IO_BAR = pci_read_config(mpt->dev, PCIR_BAR(0), 4);
740	mpt->pci_cfg.Mem0_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(1), 4);
741	mpt->pci_cfg.Mem0_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(2), 4);
742	mpt->pci_cfg.Mem1_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(3), 4);
743	mpt->pci_cfg.Mem1_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(4), 4);
744	mpt->pci_cfg.ROM_BAR = pci_read_config(mpt->dev, PCIR_BIOS, 4);
745	mpt->pci_cfg.IntLine = pci_read_config(mpt->dev, PCIR_INTLINE, 1);
746	mpt->pci_cfg.PMCSR = pci_read_config(mpt->dev, 0x44, 4);
747}
748
749/* Sets modifiable config registers */
750static void
751mpt_set_config_regs(struct mpt_softc *mpt)
752{
753	uint32_t val;
754
755#define MPT_CHECK(reg, offset, size)					\
756	val = pci_read_config(mpt->dev, offset, size);			\
757	if (mpt->pci_cfg.reg != val) {					\
758		mpt_prt(mpt,						\
759		    "Restoring " #reg " to 0x%X from 0x%X\n",		\
760		    mpt->pci_cfg.reg, val);				\
761	}
762
763	if (mpt->verbose >= MPT_PRT_DEBUG) {
764		MPT_CHECK(Command, PCIR_COMMAND, 2);
765		MPT_CHECK(LatencyTimer_LineSize, PCIR_CACHELNSZ, 2);
766		MPT_CHECK(IO_BAR, PCIR_BAR(0), 4);
767		MPT_CHECK(Mem0_BAR[0], PCIR_BAR(1), 4);
768		MPT_CHECK(Mem0_BAR[1], PCIR_BAR(2), 4);
769		MPT_CHECK(Mem1_BAR[0], PCIR_BAR(3), 4);
770		MPT_CHECK(Mem1_BAR[1], PCIR_BAR(4), 4);
771		MPT_CHECK(ROM_BAR, PCIR_BIOS, 4);
772		MPT_CHECK(IntLine, PCIR_INTLINE, 1);
773		MPT_CHECK(PMCSR, 0x44, 4);
774	}
775#undef MPT_CHECK
776
777	pci_write_config(mpt->dev, PCIR_COMMAND, mpt->pci_cfg.Command, 2);
778	pci_write_config(mpt->dev, PCIR_CACHELNSZ,
779	    mpt->pci_cfg.LatencyTimer_LineSize, 2);
780	pci_write_config(mpt->dev, PCIR_BAR(0), mpt->pci_cfg.IO_BAR, 4);
781	pci_write_config(mpt->dev, PCIR_BAR(1), mpt->pci_cfg.Mem0_BAR[0], 4);
782	pci_write_config(mpt->dev, PCIR_BAR(2), mpt->pci_cfg.Mem0_BAR[1], 4);
783	pci_write_config(mpt->dev, PCIR_BAR(3), mpt->pci_cfg.Mem1_BAR[0], 4);
784	pci_write_config(mpt->dev, PCIR_BAR(4), mpt->pci_cfg.Mem1_BAR[1], 4);
785	pci_write_config(mpt->dev, PCIR_BIOS, mpt->pci_cfg.ROM_BAR, 4);
786	pci_write_config(mpt->dev, PCIR_INTLINE, mpt->pci_cfg.IntLine, 1);
787	pci_write_config(mpt->dev, 0x44, mpt->pci_cfg.PMCSR, 4);
788}
789#endif
790
791static void
792mpt_pci_intr(void *arg)
793{
794	struct mpt_softc *mpt;
795
796	mpt = (struct mpt_softc *)arg;
797	MPT_LOCK(mpt);
798	mpt_intr(mpt);
799	MPT_UNLOCK(mpt);
800}
801