1 /**	$MirOS: src/sys/dev/ic/mpt_openbsd.c,v 1.2 2005/03/06 21:27:40 tg Exp $ */
2 /*	$OpenBSD: mpt_openbsd.c,v 1.11 2004/04/28 01:45:48 marco Exp $	*/
3 /*	$NetBSD: mpt_netbsd.c,v 1.7 2003/07/14 15:47:11 lukem Exp $	*/
4 
5 /*
6  * Copyright (c) 2004 Milos Urbanek
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  */
25 
26 /*
27  * Copyright (c) 2003 Wasabi Systems, Inc.
28  * All rights reserved.
29  *
30  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
31  *
32  * Redistribution and use in source and binary forms, with or without
33  * modification, are permitted provided that the following conditions
34  * are met:
35  * 1. Redistributions of source code must retain the above copyright
36  *    notice, this list of conditions and the following disclaimer.
37  * 2. Redistributions in binary form must reproduce the above copyright
38  *    notice, this list of conditions and the following disclaimer in the
39  *    documentation and/or other materials provided with the distribution.
40  * 3. All advertising materials mentioning features or use of this software
41  *    must display the following acknowledgement:
42  *	This product includes software developed for the NetBSD Project by
43  *	Wasabi Systems, Inc.
44  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
45  *    or promote products derived from this software without specific prior
46  *    written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
50  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
51  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
52  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58  * POSSIBILITY OF SUCH DAMAGE.
59  */
60 
61 /*
62  * Copyright (c) 2000, 2001 by Greg Ansley
63  * Partially derived from Matt Jacob's ISP driver.
64  *
65  * Redistribution and use in source and binary forms, with or without
66  * modification, are permitted provided that the following conditions
67  * are met:
68  * 1. Redistributions of source code must retain the above copyright
69  *    notice immediately at the beginning of the file, without modification,
70  *    this list of conditions, and the following disclaimer.
71  * 2. The name of the author may not be used to endorse or promote products
72  *    derived from this software without specific prior written permission.
73  *
74  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
75  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
76  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
77  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
78  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
79  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
80  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
81  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
82  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
83  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
84  * SUCH DAMAGE.
85  */
86 /*
87  * Additional Copyright (c) 2002 by Matthew Jacob under same license.
88  */
89 
90 /*
91  * mpt_openbsd.c:
92  *
93  * OpenBSD-specific routines for LSI Fusion adapters.  Includes some
94  * bus_dma glue, and SCSI glue.
95  *
96  * Adapted from the NetBSD "mpt" driver by Milos Urbanek for
97  * ZOOM International, s.r.o.
98  */
99 
100 #include <sys/cdefs.h>
101 /* __KERNEL_RCSID(0, "$NetBSD: mpt_netbsd.c,v 1.7 2003/07/14 15:47:11 lukem Exp $"); */
102 
103 #include <dev/ic/mpt.h>			/* pulls in all headers */
104 
105 static void	mpt_run_ppr(mpt_softc_t *);
106 static int	mpt_ppr(mpt_softc_t *, struct scsi_link *, int speed);
107 static int	mpt_poll(mpt_softc_t *, struct scsi_xfer *, int);
108 static void	mpt_timeout(void *);
109 static void	mpt_done(mpt_softc_t *, uint32_t);
110 static int	mpt_run_xfer(mpt_softc_t *, struct scsi_xfer *);
111 static void	mpt_check_xfer_settings(mpt_softc_t *, struct scsi_xfer *, MSG_SCSI_IO_REQUEST *);
112 static void	mpt_ctlop(mpt_softc_t *, void *vmsg, uint32_t);
113 static void	mpt_event_notify_reply(mpt_softc_t *, MSG_EVENT_NOTIFY_REPLY *);
114 
115 static int	mpt_action(struct scsi_xfer *);
116 static void	mpt_minphys(struct buf *);
117 
118 struct cfdriver mpt_cd = {
119 	NULL, "mpt", DV_DULL
120 };
121 
122 /* the below structure is so we have a default dev struct for our link struct */
123 static struct scsi_device mpt_dev =
124 {
125 	NULL, /* Use default error handler */
126 	NULL, /* have a queue, served by this */
127 	NULL, /* have no async handler */
128 	NULL, /* Use default 'done' routine */
129 };
130 
131 enum mpt_scsi_speed { U320, U160, U80 };
132 
133 /*
134  * try speed and
135  * return 0 if failed
136  * return 1 if passed
137  */
138 int
mpt_ppr(mpt_softc_t * mpt,struct scsi_link * sc_link,int speed)139 mpt_ppr(mpt_softc_t *mpt, struct scsi_link *sc_link, int speed)
140 {
141 	fCONFIG_PAGE_SCSI_DEVICE_0 page0;
142 	fCONFIG_PAGE_SCSI_DEVICE_1 page1;
143         struct scsi_inquiry scsi_cmd;
144 	uint8_t tp;
145 	int error;
146 	struct scsi_inquiry_data inqbuf;
147 
148 	if (mpt->verbose > 1) {
149 		mpt_prt(mpt, "Entering PPR");
150 	}
151 
152 	if (mpt->is_fc) {
153 		/*
154 		 * SCSI transport settings don't make any sense for
155 		 * Fibre Channel; silently ignore the request.
156 		 */
157 		return 1; /* success */
158 	}
159 
160 	/*
161 	 * Always allow disconnect; we don't have a way to disable
162 	 * it right now, in any case.
163 	 */
164 	mpt->mpt_disc_enable |= (1 << sc_link->target);
165 
166 	/*
167 	 * Enable tagged queueing.
168 	 */
169 	if (sc_link->quirks & SDEV_NOTAGS)
170 		mpt->mpt_tag_enable &= ~(1 << sc_link->target);
171 	else
172 		mpt->mpt_tag_enable |= (1 << sc_link->target);
173 
174 	page1 = mpt->mpt_dev_page1[sc_link->target];
175 
176 	/*
177 	 * Set the wide/narrow parameter for the target.
178 	 */
179 	if (sc_link->quirks & SDEV_NOWIDE)
180 		page1.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_WIDE;
181 	else {
182 		page1.RequestedParameters |= MPI_SCSIDEVPAGE1_RP_WIDE;
183 	}
184 
185 	/*
186 	 * Set the synchronous parameters for the target.
187 	 */
188 	page1.RequestedParameters &= ~(MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK |
189 	    MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK |
190 	    MPI_SCSIDEVPAGE1_RP_DT | MPI_SCSIDEVPAGE1_RP_QAS |
191 	    MPI_SCSIDEVPAGE1_RP_IU);
192 	if (!(sc_link->quirks & SDEV_NOSYNC)) {
193 		int factor, offset, np;
194 
195 		/*
196 		 * Factor:
197 		 * 0x08 = U320 = 6.25ns
198 		 * 0x09 = U160 = 12.5ns
199 		 * 0x0a = U80 = 25ns
200 		 */
201 		factor = (mpt->mpt_port_page0.Capabilities >> 8) & 0xff;
202 		offset = (mpt->mpt_port_page0.Capabilities >> 16) & 0xff;
203 		np = 0;
204 
205 		switch (speed) {
206 			case U320:
207 				/* do nothing */
208 				break;
209 
210 			case U160:
211 				factor = 0x09; /* force U160 */
212 				break;
213 
214 			case U80:
215 				factor = 0x0a; /* force U80 */
216 		}
217 
218 		if (factor < 0x9) {
219 			/* Ultra320 enable QAS & IU */
220 			np |= MPI_SCSIDEVPAGE1_RP_QAS | MPI_SCSIDEVPAGE1_RP_IU;
221 		}
222 		if (factor < 0xa) {
223 			/* >= Ultra160 enable DT transfer */
224 			np |= MPI_SCSIDEVPAGE1_RP_DT;
225 		}
226 		np |= (factor << 8) | (offset << 16);
227 		page1.RequestedParameters |= np;
228 	}
229 
230 	/* write parameters out to chip */
231 	if (mpt_write_cfg_page(mpt, sc_link->target, &page1.Header)) {
232 		mpt_prt(mpt, "unable to write Device Page 1");
233 		return 0;
234 	}
235 
236 	/* make sure the parameters were written */
237 	if (mpt_read_cfg_page(mpt, sc_link->target, &page1.Header)) {
238 		mpt_prt(mpt, "unable to read back Device Page 1");
239 		return 0;
240 	}
241 
242 	mpt->mpt_dev_page1[sc_link->target] = page1;
243 	if (mpt->verbose > 1) {
244 		mpt_prt(mpt,
245 		    "SPI Target %d Page 1: RequestedParameters %x Config %x",
246 		    sc_link->target,
247 		    mpt->mpt_dev_page1[sc_link->target].RequestedParameters,
248 		    mpt->mpt_dev_page1[sc_link->target].Configuration);
249 	}
250 
251 	/*
252 	 * use INQUIRY for PPR two reasons:
253 	 * 1) actually transfer data at requested speed
254 	 * 2) no need to test for TUR QUIRK
255 	 */
256 	bzero(&scsi_cmd, sizeof scsi_cmd);
257 	scsi_cmd.opcode = INQUIRY;
258 	bzero(&inqbuf, sizeof inqbuf);
259 	/*
260 	 * Ask only for a minimal amount of data, since we only want to
261 	 * test data xfer not read all the INQUIRY data.
262 	 */
263 	scsi_cmd.length = SID_INQUIRY_HDR + SID_SCSI2_ALEN;
264 	error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
265 		sizeof(scsi_cmd), (u_char *)&inqbuf, scsi_cmd.length, 0, 10000, NULL,
266 		SCSI_DATA_IN);
267 	if (error) {
268 		mpt_prt(mpt, "Invalid INQUIRY on target: %d", sc_link->target);
269 		return 0;
270 	}
271 
272 	/* read page 0 back to figure out if the PPR worked */
273         page0 = mpt->mpt_dev_page0[sc_link->target];
274         if (mpt_read_cfg_page(mpt, sc_link->target, &page0.Header)) {
275                 mpt_prt(mpt, "unable to read Device Page 0");
276                 return 0;
277         }
278 
279         if (mpt->verbose > 1) {
280                 mpt_prt(mpt,
281                     "SPI Tgt %d Page 0: NParms %x Information %x",
282                     sc_link->target,
283                     page0.NegotiatedParameters, page0.Information);
284         }
285 
286 	if (!(page0.NegotiatedParameters & 0x07) && (speed == U320)) {
287 		/* if lowest 3 aren't set the PPR probably failed, retry with other parameters */
288         	if (mpt->verbose > 1) {
289 			mpt_prt(mpt, "U320 PPR failed");
290 		}
291 		return 0;
292 	}
293 
294 	if ((((page0.NegotiatedParameters >> 8) & 0xff) > 0x09) && (speed == U160)) {
295 		/* if transfer period > 0x09 then U160 PPR failed, retry */
296         	if (mpt->verbose > 1) {
297 			mpt_prt(mpt, "U160 PPR failed");
298 		}
299 		return 0;
300 	}
301 
302 	/*
303 	 * Bit 3 - PPR rejected: The IOC sets this bit if the device rejects a PPR message.
304 	 * Bit 2 - WDTR Rejected: The IOC sets this bit if the device rejects a WDTR message.
305 	 * Bit 1 - SDTR Rejected: The IOC sets this bit if the device rejects a SDTR message.
306 	 * Bit 0 - 1 A SCSI SDTR, WDTR, or PPR negotiation has occurred with this device.
307 	 */
308 	if (page0.Information & 0x0e) {
309 		/* target rejected PPR message */
310 		mpt_prt(mpt, "Target %d rejected PPR message with %02x",
311 			sc_link->target,
312 			(uint8_t)page0.Information);
313 		return 0;
314 	}
315 
316 	/* print PPR results */
317 	switch ((page0.NegotiatedParameters >> 8) & 0xff) {
318 		case 0x08:
319 			tp = 160;
320 			break;
321 
322 		case 0x09:
323 			tp = 80;
324 			break;
325 
326 		case 0x0a:
327 			tp = 40;
328 			break;
329 
330 		case 0x0b:
331 			tp = 20;
332 			break;
333 
334 		case 0x0c:
335 			tp = 10;
336 			break;
337 
338 		default:
339 			tp = 0;
340 	}
341 
342 	mpt_prt(mpt,
343 		"target %d %s at %dMHz width %dbit offset %d QAS %d DT %d IU %d",
344 		sc_link->target,
345 		tp ? "Synchronous" : "Asynchronous",
346 		tp,
347 		(page0.NegotiatedParameters & 0x20000000) ? 16 : 8,
348 		(page0.NegotiatedParameters >> 16) & 0xff,
349 		(page0.NegotiatedParameters & 0x04) ? 1 : 0,
350 		(page0.NegotiatedParameters & 0x02) ? 1 : 0,
351 		(page0.NegotiatedParameters & 0x01) ? 1 : 0);
352 
353 	return 1; /* success */
354 }
355 
356 /*
357  * Run PPR on all attached devices
358  */
359 void
mpt_run_ppr(mpt_softc_t * mpt)360 mpt_run_ppr(mpt_softc_t *mpt)
361 {
362 	struct scsi_link *sc_link;
363 	struct device *dev;
364 	u_int8_t target;
365 	u_int16_t buswidth;
366 
367 	/* walk device list */
368 	for (dev = TAILQ_FIRST(&alldevs); dev != NULL;
369 	    dev = TAILQ_NEXT(dev, dv_list)) {
370 		if (dev->dv_parent == (struct device *)mpt) {
371 			/* found scsibus softc */
372 			buswidth = ((struct scsi_link *)&mpt->sc_link)->adapter_buswidth;
373 			/* printf("mpt_softc: %x  scsibus: %x  buswidth: %d\n",
374 				mpt, dev, buswidth); */
375 			/* walk target list */
376 			for (target = 0; target < buswidth; target++) {
377 				sc_link = ((struct scsibus_softc *)dev)->sc_link[target][0];
378 				if ((sc_link != NULL)) {
379 				/* got a device! run PPR */
380 					/* FIXME: skip CPU devices since they can
381 					 * crash at U320 speeds */
382 					/*if (device == cpu) {
383 						continue;
384 					}*/
385 					if (mpt_ppr(mpt, sc_link, U320)) {
386 						mpt->mpt_negotiated_speed[target] = U320;
387 						continue;
388 					}
389 
390 					if (mpt_ppr(mpt, sc_link, U160)) {
391 						mpt->mpt_negotiated_speed[target] = U160;
392 						continue;
393 					}
394 
395 					if (mpt_ppr(mpt, sc_link, U80)) {
396 						mpt->mpt_negotiated_speed[target] = U80;
397 						continue;
398 					}
399 
400 				} /* sc_link */
401 			} /* for target */
402 		} /* if dev */
403 	} /* end for dev */
404 }
405 
406 /*
407  * Complete attachment of hardware, include subdevices.
408  */
409 void
mpt_attach(mpt_softc_t * mpt)410 mpt_attach(mpt_softc_t *mpt)
411 {
412 	struct scsi_link *lptr = &mpt->sc_link;
413 
414 	mpt->bus = 0;		/* XXX ?? */
415 
416 	/* Fill in the scsi_adapter. */
417 	mpt->sc_adapter.scsi_cmd = mpt_action;
418 	mpt->sc_adapter.scsi_minphys = mpt_minphys;
419 
420 	/* Fill in the prototype scsi_link */
421 	lptr->adapter_softc = mpt;
422 	lptr->device = &mpt_dev;
423 	lptr->adapter = &mpt->sc_adapter;
424 	lptr->flags = 0;
425 	lptr->luns = 8;
426 
427 	if (mpt->is_fc) {
428 		lptr->adapter_buswidth = 256;
429 		lptr->adapter_target = 256;
430 	} else {
431 		lptr->adapter_buswidth = 16;
432 		lptr->adapter_target = mpt->mpt_ini_id;
433 	}
434 	lptr->openings = MPT_MAX_REQUESTS(mpt) / lptr->adapter_buswidth;
435 
436 #ifdef MPT_DEBUG
437 	mpt->verbose = 2;
438 #endif
439 	(void) config_found(&mpt->mpt_dev, lptr, scsiprint);
440 
441 	/* done attaching now walk targets and PPR them */
442 	/* FC does not do PPR */
443 	if (!mpt->is_fc) {
444 		mpt_run_ppr(mpt);
445 	}
446 }
447 
448 int
mpt_dma_mem_alloc(mpt_softc_t * mpt)449 mpt_dma_mem_alloc(mpt_softc_t *mpt)
450 {
451 	bus_dma_segment_t reply_seg, request_seg;
452 	int reply_rseg, request_rseg;
453 	bus_addr_t pptr, end;
454 	caddr_t vptr;
455 	size_t len;
456 	int error, i;
457 
458 	/* Check if we have already allocated the reply memory. */
459 	if (mpt->reply != NULL)
460 		return (0);
461 
462 	/*
463 	 * Allocate the request pool.  This isn't really DMA'd memory,
464 	 * but it's a convenient place to do it.
465 	 */
466 	len = sizeof(request_t) * MPT_MAX_REQUESTS(mpt);
467 	mpt->request_pool = malloc(len, M_DEVBUF, M_WAITOK);
468 	if (mpt->request_pool == NULL) {
469 		printf("%s: unable to allocate request pool\n",
470 		    mpt->mpt_dev.dv_xname);
471 		return (ENOMEM);
472 	}
473 	bzero(mpt->request_pool, len);
474 	/*
475 	 * Allocate DMA resources for reply buffers.
476 	 */
477 	error = bus_dmamem_alloc(mpt->sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
478 	    &reply_seg, 1, &reply_rseg, 0);
479 	if (error) {
480 		printf("%s: unable to allocate reply area, error = %d\n",
481 		    mpt->mpt_dev.dv_xname, error);
482 		goto fail_0;
483 	}
484 
485 	error = bus_dmamem_map(mpt->sc_dmat, &reply_seg, reply_rseg, PAGE_SIZE,
486 	    (caddr_t *) &mpt->reply, BUS_DMA_COHERENT/*XXX*/);
487 	if (error) {
488 		printf("%s: unable to map reply area, error = %d\n",
489 		    mpt->mpt_dev.dv_xname, error);
490 		goto fail_1;
491 	}
492 
493 	error = bus_dmamap_create(mpt->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE,
494 	    0, 0, &mpt->reply_dmap);
495 	if (error) {
496 		printf("%s: unable to create reply DMA map, error = %d\n",
497 		    mpt->mpt_dev.dv_xname, error);
498 		goto fail_2;
499 	}
500 
501 	error = bus_dmamap_load(mpt->sc_dmat, mpt->reply_dmap, mpt->reply,
502 	    PAGE_SIZE, NULL, 0);
503 	if (error) {
504 		printf("%s: unable to load reply DMA map, error = %d\n",
505 		    mpt->mpt_dev.dv_xname, error);
506 		goto fail_3;
507 	}
508 	mpt->reply_phys = mpt->reply_dmap->dm_segs[0].ds_addr;
509 
510 	/*
511 	 * Allocate DMA resources for request buffers.
512 	 */
513 	error = bus_dmamem_alloc(mpt->sc_dmat, MPT_REQ_MEM_SIZE(mpt),
514 	    PAGE_SIZE, 0, &request_seg, 1, &request_rseg, 0);
515 	if (error) {
516 		printf("%s: unable to allocate request area, error = %d\n",
517 		    mpt->mpt_dev.dv_xname, error);
518 		goto fail_4;
519 	}
520 
521 	error = bus_dmamem_map(mpt->sc_dmat, &request_seg, request_rseg,
522 	    MPT_REQ_MEM_SIZE(mpt), (caddr_t *) &mpt->request, 0);
523 	if (error) {
524 		printf("%s: unable to map request area, error = %d\n",
525 		    mpt->mpt_dev.dv_xname, error);
526 		goto fail_5;
527 	}
528 
529 	error = bus_dmamap_create(mpt->sc_dmat, MPT_REQ_MEM_SIZE(mpt), 1,
530 	    MPT_REQ_MEM_SIZE(mpt), 0, 0, &mpt->request_dmap);
531 	if (error) {
532 		printf("%s: unable to create request DMA map, error = %d\n",
533 		    mpt->mpt_dev.dv_xname, error);
534 		goto fail_6;
535 	}
536 
537 	error = bus_dmamap_load(mpt->sc_dmat, mpt->request_dmap, mpt->request,
538 	    MPT_REQ_MEM_SIZE(mpt), NULL, 0);
539 	if (error) {
540 		printf("%s: unable to load request DMA map, error = %d\n",
541 		    mpt->mpt_dev.dv_xname, error);
542 		goto fail_7;
543 	}
544 	mpt->request_phys = mpt->request_dmap->dm_segs[0].ds_addr;
545 
546 	pptr = mpt->request_phys;
547 	vptr = (caddr_t) mpt->request;
548 	end = pptr + MPT_REQ_MEM_SIZE(mpt);
549 
550 	for (i = 0; pptr < end; i++) {
551 		request_t *req = &mpt->request_pool[i];
552 		req->index = i;
553 
554 		/* Store location of Request Data */
555 		req->req_pbuf = pptr;
556 		req->req_vbuf = vptr;
557 
558 		pptr += MPT_REQUEST_AREA;
559 		vptr += MPT_REQUEST_AREA;
560 
561 		req->sense_pbuf = (pptr - MPT_SENSE_SIZE);
562 		req->sense_vbuf = (vptr - MPT_SENSE_SIZE);
563 
564 		error = bus_dmamap_create(mpt->sc_dmat, MAXPHYS,
565 		    MPT_SGL_MAX, MAXPHYS, 0, 0, &req->dmap);
566 		if (error) {
567 			printf("%s: unable to create req %d DMA map, error = "
568 			    "%d", mpt->mpt_dev.dv_xname, i, error);
569 			goto fail_8;
570 		}
571 	}
572 
573 	return (0);
574 
575  fail_8:
576 	for (--i; i >= 0; i--) {
577 		request_t *req = &mpt->request_pool[i];
578 		if (req->dmap != NULL)
579 			bus_dmamap_destroy(mpt->sc_dmat, req->dmap);
580 	}
581 	bus_dmamap_unload(mpt->sc_dmat, mpt->request_dmap);
582  fail_7:
583 	bus_dmamap_destroy(mpt->sc_dmat, mpt->request_dmap);
584  fail_6:
585 	bus_dmamem_unmap(mpt->sc_dmat, (caddr_t)mpt->request, PAGE_SIZE);
586  fail_5:
587 	bus_dmamem_free(mpt->sc_dmat, &request_seg, request_rseg);
588  fail_4:
589 	bus_dmamap_unload(mpt->sc_dmat, mpt->reply_dmap);
590  fail_3:
591 	bus_dmamap_destroy(mpt->sc_dmat, mpt->reply_dmap);
592  fail_2:
593 	bus_dmamem_unmap(mpt->sc_dmat, (caddr_t)mpt->reply, PAGE_SIZE);
594  fail_1:
595 	bus_dmamem_free(mpt->sc_dmat, &reply_seg, reply_rseg);
596  fail_0:
597 	free(mpt->request_pool, M_DEVBUF);
598 
599 	mpt->reply = NULL;
600 	mpt->request = NULL;
601 	mpt->request_pool = NULL;
602 
603 	return (error);
604 }
605 
606 int
mpt_intr(void * arg)607 mpt_intr(void *arg)
608 {
609 	mpt_softc_t *mpt = arg;
610 	int nrepl = 0;
611 	uint32_t reply;
612 
613 	/*
614 	if ((mpt_read(mpt, MPT_OFFSET_INTR_STATUS) & MPT_INTR_REPLY_READY) == 0)
615 		return (0);
616 	*/
617 
618 	/*
619 	 * Speed up trick to save one PCI read.
620 	 * Reply FIFO replies 0xffffffff whenever
621 	 * MPT_OFFSET_INTR_STATUS & MPT_INTR_REPLY_READY == 0
622 	 *
623 	 */
624 
625 	reply = mpt_pop_reply_queue(mpt);
626 
627 	if (reply == 0xffffffff) {
628 		/* check doorbell, this is error path not IO path */
629 		/* FIXME for now ignore strays and doorbells */
630 		return (0);
631 	}
632 
633 	while (reply != MPT_REPLY_EMPTY) {
634 		nrepl++;
635 		if (mpt->verbose > 1) {
636 			if ((reply & MPT_CONTEXT_REPLY) != 0) {
637 				/* Address reply; IOC has something to say */
638 				mpt_print_reply(MPT_REPLY_PTOV(mpt, reply));
639 			} else {
640 				/* Context reply; all went well */
641 				mpt_prt(mpt, "context %u reply OK", reply);
642 			}
643 		}
644 		mpt_done(mpt, reply);
645 		reply = mpt_pop_reply_queue(mpt);
646 	}
647 	return (nrepl != 0);
648 }
649 
650 void
mpt_prt(mpt_softc_t * mpt,const char * fmt,...)651 mpt_prt(mpt_softc_t *mpt, const char *fmt, ...)
652 {
653 	va_list ap;
654 
655 	printf("%s: ", mpt->mpt_dev.dv_xname);
656 	va_start(ap, fmt);
657 	vprintf(fmt, ap);
658 	va_end(ap);
659 	printf("\n");
660 }
661 
662 static int
mpt_poll(mpt_softc_t * mpt,struct scsi_xfer * xs,int count)663 mpt_poll(mpt_softc_t *mpt, struct scsi_xfer *xs, int count)
664 {
665 
666 	/* Timeouts are in msec, so we loop in 1000usec cycles */
667 	while (count) {
668 		mpt_intr(mpt);
669 		if (xs->flags & ITSDONE) {
670 			return (0);
671 		}
672 		delay(1000);		/* only happens in boot, so ok */
673 		count--;
674 	}
675 	return (1);
676 }
677 
678 static void
mpt_timeout(void * arg)679 mpt_timeout(void *arg)
680 {
681 	request_t *req = arg;
682 	struct scsi_xfer *xs = req->xfer;
683 	struct scsi_link *linkp = xs->sc_link;
684 	mpt_softc_t *mpt = (void *) linkp->adapter_softc;
685 	uint32_t oseq;
686 	int s, index;
687 
688 	mpt_prt(mpt, "command timeout");
689 	sc_print_addr(linkp);
690 
691 	s = splbio();
692 
693 	oseq = req->sequence;
694 	mpt->timeouts++;
695 	if (mpt_intr(mpt)) {
696 		if (req->sequence != oseq) {
697 			mpt_prt(mpt, "recovered from command timeout");
698 			splx(s);
699 			return;
700 		}
701 	}
702 	mpt_prt(mpt,
703 	    "timeout on request index = 0x%x, seq = 0x%08x",
704 	    req->index, req->sequence);
705 	mpt_check_doorbell(mpt);
706 	mpt_prt(mpt, "Status 0x%08x, Mask 0x%08x, Doorbell 0x%08x",
707 	    mpt_read(mpt, MPT_OFFSET_INTR_STATUS),
708 	    mpt_read(mpt, MPT_OFFSET_INTR_MASK),
709 	    mpt_read(mpt, MPT_OFFSET_DOORBELL));
710 	mpt_prt(mpt, "request state: %s", mpt_req_state(req->debug));
711 	if (mpt->verbose > 1)
712 		mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);
713 
714 	for(index = 0; index < MPT_MAX_REQUESTS(mpt); index++)
715 		if (req == &mpt->request_pool[index]) {
716 			req->debug = REQ_TIMEOUT;
717 			break;
718 		}
719 
720 	mpt_done(mpt, index);
721 
722 	splx(s);
723 }
724 
725 static void
mpt_done(mpt_softc_t * mpt,uint32_t reply)726 mpt_done(mpt_softc_t *mpt, uint32_t reply)
727 {
728 	struct scsi_xfer *xs = NULL;
729 	struct scsi_link *linkp;
730 	int index;
731 	request_t *req;
732 	MSG_REQUEST_HEADER *mpt_req;
733 	MSG_SCSI_IO_REPLY *mpt_reply;
734 
735 
736 	if ((reply & MPT_CONTEXT_REPLY) == 0) {
737 		/* context reply (ok) */
738 		mpt_reply = NULL;
739 		index = reply & MPT_CONTEXT_MASK;
740 	} else {
741 		/* address reply (error) */
742 
743 		/* XXX BUS_DMASYNC_POSTREAD XXX */
744 		mpt_reply = MPT_REPLY_PTOV(mpt, reply);
745 		if (mpt->verbose > 1) {
746 			uint32_t *pReply = (uint32_t *) mpt_reply;
747 
748 			mpt_prt(mpt, "Address Reply (index %u):",
749 			    mpt_reply->MsgContext & 0xffff);
750 			mpt_prt(mpt, "%08x %08x %08x %08x",
751 			    pReply[0], pReply[1], pReply[2], pReply[3]);
752 			mpt_prt(mpt, "%08x %08x %08x %08x",
753 			    pReply[4], pReply[5], pReply[6], pReply[7]);
754 			mpt_prt(mpt, "%08x %08x %08x %08x",
755 			    pReply[8], pReply[9], pReply[10], pReply[11]);
756 		}
757 		index = mpt_reply->MsgContext;
758 	}
759 
760 	/*
761 	 * Address reply with MessageContext high bit set.
762 	 * This is most likely a notify message, so we try
763 	 * to process it, then free it.
764 	 */
765 	if ((index & 0x80000000) != 0) {
766 		if (mpt_reply != NULL)
767 			mpt_ctlop(mpt, mpt_reply, reply);
768 		else
769 			mpt_prt(mpt, "mpt_done: index 0x%x, NULL reply", index);
770 		return;
771 	}
772 
773 	/* Did we end up with a valid index into the table? */
774 	if (index < 0 || index >= MPT_MAX_REQUESTS(mpt)) {
775 		mpt_prt(mpt, "mpt_done: invalid index (0x%x) in reply", index);
776 		return;
777 	}
778 
779 	req = &mpt->request_pool[index];
780 
781 	/* Make sure memory hasn't been trashed. */
782 	if (req->index != index) {
783 		mpt_prt(mpt, "mpt_done: corrupted request_t (0x%x)", index);
784 		return;
785 	}
786 
787 	MPT_SYNC_REQ(mpt, req, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
788 	mpt_req = req->req_vbuf;
789 
790 	/* Short cut for task management replies; nothing more for us to do. */
791 	if (mpt_req->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
792 		if (mpt->verbose > 1)
793 			mpt_prt(mpt, "mpt_done: TASK MGMT");
794 		goto done;
795 	}
796 
797 	if (mpt_req->Function == MPI_FUNCTION_PORT_ENABLE)
798 		goto done;
799 
800 	/*
801 	 * At this point, it had better be a SCSI I/O command, but don't
802 	 * crash if it isn't.
803 	 */
804 	if (mpt_req->Function != MPI_FUNCTION_SCSI_IO_REQUEST) {
805 		if (mpt->verbose > 1)
806 			mpt_prt(mpt, "mpt_done: unknown Function 0x%x (0x%x)",
807 			    mpt_req->Function, index);
808 		goto done;
809 	}
810 
811 	/* Recover scsi_xfer from the request structure. */
812 	xs = req->xfer;
813 
814 	/* Can't have a SCSI command without a scsi_xfer. */
815 	if (xs == NULL) {
816 		mpt_prt(mpt,
817 		    "mpt_done: no scsi_xfer, index = 0x%x, seq = 0x%08x",
818 		    req->index, req->sequence);
819 		mpt_prt(mpt, "request state: %s", mpt_req_state(req->debug));
820 		mpt_prt(mpt, "mpt_request:");
821 		mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);
822 
823 		if (mpt_reply != NULL) {
824 			mpt_prt(mpt, "mpt_reply:");
825 			mpt_print_reply(mpt_reply);
826 		} else {
827 			mpt_prt(mpt, "context reply: 0x%08x", reply);
828 		}
829 		goto done;
830 	}
831 
832 	timeout_del(&xs->stimeout);
833 
834 	linkp = xs->sc_link;
835 
836 	/*
837 	 * If we were a data transfer, unload the map that described
838 	 * the data buffer.
839 	 */
840 	if (xs->datalen != 0) {
841 		bus_dmamap_sync(mpt->sc_dmat, req->dmap, 0,
842 		    req->dmap->dm_mapsize,
843 		    (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD
844 						      : BUS_DMASYNC_POSTWRITE);
845 		bus_dmamap_unload(mpt->sc_dmat, req->dmap);
846 	}
847 
848 	if (req->debug == REQ_TIMEOUT) {
849 		xs->error = XS_TIMEOUT;
850 		xs->status = SCSI_OK;
851 		xs->resid = 0;
852 		goto done;
853 	} else if (mpt_reply == NULL) {
854 		/*
855 		 * Context reply; report that the command was
856 		 * successful!
857 		 *
858 		 * Also report the xfer mode, if necessary.
859 		 */
860 #if 0 /*XXX report xfer mode not impl */
861 		if (mpt->mpt_report_xfer_mode != 0) {
862 			if ((mpt->mpt_report_xfer_mode &
863 			     (1 << periph->periph_target)) != 0)
864 				mpt_get_xfer_mode(mpt, periph);
865 		}
866 #endif
867 		xs->error = XS_NOERROR;
868 		xs->status = SCSI_OK;
869 		xs->resid = 0;
870 		goto done;
871 	}
872 
873 	xs->status = mpt_reply->SCSIStatus;
874 	switch (mpt_reply->IOCStatus) {
875 	case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
876 		xs->error = XS_DRIVER_STUFFUP;
877 		break;
878 
879 	case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
880 		/*
881 		 * Yikes!  Tagged queue full comes through this path!
882 		 *
883 		 * So we'll change it to a status error and anything
884 		 * that returns status should probably be a status
885 		 * error as well.
886 		 */
887 		xs->resid = xs->datalen - mpt_reply->TransferCount;
888 		if (mpt_reply->SCSIState &
889 		    MPI_SCSI_STATE_NO_SCSI_STATUS) {
890 			xs->error = XS_DRIVER_STUFFUP;
891 			break;
892 		}
893 		/* FALLTHROUGH */
894 	case MPI_IOCSTATUS_SUCCESS:
895 	case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:
896 		switch (xs->status) {
897 		case SCSI_OK:
898 #if 0 /* XXX xfer mode */
899 			/* Report the xfer mode, if necessary. */
900 			if ((mpt->mpt_report_xfer_mode &
901 			     (1 << periph->periph_target)) != 0)
902 				mpt_get_xfer_mode(mpt, periph);
903 #endif
904 			xs->resid = 0;
905 			break;
906 
907 		case SCSI_CHECK:
908 			xs->error = XS_SENSE;
909 			break;
910 
911 		case SCSI_BUSY:
912 			xs->error = XS_BUSY;
913 			break;
914 
915 		case SCSI_QUEUE_FULL:
916 			xs->error = XS_TIMEOUT;
917 			xs->retries++;
918 			break;
919 		default:
920 			sc_print_addr(linkp);
921 			mpt_prt(mpt, "invalid status code %d", xs->status);
922 			xs->error = XS_DRIVER_STUFFUP;
923 			break;
924 		}
925 		break;
926 
927 #if 0 /* XS_RESOURCE_SHORTAGE not impl */
928 	case MPI_IOCSTATUS_BUSY:
929 	case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
930 		xs->error = XS_RESOURCE_SHORTAGE;
931 		break;
932 #endif
933 	case MPI_IOCSTATUS_SCSI_INVALID_BUS:
934 	case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
935 	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
936 		xs->error = XS_SELTIMEOUT;
937 		break;
938 
939 	case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
940 		xs->error = XS_DRIVER_STUFFUP;
941 		break;
942 
943 	case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
944 		xs->error = XS_DRIVER_STUFFUP;
945 		break;
946 
947 	case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
948 		/* XXX */
949 		xs->error = XS_DRIVER_STUFFUP;
950 		break;
951 
952 	case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
953 		/* XXX */
954 		xs->error = XS_DRIVER_STUFFUP;
955 		break;
956 
957 	case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
958 		/* XXX This is a bus-reset */
959 		xs->error = XS_DRIVER_STUFFUP;
960 		break;
961 
962 	default:
963 		/* XXX unrecognized HBA error */
964 		xs->error = XS_DRIVER_STUFFUP;
965 		break;
966 	}
967 
968 	if (mpt_reply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
969 		memcpy(&xs->sense, req->sense_vbuf,
970 		    sizeof(xs->sense));
971 	} else if (mpt_reply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
972 		/*
973 		 * This will cause the scsi layer to issue
974 		 * a REQUEST SENSE.
975 		 */
976 		if (xs->status == SCSI_CHECK)
977 			xs->error = XS_BUSY;
978 	}
979 
980  done:
981 	/* If IOC done with this requeset, free it up. */
982 	if (mpt_reply == NULL || (mpt_reply->MsgFlags & 0x80) == 0)
983 		mpt_free_request(mpt, req);
984 
985 	/* If address reply, give the buffer back to the IOC. */
986 	if (mpt_reply != NULL)
987 		mpt_free_reply(mpt, (reply << 1));
988 
989 	if (xs != NULL) {
990 		xs->flags |= ITSDONE;
991 		scsi_done(xs);
992 	}
993 }
994 
995 static int
mpt_run_xfer(mpt_softc_t * mpt,struct scsi_xfer * xs)996 mpt_run_xfer(mpt_softc_t *mpt, struct scsi_xfer *xs)
997 {
998 	struct scsi_link *linkp = xs->sc_link;
999 	request_t *req;
1000 	MSG_SCSI_IO_REQUEST *mpt_req;
1001 	int error, s;
1002 
1003 	s = splbio();
1004 	req = mpt_get_request(mpt);
1005 	if (req == NULL) {
1006 		/* This should happen very infrequently. */
1007 		xs->error = XS_DRIVER_STUFFUP;
1008 		/*
1009 		xs->error = XS_RESOURCE_SHORTAGE;
1010 		*/
1011 		xs->flags |= ITSDONE;
1012 		scsi_done(xs);
1013 		splx(s);
1014 		return (COMPLETE);
1015 	}
1016 	splx(s);
1017 
1018 	/* Link the req and the scsi_xfer. */
1019 	req->xfer = xs;
1020 
1021 	/* Now we build the command for the IOC */
1022 	mpt_req = req->req_vbuf;
1023 	bzero(mpt_req, sizeof(*mpt_req));
1024 
1025 	mpt_req->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1026 	mpt_req->Bus = mpt->bus;
1027 
1028 	mpt_req->SenseBufferLength =
1029 	    (sizeof(xs->sense) < MPT_SENSE_SIZE) ?
1030 	    sizeof(xs->sense) : MPT_SENSE_SIZE;
1031 
1032 	/*
1033 	 * We use the message context to find the request structure when
1034 	 * we get the command completion interrupt from the IOC.
1035 	 */
1036 	mpt_req->MsgContext = req->index;
1037 
1038 	/* Which physical device to do the I/O on. */
1039 	mpt_req->TargetID = linkp->target;
1040 	mpt_req->LUN[1] = linkp->lun;
1041 
1042 	/* Set the direction of the transfer. */
1043 	if (xs->flags & SCSI_DATA_IN)
1044 		mpt_req->Control = MPI_SCSIIO_CONTROL_READ;
1045 	else if (xs->flags & SCSI_DATA_OUT)
1046 		mpt_req->Control = MPI_SCSIIO_CONTROL_WRITE;
1047 	else
1048 		mpt_req->Control = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1049 
1050 	mpt_check_xfer_settings(mpt, xs, mpt_req);
1051 
1052 	/* Copy the SCSI command block into place. */
1053 	memcpy(mpt_req->CDB, xs->cmd, xs->cmdlen);
1054 
1055 	mpt_req->CDBLength = xs->cmdlen;
1056 	mpt_req->DataLength = xs->datalen;
1057 	mpt_req->SenseBufferLowAddr = req->sense_pbuf;
1058 
1059 	/*
1060 	 * Map the DMA transfer.
1061 	 */
1062 	if (xs->datalen) {
1063 		SGE_SIMPLE32 *se;
1064 
1065 		error = bus_dmamap_load(mpt->sc_dmat, req->dmap, xs->data,
1066 		    xs->datalen, NULL,
1067 		    ((xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT
1068 						       : BUS_DMA_WAITOK) |
1069 		    BUS_DMA_STREAMING |
1070 		    ((xs->flags & SCSI_DATA_IN) ? BUS_DMA_READ
1071 						       : BUS_DMA_WRITE));
1072 		switch (error) {
1073 		case 0:
1074 			break;
1075 
1076 		case ENOMEM:
1077 		case EAGAIN:
1078 			xs->error = XS_DRIVER_STUFFUP;
1079 			/* xs->error = XS_RESOURCE_SHORTAGE; */
1080 			goto out_bad;
1081 		default:
1082 			xs->error = XS_DRIVER_STUFFUP;
1083 			mpt_prt(mpt, "error %d loading DMA map", error);
1084  out_bad:
1085 			s = splbio();
1086 			mpt_free_request(mpt, req);
1087 			xs->flags |= ITSDONE;
1088 			scsi_done(xs);
1089 			splx(s);
1090 			return (TRY_AGAIN_LATER);
1091 		}
1092 
1093 		if (req->dmap->dm_nsegs > MPT_NSGL_FIRST(mpt)) {
1094 			int seg, i, nleft = req->dmap->dm_nsegs;
1095 			uint32_t flags;
1096 			SGE_CHAIN32 *ce;
1097 
1098 			seg = 0;
1099 
1100 			mpt_req->DataLength = xs->datalen;
1101 			flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT;
1102 			if (xs->flags & SCSI_DATA_OUT)
1103 				flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
1104 
1105 			se = (SGE_SIMPLE32 *) &mpt_req->SGL;
1106 			for (i = 0; i < MPT_NSGL_FIRST(mpt) - 1;
1107 			     i++, se++, seg++) {
1108 				uint32_t tf;
1109 
1110 				bzero(se, sizeof(*se));
1111 				se->Address = req->dmap->dm_segs[seg].ds_addr;
1112 				MPI_pSGE_SET_LENGTH(se,
1113 				    req->dmap->dm_segs[seg].ds_len);
1114 				tf = flags;
1115 				if (i == MPT_NSGL_FIRST(mpt) - 2)
1116 					tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
1117 				MPI_pSGE_SET_FLAGS(se, tf);
1118 				nleft--;
1119 			}
1120 
1121 			/*
1122 			 * Tell the IOC where to find the first chain element.
1123 			 */
1124 			mpt_req->ChainOffset =
1125 			    ((char *)se - (char *)mpt_req) >> 2;
1126 
1127 			/*
1128 			 * Until we're finished with all segments...
1129 			 */
1130 			while (nleft) {
1131 				int ntodo;
1132 
1133 				/*
1134 				 * Construct the chain element that points to
1135 				 * the next segment.
1136 				 */
1137 				ce = (SGE_CHAIN32 *) se++;
1138 				if (nleft > MPT_NSGL(mpt)) {
1139 					ntodo = MPT_NSGL(mpt) - 1;
1140 					ce->NextChainOffset = (MPT_RQSL(mpt) -
1141 					    sizeof(SGE_SIMPLE32)) >> 2;
1142 					ce->Length = MPT_NSGL(mpt)
1143 						* sizeof(SGE_SIMPLE32);
1144 				} else {
1145 					ntodo = nleft;
1146 					ce->NextChainOffset = 0;
1147 					ce->Length = ntodo
1148 						* sizeof(SGE_SIMPLE32);
1149 				}
1150 				ce->Address = req->req_pbuf +
1151 				    ((char *)se - (char *)mpt_req);
1152 				ce->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
1153 				for (i = 0; i < ntodo; i++, se++, seg++) {
1154 					uint32_t tf;
1155 
1156 					bzero(se, sizeof(*se));
1157 					se->Address =
1158 					    req->dmap->dm_segs[seg].ds_addr;
1159 					MPI_pSGE_SET_LENGTH(se,
1160 					    req->dmap->dm_segs[seg].ds_len);
1161 					tf = flags;
1162 					if (i == ntodo - 1) {
1163 						tf |=
1164 						    MPI_SGE_FLAGS_LAST_ELEMENT;
1165 						if (ce->NextChainOffset == 0) {
1166 							tf |=
1167 						    MPI_SGE_FLAGS_END_OF_LIST |
1168 						    MPI_SGE_FLAGS_END_OF_BUFFER;
1169 						}
1170 					}
1171 					MPI_pSGE_SET_FLAGS(se, tf);
1172 					nleft--;
1173 				}
1174 			}
1175 			bus_dmamap_sync(mpt->sc_dmat, req->dmap, 0,
1176 			    req->dmap->dm_mapsize,
1177 			    (xs->flags & SCSI_DATA_IN) ?
1178 			    				BUS_DMASYNC_PREREAD
1179 						      : BUS_DMASYNC_PREWRITE);
1180 		} else {
1181 			int i;
1182 			uint32_t flags;
1183 
1184 			mpt_req->DataLength = xs->datalen;
1185 			flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT;
1186 			if (xs->flags & SCSI_DATA_OUT)
1187 				flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
1188 
1189 			/* Copy the segments into our SG list. */
1190 			se = (SGE_SIMPLE32 *) &mpt_req->SGL;
1191 			for (i = 0; i < req->dmap->dm_nsegs;
1192 			     i++, se++) {
1193 				uint32_t tf;
1194 
1195 				bzero(se, sizeof(*se));
1196 				se->Address = req->dmap->dm_segs[i].ds_addr;
1197 				MPI_pSGE_SET_LENGTH(se,
1198 				    req->dmap->dm_segs[i].ds_len);
1199 				tf = flags;
1200 				if (i == req->dmap->dm_nsegs - 1) {
1201 					tf |=
1202 					    MPI_SGE_FLAGS_LAST_ELEMENT |
1203 					    MPI_SGE_FLAGS_END_OF_BUFFER |
1204 					    MPI_SGE_FLAGS_END_OF_LIST;
1205 				}
1206 				MPI_pSGE_SET_FLAGS(se, tf);
1207 			}
1208 			bus_dmamap_sync(mpt->sc_dmat, req->dmap, 0,
1209 			    req->dmap->dm_mapsize,
1210 			    (xs->flags & SCSI_DATA_IN) ?
1211 			    				BUS_DMASYNC_PREREAD
1212 						      : BUS_DMASYNC_PREWRITE);
1213 		}
1214 	} else {
1215 		/*
1216 		 * No data to transfer; just make a single simple SGL
1217 		 * with zero length.
1218 		 */
1219 		SGE_SIMPLE32 *se = (SGE_SIMPLE32 *) &mpt_req->SGL;
1220 		bzero(se, sizeof(*se));
1221 		MPI_pSGE_SET_FLAGS(se,
1222 		    (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
1223 		     MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
1224 	}
1225 
1226 	if (mpt->verbose > 1)
1227 		mpt_print_scsi_io_request(mpt_req);
1228 
1229 	s = splbio();
1230 
1231 	/* Always reset xs->stimeout, lest we timeout_del() with trash */
1232 	timeout_set(&xs->stimeout, mpt_timeout, req);
1233 
1234 	if ((xs->flags & SCSI_POLL) == 0)
1235 		timeout_add(&xs->stimeout, mstohz(xs->timeout));
1236 	mpt_send_cmd(mpt, req);
1237 	splx(s);
1238 
1239 	if ((xs->flags & SCSI_POLL) == 0) {
1240 		return (SUCCESSFULLY_QUEUED);
1241 	}
1242 	/*
1243 	 * If we can't use interrupts, poll on completion.
1244 	 */
1245 	if (mpt_poll(mpt, xs, xs->timeout)) {
1246 		mpt_timeout(req);
1247 		/* XXX scsi_done called
1248 		return (TRY_AGAIN_LATER);
1249 		*/
1250 		return (COMPLETE);
1251 	}
1252 
1253 	return (COMPLETE);
1254 }
1255 
1256 static void
mpt_ctlop(mpt_softc_t * mpt,void * vmsg,uint32_t reply)1257 mpt_ctlop(mpt_softc_t *mpt, void *vmsg, uint32_t reply)
1258 {
1259 	MSG_DEFAULT_REPLY *dmsg = vmsg;
1260 
1261 	switch (dmsg->Function) {
1262 	case MPI_FUNCTION_EVENT_NOTIFICATION:
1263 		mpt_event_notify_reply(mpt, vmsg);
1264 		mpt_free_reply(mpt, (reply << 1));
1265 		break;
1266 
1267 	case MPI_FUNCTION_EVENT_ACK:
1268 		mpt_free_reply(mpt, (reply << 1));
1269 		break;
1270 
1271 	case MPI_FUNCTION_PORT_ENABLE:
1272 	    {
1273 		MSG_PORT_ENABLE_REPLY *msg = vmsg;
1274 		int index = msg->MsgContext & ~0x80000000;
1275 		if (mpt->verbose > 1)
1276 			mpt_prt(mpt, "enable port reply index %d", index);
1277 		if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) {
1278 			request_t *req = &mpt->request_pool[index];
1279 			req->debug = REQ_DONE;
1280 		}
1281 		mpt_free_reply(mpt, (reply << 1));
1282 		break;
1283 	    }
1284 
1285 	case MPI_FUNCTION_CONFIG:
1286 	    {
1287 		MSG_CONFIG_REPLY *msg = vmsg;
1288 		int index = msg->MsgContext & ~0x80000000;
1289 		if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) {
1290 			request_t *req = &mpt->request_pool[index];
1291 			req->debug = REQ_DONE;
1292 			req->sequence = reply;
1293 		} else
1294 			mpt_free_reply(mpt, (reply << 1));
1295 		break;
1296 	    }
1297 
1298 	default:
1299 		mpt_prt(mpt, "unknown ctlop: 0x%x", dmsg->Function);
1300 	}
1301 }
1302 
1303 static void
mpt_event_notify_reply(mpt_softc_t * mpt,MSG_EVENT_NOTIFY_REPLY * msg)1304 mpt_event_notify_reply(mpt_softc_t *mpt, MSG_EVENT_NOTIFY_REPLY *msg)
1305 {
1306 
1307 	switch (msg->Event) {
1308 	case MPI_EVENT_LOG_DATA:
1309 	    {
1310 		int i;
1311 
1312 		/* Some error occurrerd that the Fusion wants logged. */
1313 		mpt_prt(mpt, "EvtLogData: IOCLogInfo: 0x%08x", msg->IOCLogInfo);
1314 		mpt_prt(mpt, "EvtLogData: Event Data:");
1315 		for (i = 0; i < msg->EventDataLength; i++) {
1316 			if ((i % 4) == 0)
1317 				printf("%s:\t", mpt->mpt_dev.dv_xname);
1318 			printf("0x%08x%c", msg->Data[i],
1319 			    ((i % 4) == 3) ? '\n' : ' ');
1320 		}
1321 		if ((i % 4) != 0)
1322 			printf("\n");
1323 		break;
1324 	    }
1325 
1326 	case MPI_EVENT_UNIT_ATTENTION:
1327 		mpt_prt(mpt, "Unit Attn: Bus 0x%02x Target 0x%02x",
1328 		    (msg->Data[0] >> 8) & 0xff, msg->Data[0] & 0xff);
1329 		break;
1330 
1331 	case MPI_EVENT_IOC_BUS_RESET:
1332 		/* We generated a bus reset. */
1333 		mpt_prt(mpt, "IOC Bus Reset Port %d",
1334 		    (msg->Data[0] >> 8) & 0xff);
1335 		break;
1336 
1337 	case MPI_EVENT_EXT_BUS_RESET:
1338 		/* Someone else generated a bus reset. */
1339 		mpt_prt(mpt, "External Bus Reset");
1340 		/*
1341 		 * These replies don't return EventData like the MPI
1342 		 * spec says they do.
1343 		 */
1344 		/* XXX Send an async event? */
1345 		break;
1346 
1347 	case MPI_EVENT_RESCAN:
1348 		/*
1349 		 * In general, thise means a device has been added
1350 		 * to the loop.
1351 		 */
1352 		mpt_prt(mpt, "Rescan Port %d", (msg->Data[0] >> 8) & 0xff);
1353 		/* XXX Send an async event? */
1354 		break;
1355 
1356 	case MPI_EVENT_LINK_STATUS_CHANGE:
1357 		mpt_prt(mpt, "Port %d: Link state %s",
1358 		    (msg->Data[1] >> 8) & 0xff,
1359 		    (msg->Data[0] & 0xff) == 0 ? "Failed" : "Active");
1360 		break;
1361 
1362 	case MPI_EVENT_LOOP_STATE_CHANGE:
1363 		switch ((msg->Data[0] >> 16) & 0xff) {
1364 		case 0x01:
1365 			mpt_prt(mpt,
1366 			    "Port %d: FC Link Event: LIP(%02x,%02x) "
1367 			    "(Loop Initialization)",
1368 			    (msg->Data[1] >> 8) & 0xff,
1369 			    (msg->Data[0] >> 8) & 0xff,
1370 			    (msg->Data[0]     ) & 0xff);
1371 			switch ((msg->Data[0] >> 8) & 0xff) {
1372 			case 0xf7:
1373 				if ((msg->Data[0] & 0xff) == 0xf7)
1374 					mpt_prt(mpt, "\tDevice needs AL_PA");
1375 				else
1376 					mpt_prt(mpt, "\tDevice %02x doesn't "
1377 					    "like FC performance",
1378 					    msg->Data[0] & 0xff);
1379 				break;
1380 
1381 			case 0xf8:
1382 				if ((msg->Data[0] & 0xff) == 0xf7)
1383 					mpt_prt(mpt, "\tDevice detected loop "
1384 					    "failure before acquiring AL_PA");
1385 				else
1386 					mpt_prt(mpt, "\tDevice %02x detected "
1387 					    "loop failure",
1388 					    msg->Data[0] & 0xff);
1389 				break;
1390 
1391 			default:
1392 				mpt_prt(mpt, "\tDevice %02x requests that "
1393 				    "device %02x reset itself",
1394 				    msg->Data[0] & 0xff,
1395 				    (msg->Data[0] >> 8) & 0xff);
1396 				break;
1397 			}
1398 			break;
1399 
1400 		case 0x02:
1401 			mpt_prt(mpt, "Port %d: FC Link Event: LPE(%02x,%02x) "
1402 			    "(Loop Port Enable)",
1403 			    (msg->Data[1] >> 8) & 0xff,
1404 			    (msg->Data[0] >> 8) & 0xff,
1405 			    (msg->Data[0]     ) & 0xff);
1406 			break;
1407 
1408 		case 0x03:
1409 			mpt_prt(mpt, "Port %d: FC Link Event: LPB(%02x,%02x) "
1410 			    "(Loop Port Bypass)",
1411 			    (msg->Data[1] >> 8) & 0xff,
1412 			    (msg->Data[0] >> 8) & 0xff,
1413 			    (msg->Data[0]     ) & 0xff);
1414 			break;
1415 
1416 		default:
1417 			mpt_prt(mpt, "Port %d: FC Link Event: "
1418 			    "Unknown event (%02x %02x %02x)",
1419 			    (msg->Data[1] >>  8) & 0xff,
1420 			    (msg->Data[0] >> 16) & 0xff,
1421 			    (msg->Data[0] >>  8) & 0xff,
1422 			    (msg->Data[0]      ) & 0xff);
1423 			break;
1424 		}
1425 		break;
1426 
1427 	case MPI_EVENT_LOGOUT:
1428 		mpt_prt(mpt, "Port %d: FC Logout: N_PortID: %02x",
1429 		    (msg->Data[1] >> 8) & 0xff, msg->Data[0]);
1430 		break;
1431 
1432 	case MPI_EVENT_EVENT_CHANGE:
1433 		/*
1434 		 * This is just an acknowledgement of our
1435 		 * mpt_send_event_request().
1436 		 */
1437 		break;
1438 
1439 	default:
1440 		mpt_prt(mpt, "Unknown async event: 0x%x", msg->Event);
1441 		break;
1442 	}
1443 
1444 	if (msg->AckRequired) {
1445 		MSG_EVENT_ACK *ackp;
1446 		request_t *req;
1447 
1448 		if ((req = mpt_get_request(mpt)) == NULL) {
1449 			/* XXX XXX XXX XXXJRT */
1450 			panic("mpt_event_notify_reply: unable to allocate "
1451 			    "request structure");
1452 		}
1453 
1454 		ackp = (MSG_EVENT_ACK *) req->req_vbuf;
1455 		bzero(ackp, sizeof(*ackp));
1456 		ackp->Function = MPI_FUNCTION_EVENT_ACK;
1457 		ackp->Event = msg->Event;
1458 		ackp->EventContext = msg->EventContext;
1459 		ackp->MsgContext = req->index | 0x80000000;
1460 		mpt_check_doorbell(mpt);
1461 		mpt_send_cmd(mpt, req);
1462 	}
1463 }
1464 
1465 void
mpt_check_xfer_settings(mpt_softc_t * mpt,struct scsi_xfer * xs,MSG_SCSI_IO_REQUEST * mpt_req)1466 mpt_check_xfer_settings(mpt_softc_t *mpt, struct scsi_xfer *xs, MSG_SCSI_IO_REQUEST *mpt_req)
1467 {
1468 	if (mpt->is_fc) {
1469 		/*
1470 		 * SCSI transport settings don't make any sense for
1471 		 * Fibre Channel; silently ignore the request.
1472 		 */
1473 		return;
1474 	}
1475 
1476 	/*
1477 	 * XXX never do these commands with tags. Should really be
1478 	 * in a higher layer.
1479 	 */
1480 	if (xs->cmd->opcode == INQUIRY ||
1481              xs->cmd->opcode == TEST_UNIT_READY ||
1482              xs->cmd->opcode == REQUEST_SENSE)
1483 		return;
1484 
1485 	/* Set the queue behavior. */
1486 	if (mpt->is_fc || (mpt->mpt_tag_enable & (1 << xs->sc_link->target))) {
1487 			mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ;
1488 	} else {
1489 		mpt_req->Control |= MPI_SCSIIO_CONTROL_UNTAGGED;
1490 		mpt_req->Control |= MPI_SCSIIO_CONTROL_NO_DISCONNECT;
1491 	}
1492 #if 0
1493 	if (mpt->is_fc == 0 && (mpt->mpt_disc_enable &
1494 			(1 << linkp->target)) == 0)
1495 		mpt_req->Control |= MPI_SCSIIO_CONTROL_NO_DISCONNECT;
1496 #endif
1497 	return;
1498 }
1499 
1500 /* XXXJRT mpt_bus_reset() */
1501 
1502 /*****************************************************************************
1503  * SCSI interface routines
1504  *****************************************************************************/
1505 
1506 static int
mpt_action(struct scsi_xfer * xfer)1507 mpt_action(struct scsi_xfer *xfer)
1508 {
1509 	mpt_softc_t *mpt = (void *) xfer->sc_link->adapter_softc;
1510 	int ret;
1511 
1512 	ret = mpt_run_xfer(mpt, xfer);
1513 	return ret;
1514 #if 0
1515 	switch (req) {
1516 	case ADAPTER_REQ_RUN_XFER:
1517 		mpt_run_xfer(mpt, (struct scsipi_xfer *) arg);
1518 		return;
1519 
1520 	case ADAPTER_REQ_GROW_RESOURCES:
1521 		/* Not supported. */
1522 		return;
1523 
1524 	case ADAPTER_REQ_SET_XFER_MODE:
1525 		mpt_set_xfer_mode(mpt, (struct scsipi_xfer_mode *) arg);
1526 		return;
1527 	}
1528 #endif
1529 }
1530 
1531 static void
mpt_minphys(struct buf * bp)1532 mpt_minphys(struct buf *bp)
1533 {
1534 
1535 /*
1536  * Subtract one from the SGL limit, since we need an extra one to handle
1537  * an non-page-aligned transfer.
1538  */
1539 #define	MPT_MAX_XFER	((MPT_SGL_MAX - 1) * PAGE_SIZE)
1540 
1541 	if (bp->b_bcount > MPT_MAX_XFER)
1542 		bp->b_bcount = MPT_MAX_XFER;
1543 	minphys(bp);
1544 }
1545 
1546 /*
1547  * Allocate DMA resources for FW image
1548  *
1549  * img_sz : size of image
1550  * maxsgl : maximum number of DMA segments
1551  */
1552 int
mpt_alloc_fw_mem(mpt_softc_t * mpt,uint32_t img_sz,int maxsgl)1553 mpt_alloc_fw_mem(mpt_softc_t *mpt, uint32_t img_sz, int maxsgl)
1554 {
1555 	int error;
1556 
1557 	error = bus_dmamem_alloc(mpt->sc_dmat, img_sz, PAGE_SIZE, 0,
1558 		&mpt->fw_seg, maxsgl, &mpt->fw_rseg, 0);
1559 	if (error) {
1560 	mpt_prt(mpt, "unable to allocate fw memory, error = %d", error);
1561 		goto fw_fail0;
1562 	}
1563 
1564 	error = bus_dmamem_map(mpt->sc_dmat, &mpt->fw_seg, mpt->fw_rseg, img_sz,
1565 		(caddr_t *)&mpt->fw, BUS_DMA_COHERENT);
1566 	if (error) {
1567 		mpt_prt(mpt, "unable to map fw area, error = %d", error);
1568 		goto fw_fail1;
1569 	}
1570 
1571 	error = bus_dmamap_create(mpt->sc_dmat, img_sz, maxsgl, img_sz,
1572 		0, 0, &mpt->fw_dmap);
1573 	if (error) {
1574 		mpt_prt(mpt, "unable to create request DMA map, error = %d",
1575 			error);
1576 		goto fw_fail2;
1577 	}
1578 
1579 	error = bus_dmamap_load(mpt->sc_dmat, mpt->fw_dmap, mpt->fw, img_sz,
1580 		NULL, 0);
1581 	if (error) {
1582 	mpt_prt(mpt, "unable to load request DMA map, error = %d", error);
1583 		goto fw_fail3;
1584 	}
1585 
1586 	return(error);
1587 fw_fail3:
1588 	bus_dmamap_unload(mpt->sc_dmat, mpt->fw_dmap);
1589 fw_fail2:
1590 	bus_dmamap_destroy(mpt->sc_dmat, mpt->fw_dmap);
1591 fw_fail1:
1592 	bus_dmamem_unmap(mpt->sc_dmat, (caddr_t)mpt->fw, img_sz);
1593 fw_fail0:
1594 	bus_dmamem_free(mpt->sc_dmat, &mpt->fw_seg, mpt->fw_rseg);
1595 
1596 	mpt->fw = NULL;
1597 	return (error);
1598 }
1599 
1600 void
mpt_free_fw_mem(mpt_softc_t * mpt)1601 mpt_free_fw_mem(mpt_softc_t *mpt)
1602 {
1603 	bus_dmamap_unload(mpt->sc_dmat, mpt->fw_dmap);
1604 	bus_dmamap_destroy(mpt->sc_dmat, mpt->fw_dmap);
1605 	bus_dmamem_unmap(mpt->sc_dmat, (caddr_t)mpt->fw, mpt->fw_image_size);
1606 	bus_dmamem_free(mpt->sc_dmat, &mpt->fw_seg, mpt->fw_rseg);
1607 }
1608