xref: /dragonfly/sys/dev/disk/mpt/mpt_pci.c (revision 19fe1c42)
1 /* $FreeBSD: src/sys/dev/mpt/mpt_pci.c,v 1.3.2.3 2002/09/24 21:37:25 mjacob Exp $ */
2 /* $DragonFly: src/sys/dev/disk/mpt/mpt_pci.c,v 1.12 2008/06/05 18:06:31 swildner Exp $ */
3 /*
4  * PCI specific probe and attach routines for LSI '909 FC  adapters.
5  * FreeBSD Version.
6  *
7  * Copyright (c)  2000, 2001 by Greg Ansley
8  * Partially derived from Matt Jacob's ISP driver.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice immediately at the beginning of the file, without modification,
15  *    this list of conditions, and the following disclaimer.
16  * 2. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 /*
32  * Additional Copyright (c) 2002 by Matthew Jacob under same license.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/bus.h>
40 #include <sys/rman.h>
41 #include <sys/malloc.h>
42 
43 #include <bus/pci/pcidevs.h>
44 #include <bus/pci/pcireg.h>
45 #include <bus/pci/pcivar.h>
46 
47 #include "mpt_freebsd.h"
48 
49 #ifndef	PCIM_CMD_SERRESPEN
50 #define	PCIM_CMD_SERRESPEN	0x0100
51 #endif
52 
53 
54 
55 #define	MEM_MAP_REG	0x14
56 #define	MEM_MAP_SRAM	0x1C
57 
58 static int mpt_probe(device_t);
59 static int mpt_attach(device_t);
60 static void mpt_free_bus_resources(mpt_softc_t *mpt);
61 static int mpt_detach(device_t);
62 static int mpt_shutdown(device_t);
63 static int mpt_dma_mem_alloc(mpt_softc_t *mpt);
64 static void mpt_dma_mem_free(mpt_softc_t *mpt);
65 static void mpt_read_config_regs(mpt_softc_t *mpt);
66 static void mpt_pci_intr(void *);
67 
68 static device_method_t mpt_methods[] = {
69 	/* Device interface */
70 	DEVMETHOD(device_probe,		mpt_probe),
71 	DEVMETHOD(device_attach,	mpt_attach),
72 	DEVMETHOD(device_detach,	mpt_detach),
73 	DEVMETHOD(device_shutdown,	mpt_shutdown),
74 	{ 0, 0 }
75 };
76 
77 static driver_t mpt_driver = {
78 	"mpt", mpt_methods, sizeof (mpt_softc_t)
79 };
80 static devclass_t mpt_devclass;
81 DRIVER_MODULE(mpt, pci, mpt_driver, mpt_devclass, 0, 0);
82 MODULE_VERSION(mpt, 1);
83 
84 int
85 mpt_intr(void *dummy)
86 {
87 	int nrepl = 0;
88 	u_int32_t reply;
89 	mpt_softc_t *mpt = (mpt_softc_t *)dummy;
90 
91 	if ((mpt_read(mpt, MPT_OFFSET_INTR_STATUS) & MPT_INTR_REPLY_READY) == 0)
92 		return (0);
93 	reply = mpt_pop_reply_queue(mpt);
94 	while (reply != MPT_REPLY_EMPTY) {
95 		nrepl++;
96 		if (mpt->verbose > 1) {
97 			if ((reply & MPT_CONTEXT_REPLY) != 0)  {
98 				/* Address reply; IOC has something to say */
99 				mpt_print_reply(MPT_REPLY_PTOV(mpt, reply));
100 			} else {
101 				/* Context reply ; all went well */
102 				device_printf(mpt->dev,
103 				    "context %u reply OK\n", reply);
104 			}
105 		}
106 		mpt_done(mpt, reply);
107 		reply = mpt_pop_reply_queue(mpt);
108 	}
109 	return (nrepl != 0);
110 }
111 
112 static int
113 mpt_probe(device_t dev)
114 {
115 	char *desc;
116 
117 	if (pci_get_vendor(dev) != PCI_VENDOR_SYMBIOS)
118 		return (ENXIO);
119 
120 	switch ((pci_get_device(dev) & ~1)) {
121 	case PCI_PRODUCT_SYMBIOS_FC909:
122 		desc = "LSILogic FC909 FC Adapter";
123 		break;
124 	case PCI_PRODUCT_SYMBIOS_FC909A:
125 		desc = "LSILogic FC909A FC Adapter";
126 		break;
127 	case PCI_PRODUCT_SYMBIOS_FC919:
128 		desc = "LSILogic FC919 FC Adapter";
129 		break;
130 	case PCI_PRODUCT_SYMBIOS_FC929:
131 		desc = "LSILogic FC929 FC Adapter";
132 		break;
133 	case PCI_PRODUCT_SYMBIOS_FC929X:
134 		desc = "LSILogic FC929X FC Adapter";
135 		break;
136 	case PCI_PRODUCT_SYMBIOS_1030:
137 		desc = "LSILogic 1030 Ultra4 Adapter";
138 		break;
139 	default:
140 		return (ENXIO);
141 	}
142 
143 	device_set_desc(dev, desc);
144 	return (0);
145 }
146 
147 static void
148 mpt_set_options(mpt_softc_t *mpt)
149 {
150 	int bitmap;
151 
152 	bitmap = 0;
153 	if (kgetenv_int("mpt_disable", &bitmap)) {
154 		if (bitmap & (1 << mpt->unit)) {
155 			mpt->disabled = 1;
156 		}
157 	}
158 
159 	bitmap = 0;
160 	if (kgetenv_int("mpt_debug", &bitmap)) {
161 		if (bitmap & (1 << mpt->unit)) {
162 			mpt->verbose = 2;
163 		}
164 	}
165 
166 }
167 
168 static void
169 mpt_link_peer(mpt_softc_t *mpt)
170 {
171 	mpt_softc_t *mpt2;
172 
173 	if (mpt->unit == 0) {
174 		return;
175 	}
176 
177 	/*
178 	 * XXX: depends on probe order
179 	 */
180 	mpt2 = (mpt_softc_t *) devclass_get_softc(mpt_devclass, mpt->unit-1);
181 
182 	if (mpt2 == NULL) {
183 		return;
184 	}
185 	if (pci_get_vendor(mpt2->dev) != pci_get_vendor(mpt->dev)) {
186 		return;
187 	}
188 	if (pci_get_device(mpt2->dev) != pci_get_device(mpt->dev)) {
189 		return;
190 	}
191 	mpt->mpt2 = mpt2;
192 	mpt2->mpt2 = mpt;
193 	if (mpt->verbose) {
194 		device_printf(mpt->dev, "linking with peer (mpt%d)\n",
195 		    device_get_unit(mpt2->dev));
196 	}
197 }
198 
199 
200 static int
201 mpt_attach(device_t dev)
202 {
203 	int iqd;
204 	u_int32_t data, cmd;
205 	mpt_softc_t *mpt;
206 
207 	/* Allocate the softc structure */
208 	mpt  = (mpt_softc_t*) device_get_softc(dev);
209 	if (mpt == NULL) {
210 		device_printf(dev, "cannot allocate softc\n");
211 		return (ENOMEM);
212 	}
213 	bzero(mpt, sizeof (mpt_softc_t));
214 	switch ((pci_get_device(dev) & ~1)) {
215 	case PCI_PRODUCT_SYMBIOS_FC909:
216 	case PCI_PRODUCT_SYMBIOS_FC909A:
217 	case PCI_PRODUCT_SYMBIOS_FC919:
218 	case PCI_PRODUCT_SYMBIOS_FC929:
219 	case PCI_PRODUCT_SYMBIOS_FC929X:
220 		mpt->is_fc = 1;
221 		break;
222 	default:
223 		break;
224 	}
225 	mpt->dev = dev;
226 	mpt->unit = device_get_unit(dev);
227 	mpt_set_options(mpt);
228 	mpt->verbose += (bootverbose != 0)? 1 : 0;
229 
230 	/* Make sure memory access decoders are enabled */
231 	cmd = pci_read_config(dev, PCIR_COMMAND, 2);
232 	if ((cmd & PCIM_CMD_MEMEN) == 0) {
233 		device_printf(dev, "Memory accesses disabled");
234 		goto bad;
235 	}
236 
237 	/*
238 	 * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set.
239 	 */
240 	cmd |=
241 	    PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN |
242 	    PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
243 	pci_write_config(dev, PCIR_COMMAND, cmd, 2);
244 
245 	/*
246 	 * Make sure we've disabled the ROM.
247 	 */
248 	data = pci_read_config(dev, PCIR_BIOS, 4);
249 	data &= ~1;
250 	pci_write_config(dev, PCIR_BIOS, data, 4);
251 
252 
253 	/*
254 	 * Is this part a dual?
255 	 * If so, link with our partner (around yet)
256 	 */
257 	if ((pci_get_device(dev) & ~1) == PCI_PRODUCT_SYMBIOS_FC929 ||
258 	    (pci_get_device(dev) & ~1) == PCI_PRODUCT_SYMBIOS_FC929X ||
259 	    (pci_get_device(dev) & ~1) == PCI_PRODUCT_SYMBIOS_1030) {
260 		mpt_link_peer(mpt);
261 	}
262 
263 	/* Set up the memory regions */
264 	/* Allocate kernel virtual memory for the 9x9's Mem0 region */
265 	mpt->pci_reg_id = MEM_MAP_REG;
266 	mpt->pci_reg = bus_alloc_resource(dev, SYS_RES_MEMORY,
267 			&mpt->pci_reg_id, 0, ~0, 0, RF_ACTIVE);
268 	if (mpt->pci_reg == NULL) {
269 		device_printf(dev, "unable to map any ports\n");
270 		goto bad;
271 	}
272 	mpt->pci_st = rman_get_bustag(mpt->pci_reg);
273 	mpt->pci_sh = rman_get_bushandle(mpt->pci_reg);
274 	/*   Get the Physical Address */
275 	mpt->pci_pa = rman_get_start(mpt->pci_reg);
276 
277 	/* Get a handle to the interrupt */
278 	iqd = 0;
279 	mpt->pci_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &iqd, 0, ~0,
280 	    1, RF_ACTIVE | RF_SHAREABLE);
281 	if (mpt->pci_irq == NULL) {
282 		device_printf(dev, "could not allocate interrupt\n");
283 		goto bad;
284 	}
285 
286 	/* Register the interrupt handler */
287 	if (bus_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, mpt_pci_intr,
288 			   mpt, &mpt->ih, NULL)) {
289 		device_printf(dev, "could not setup interrupt\n");
290 		goto bad;
291 	}
292 
293 	MPT_LOCK_SETUP(mpt);
294 
295 	/* Disable interrupts at the part */
296 	mpt_disable_ints(mpt);
297 
298 	/* Allocate dma memory */
299 	if (mpt_dma_mem_alloc(mpt)) {
300 		device_printf(dev, "Could not allocate DMA memory\n");
301 		goto bad;
302 	}
303 
304 	/*
305 	 * Save the PCI config register values
306  	 *
307 	 * Hard resets are known to screw up the BAR for diagnostic
308 	 * memory accesses (Mem1).
309 	 *
310 	 * Using Mem1 is known to make the chip stop responding to
311 	 * configuration space transfers, so we need to save it now
312 	 */
313 
314 	mpt_read_config_regs(mpt);
315 
316 	/* Initialize the hardware */
317 	if (mpt->disabled == 0) {
318 		MPT_LOCK(mpt);
319 		if (mpt_init(mpt, MPT_DB_INIT_HOST) != 0) {
320 			MPT_UNLOCK(mpt);
321 			goto bad;
322 		}
323 
324 		/*
325 		 *  Attach to CAM
326 		 */
327 		mpt_cam_attach(mpt);
328 		MPT_UNLOCK(mpt);
329 	}
330 
331 	return (0);
332 
333 bad:
334 	mpt_dma_mem_free(mpt);
335 	mpt_free_bus_resources(mpt);
336 
337 	/*
338 	 * but return zero to preserve unit numbering
339 	 */
340 	return (0);
341 }
342 
343 /*
344  * Free bus resources
345  */
346 static void
347 mpt_free_bus_resources(mpt_softc_t *mpt)
348 {
349 	if (mpt->ih) {
350 		bus_teardown_intr(mpt->dev, mpt->pci_irq, mpt->ih);
351 		mpt->ih = 0;
352 	}
353 
354 	if (mpt->pci_irq) {
355 		bus_release_resource(mpt->dev, SYS_RES_IRQ, 0, mpt->pci_irq);
356 		mpt->pci_irq = 0;
357 	}
358 
359 	if (mpt->pci_reg) {
360 		bus_release_resource(mpt->dev, SYS_RES_MEMORY, mpt->pci_reg_id,
361 			mpt->pci_reg);
362 		mpt->pci_reg = 0;
363 	}
364 	MPT_LOCK_DESTROY(mpt);
365 }
366 
367 
368 /*
369  * Disconnect ourselves from the system.
370  */
371 static int
372 mpt_detach(device_t dev)
373 {
374 	mpt_softc_t *mpt;
375 	mpt  = (mpt_softc_t*) device_get_softc(dev);
376 
377 	device_printf(mpt->dev,"mpt_detach!\n");
378 
379 	if (mpt) {
380 		mpt_disable_ints(mpt);
381 		mpt_cam_detach(mpt);
382 		mpt_reset(mpt);
383 		mpt_dma_mem_free(mpt);
384 		mpt_free_bus_resources(mpt);
385 	}
386 	return(0);
387 }
388 
389 
390 /*
391  * Disable the hardware
392  */
393 static int
394 mpt_shutdown(device_t dev)
395 {
396 	mpt_softc_t *mpt;
397 	mpt  = (mpt_softc_t*) device_get_softc(dev);
398 
399 	if (mpt) {
400 		mpt_reset(mpt);
401 	}
402 	return(0);
403 }
404 
405 
406 struct imush {
407 	mpt_softc_t *mpt;
408 	int error;
409 	u_int32_t phys;
410 };
411 
412 static void
413 mpt_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error)
414 {
415 	struct imush *imushp = (struct imush *) arg;
416 	imushp->error = error;
417 	imushp->phys = segs->ds_addr;
418 }
419 
420 
421 static int
422 mpt_dma_mem_alloc(mpt_softc_t *mpt)
423 {
424 	int i, error;
425 	u_char *vptr;
426 	u_int32_t pptr, end;
427 	size_t len;
428 	struct imush im;
429 	device_t dev = mpt->dev;
430 
431 	/* Check if we alreay have allocated the reply memory */
432 	if (mpt->reply_phys != 0) {
433 		return 0;
434 	}
435 
436 	len = sizeof (request_t *) * MPT_REQ_MEM_SIZE(mpt);
437 	mpt->request_pool = (request_t *) kmalloc(len, M_DEVBUF, M_WAITOK);
438 	bzero(mpt->request_pool, len);
439 
440 	/*
441 	 * Create a dma tag for this device
442 	 *
443 	 * Align at page boundaries, limit to 32-bit addressing
444 	 * (The chip supports 64-bit addressing, but this driver doesn't)
445 	 */
446 	if (bus_dma_tag_create(NULL, PAGE_SIZE, 0, BUS_SPACE_MAXADDR_32BIT,
447 	    BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT,
448 	    BUS_SPACE_MAXSIZE_32BIT, BUS_SPACE_UNRESTRICTED, 0,
449 	    &mpt->parent_dmat) != 0) {
450 		device_printf(dev, "cannot create parent dma tag\n");
451 		return (1);
452 	}
453 
454 	/* Create a child tag for reply buffers */
455 	if (bus_dma_tag_create(mpt->parent_dmat, PAGE_SIZE,
456 	    0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
457 	    NULL, NULL, PAGE_SIZE, 1, BUS_SPACE_MAXSIZE_32BIT, 0,
458 	    &mpt->reply_dmat) != 0) {
459 		device_printf(dev, "cannot create a dma tag for replies\n");
460 		return (1);
461 	}
462 
463 	/* Allocate some DMA accessable memory for replies */
464 	if (bus_dmamem_alloc(mpt->reply_dmat, (void **)&mpt->reply,
465 	    BUS_DMA_NOWAIT, &mpt->reply_dmap) != 0) {
466 		device_printf(dev, "cannot allocate %d bytes of reply memory\n",
467 		     PAGE_SIZE);
468 		return (1);
469 	}
470 
471 	im.mpt = mpt;
472 	im.error = 0;
473 
474 	/* Load and lock it into "bus space" */
475 	bus_dmamap_load(mpt->reply_dmat, mpt->reply_dmap, mpt->reply,
476 	    PAGE_SIZE, mpt_map_rquest, &im, 0);
477 
478 	if (im.error) {
479 		device_printf(dev,
480 		    "error %d loading dma map for DMA reply queue\n", im.error);
481 		return (1);
482 	}
483 	mpt->reply_phys = im.phys;
484 
485 	/* Create a child tag for data buffers */
486 	if (bus_dma_tag_create(mpt->parent_dmat, PAGE_SIZE,
487 	    0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
488 	    NULL, NULL, MAXBSIZE, MPT_SGL_MAX, BUS_SPACE_MAXSIZE_32BIT, 0,
489 	    &mpt->buffer_dmat) != 0) {
490 		device_printf(dev,
491 		    "cannot create a dma tag for data buffers\n");
492 		return (1);
493 	}
494 
495 	/* Create a child tag for request buffers */
496 	if (bus_dma_tag_create(mpt->parent_dmat, PAGE_SIZE,
497 	    0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
498 	    NULL, NULL, MPT_REQ_MEM_SIZE(mpt), 1, BUS_SPACE_MAXSIZE_32BIT, 0,
499 	    &mpt->request_dmat) != 0) {
500 		device_printf(dev, "cannot create a dma tag for requests\n");
501 		return (1);
502 	}
503 
504 	/* Allocate some DMA accessable memory for requests */
505 	if (bus_dmamem_alloc(mpt->request_dmat, (void **)&mpt->request,
506 	    BUS_DMA_NOWAIT, &mpt->request_dmap) != 0) {
507 		device_printf(dev,
508 		    "cannot allocate %d bytes of request memory\n",
509 		    MPT_REQ_MEM_SIZE(mpt));
510 		return (1);
511 	}
512 
513 	im.mpt = mpt;
514 	im.error = 0;
515 
516 	/* Load and lock it into "bus space" */
517         bus_dmamap_load(mpt->request_dmat, mpt->request_dmap, mpt->request,
518 	    MPT_REQ_MEM_SIZE(mpt), mpt_map_rquest, &im, 0);
519 
520 	if (im.error) {
521 		device_printf(dev,
522 		    "error %d loading dma map for DMA request queue\n",
523 		    im.error);
524 		return (1);
525 	}
526 	mpt->request_phys = im.phys;
527 
528 	i = 0;
529 	pptr =  mpt->request_phys;
530 	vptr =  mpt->request;
531 	end = pptr + MPT_REQ_MEM_SIZE(mpt);
532 	while(pptr < end) {
533 		request_t *req = &mpt->request_pool[i];
534 		req->index = i++;
535 
536 		/* Store location of Request Data */
537 		req->req_pbuf = pptr;
538 		req->req_vbuf = vptr;
539 
540 		pptr += MPT_REQUEST_AREA;
541 		vptr += MPT_REQUEST_AREA;
542 
543 		req->sense_pbuf = (pptr - MPT_SENSE_SIZE);
544 		req->sense_vbuf = (vptr - MPT_SENSE_SIZE);
545 
546 		error = bus_dmamap_create(mpt->buffer_dmat, 0, &req->dmap);
547 		if (error) {
548 			device_printf(dev,
549 			     "error %d creating per-cmd DMA maps\n", error);
550 			return (1);
551 		}
552 	}
553 	return (0);
554 }
555 
556 
557 
558 /* Deallocate memory that was allocated by mpt_dma_mem_alloc
559  */
560 static void
561 mpt_dma_mem_free(mpt_softc_t *mpt)
562 {
563 	int i;
564 
565         /* Make sure we aren't double destroying */
566         if (mpt->reply_dmat == 0) {
567 		if (mpt->verbose)
568 			device_printf(mpt->dev,"Already released dma memory\n");
569 		return;
570         }
571 
572 	for (i = 0; i < MPT_MAX_REQUESTS(mpt); i++) {
573 		bus_dmamap_destroy(mpt->buffer_dmat, mpt->request_pool[i].dmap);
574 	}
575 	bus_dmamap_unload(mpt->request_dmat, mpt->request_dmap);
576 	bus_dmamem_free(mpt->request_dmat, mpt->request, mpt->request_dmap);
577 	bus_dma_tag_destroy(mpt->request_dmat);
578 	bus_dma_tag_destroy(mpt->buffer_dmat);
579 	bus_dmamap_unload(mpt->reply_dmat, mpt->reply_dmap);
580 	bus_dmamem_free(mpt->reply_dmat, mpt->reply, mpt->reply_dmap);
581 	bus_dma_tag_destroy(mpt->reply_dmat);
582 	bus_dma_tag_destroy(mpt->parent_dmat);
583 	mpt->reply_dmat = 0;
584 	kfree(mpt->request_pool, M_DEVBUF);
585 	mpt->request_pool = 0;
586 
587 }
588 
589 
590 
591 /* Reads modifiable (via PCI transactions) config registers */
592 static void
593 mpt_read_config_regs(mpt_softc_t *mpt)
594 {
595 	mpt->pci_cfg.Command = pci_read_config(mpt->dev, PCIR_COMMAND, 2);
596 	mpt->pci_cfg.LatencyTimer_LineSize =
597 	    pci_read_config(mpt->dev, PCIR_CACHELNSZ, 2);
598 	mpt->pci_cfg.IO_BAR = pci_read_config(mpt->dev, PCIR_MAPS, 4);
599 	mpt->pci_cfg.Mem0_BAR[0] = pci_read_config(mpt->dev, PCIR_MAPS+0x4, 4);
600 	mpt->pci_cfg.Mem0_BAR[1] = pci_read_config(mpt->dev, PCIR_MAPS+0x8, 4);
601 	mpt->pci_cfg.Mem1_BAR[0] = pci_read_config(mpt->dev, PCIR_MAPS+0xC, 4);
602 	mpt->pci_cfg.Mem1_BAR[1] = pci_read_config(mpt->dev, PCIR_MAPS+0x10, 4);
603 	mpt->pci_cfg.ROM_BAR = pci_read_config(mpt->dev, PCIR_BIOS, 4);
604 	mpt->pci_cfg.IntLine = pci_read_config(mpt->dev, PCIR_INTLINE, 1);
605 	mpt->pci_cfg.PMCSR = pci_read_config(mpt->dev, 0x44, 4);
606 }
607 
608 /* Sets modifiable config registers */
609 void
610 mpt_set_config_regs(mpt_softc_t *mpt)
611 {
612 	u_int32_t val;
613 
614 #define MPT_CHECK(reg, offset, size)					\
615 	val = pci_read_config(mpt->dev, offset, size);			\
616 	if (mpt->pci_cfg.reg != val) {					\
617 		device_printf(mpt->dev,					\
618 		    "Restoring " #reg " to 0x%X from 0x%X\n",		\
619 		    mpt->pci_cfg.reg, val);				\
620 	}
621 
622 	if (mpt->verbose) {
623 		MPT_CHECK(Command, PCIR_COMMAND, 2);
624 		MPT_CHECK(LatencyTimer_LineSize, PCIR_CACHELNSZ, 2);
625 		MPT_CHECK(IO_BAR, PCIR_MAPS, 4);
626 		MPT_CHECK(Mem0_BAR[0], PCIR_MAPS+0x4, 4);
627 		MPT_CHECK(Mem0_BAR[1], PCIR_MAPS+0x8, 4);
628 		MPT_CHECK(Mem1_BAR[0], PCIR_MAPS+0xC, 4);
629 		MPT_CHECK(Mem1_BAR[1], PCIR_MAPS+0x10, 4);
630 		MPT_CHECK(ROM_BAR, PCIR_BIOS, 4);
631 		MPT_CHECK(IntLine, PCIR_INTLINE, 1);
632 		MPT_CHECK(PMCSR, 0x44, 4);
633 	}
634 #undef MPT_CHECK
635 
636 	pci_write_config(mpt->dev, PCIR_COMMAND, mpt->pci_cfg.Command, 2);
637 	pci_write_config(mpt->dev, PCIR_CACHELNSZ,
638 	    mpt->pci_cfg.LatencyTimer_LineSize, 2);
639 	pci_write_config(mpt->dev, PCIR_MAPS, mpt->pci_cfg.IO_BAR, 4);
640 	pci_write_config(mpt->dev, PCIR_MAPS+0x4, mpt->pci_cfg.Mem0_BAR[0], 4);
641 	pci_write_config(mpt->dev, PCIR_MAPS+0x8, mpt->pci_cfg.Mem0_BAR[1], 4);
642 	pci_write_config(mpt->dev, PCIR_MAPS+0xC, mpt->pci_cfg.Mem1_BAR[0], 4);
643 	pci_write_config(mpt->dev, PCIR_MAPS+0x10, mpt->pci_cfg.Mem1_BAR[1], 4);
644 	pci_write_config(mpt->dev, PCIR_BIOS, mpt->pci_cfg.ROM_BAR, 4);
645 	pci_write_config(mpt->dev, PCIR_INTLINE, mpt->pci_cfg.IntLine, 1);
646 	pci_write_config(mpt->dev, 0x44, mpt->pci_cfg.PMCSR, 4);
647 }
648 
649 static void
650 mpt_pci_intr(void *arg)
651 {
652 	mpt_softc_t *mpt = arg;
653 	MPT_LOCK(mpt);
654 	(void) mpt_intr(mpt);
655 	MPT_UNLOCK(mpt);
656 }
657