1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Emulex.  All rights reserved.
24  * Use is subject to License terms.
25  */
26 
27 #include <emlxs.h>
28 
29 EMLXS_MSG_DEF(EMLXS_MEM_C);
30 
31 
32 /*
33  *  emlxs_mem_alloc_buffer
34  *
35  *  This routine will allocate iocb/data buffer
36  *  space and setup the buffers for all rings on
37  *  the specified board to use. The data buffers
38  *  can be posted to the ring with the
39  *  fc_post_buffer routine.  The iocb buffers
40  *  are used to make a temp copy of the response
41  *  ring iocbs. Returns 0 if not enough memory,
42  *  Returns 1 if successful.
43  */
44 
45 
46 extern int32_t
47 emlxs_mem_alloc_buffer(emlxs_hba_t *hba)
48 {
49 	emlxs_port_t *port = &PPORT;
50 	emlxs_config_t *cfg;
51 	MBUF_INFO *buf_info;
52 	uint8_t *bp;
53 	uint8_t *oldbp;
54 	MEMSEG *mp;
55 	MATCHMAP *matp;
56 	NODELIST *ndlp;
57 	IOCBQ *iocbq;
58 	MAILBOXQ *mbox;
59 	MBUF_INFO bufinfo;
60 	int32_t i;
61 	RING *fcp_rp;
62 	RING *ip_rp;
63 	RING *els_rp;
64 	RING *ct_rp;
65 	uint32_t total_iotags;
66 #ifdef EMLXS_SPARC
67 	int32_t j;
68 	ULP_BDE64 *p_bpl;
69 	ULP_BDE64 *v_bpl;
70 #endif	/* EMLXS_SPARC */
71 
72 	buf_info = &bufinfo;
73 	cfg = &CFG;
74 
75 	mutex_enter(&EMLXS_MEMGET_LOCK);
76 
77 	/*
78 	 * Allocate and Initialize MEM_NLP (0)
79 	 */
80 	mp = &hba->memseg[MEM_NLP];
81 	mp->fc_memsize = sizeof (NODELIST);
82 	mp->fc_numblks = (int16_t)hba->max_nodes + 2;
83 	mp->fc_total_memsize = mp->fc_memsize * mp->fc_numblks;
84 	mp->fc_memstart_virt = kmem_zalloc(mp->fc_total_memsize, KM_NOSLEEP);
85 	mp->fc_memget_cnt = mp->fc_numblks;
86 	mp->fc_memput_cnt = 0;
87 	mp->fc_memstart_phys = 0;
88 	mp->fc_memflag = 0;
89 	mp->fc_lowmem = 0;
90 	mp->fc_mem_dma_handle = 0;
91 	mp->fc_mem_dat_handle = 0;
92 	mp->fc_memget_ptr = 0;
93 	mp->fc_memget_end = 0;
94 	mp->fc_memput_ptr = 0;
95 	mp->fc_memput_end = 0;
96 
97 	if (mp->fc_memstart_virt == NULL) {
98 		mutex_exit(&EMLXS_MEMGET_LOCK);
99 
100 		(void) emlxs_mem_free_buffer(hba);
101 
102 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
103 		    "NLP memory pool.");
104 
105 		return (0);
106 	}
107 	bzero(mp->fc_memstart_virt, mp->fc_memsize);
108 	ndlp = (NODELIST *)mp->fc_memstart_virt;
109 
110 	/*
111 	 * Link buffer into beginning of list. The first pointer
112 	 * in each buffer is a forward pointer to the next buffer.
113 	 */
114 	for (i = 0; i < mp->fc_numblks; i++, ndlp++) {
115 		ndlp->flag |= NODE_POOL_ALLOCATED;
116 
117 		oldbp = mp->fc_memget_ptr;
118 		bp = (uint8_t *)ndlp;
119 		if (oldbp == NULL) {
120 			mp->fc_memget_end = bp;
121 		}
122 		mp->fc_memget_ptr = bp;
123 		*((uint8_t **)bp) = oldbp;
124 	}
125 
126 
127 	/*
128 	 * Allocate and Initialize MEM_IOCB (1)
129 	 */
130 	mp = &hba->memseg[MEM_IOCB];
131 	mp->fc_memsize = sizeof (IOCBQ);
132 	mp->fc_numblks = (uint16_t)cfg[CFG_NUM_IOCBS].current;
133 	mp->fc_total_memsize = mp->fc_memsize * mp->fc_numblks;
134 	mp->fc_memstart_virt = kmem_zalloc(mp->fc_total_memsize, KM_NOSLEEP);
135 	mp->fc_lowmem = (mp->fc_numblks >> 4);
136 	mp->fc_memget_cnt = mp->fc_numblks;
137 	mp->fc_memput_cnt = 0;
138 	mp->fc_memflag = 0;
139 	mp->fc_memstart_phys = 0;
140 	mp->fc_mem_dma_handle = 0;
141 	mp->fc_mem_dat_handle = 0;
142 	mp->fc_memget_ptr = 0;
143 	mp->fc_memget_end = 0;
144 	mp->fc_memput_ptr = 0;
145 	mp->fc_memput_end = 0;
146 
147 	if (mp->fc_memstart_virt == NULL) {
148 		mutex_exit(&EMLXS_MEMGET_LOCK);
149 
150 		(void) emlxs_mem_free_buffer(hba);
151 
152 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
153 		    "IOCB memory pool.");
154 
155 		return (0);
156 	}
157 	bzero(mp->fc_memstart_virt, mp->fc_memsize);
158 	iocbq = (IOCBQ *)mp->fc_memstart_virt;
159 
160 	/*
161 	 * Link buffer into beginning of list. The first pointer
162 	 * in each buffer is a forward pointer to the next buffer.
163 	 */
164 	for (i = 0; i < mp->fc_numblks; i++, iocbq++) {
165 		iocbq->flag |= IOCB_POOL_ALLOCATED;
166 
167 		oldbp = mp->fc_memget_ptr;
168 		bp = (uint8_t *)iocbq;
169 		if (oldbp == NULL) {
170 			mp->fc_memget_end = bp;
171 		}
172 		mp->fc_memget_ptr = bp;
173 		*((uint8_t **)bp) = oldbp;
174 	}
175 
176 	/*
177 	 * Allocate and Initialize MEM_MBOX (2)
178 	 */
179 	mp = &hba->memseg[MEM_MBOX];
180 	mp->fc_memsize = sizeof (MAILBOXQ);
181 	mp->fc_numblks = (int16_t)hba->max_nodes + 32;
182 	mp->fc_total_memsize = mp->fc_memsize * mp->fc_numblks;
183 	mp->fc_memstart_virt = kmem_zalloc(mp->fc_total_memsize, KM_NOSLEEP);
184 	mp->fc_lowmem = (mp->fc_numblks >> 3);
185 	mp->fc_memget_cnt = mp->fc_numblks;
186 	mp->fc_memput_cnt = 0;
187 	mp->fc_memflag = 0;
188 	mp->fc_memstart_phys = 0;
189 	mp->fc_mem_dma_handle = 0;
190 	mp->fc_mem_dat_handle = 0;
191 	mp->fc_memget_ptr = 0;
192 	mp->fc_memget_end = 0;
193 	mp->fc_memput_ptr = 0;
194 	mp->fc_memput_end = 0;
195 
196 	if (mp->fc_memstart_virt == NULL) {
197 		mutex_exit(&EMLXS_MEMGET_LOCK);
198 
199 		(void) emlxs_mem_free_buffer(hba);
200 
201 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
202 		    "MBOX memory pool.");
203 
204 		return (0);
205 	}
206 	bzero(mp->fc_memstart_virt, mp->fc_memsize);
207 	mbox = (MAILBOXQ *)mp->fc_memstart_virt;
208 
209 	/*
210 	 * Link buffer into beginning of list. The first pointer
211 	 * in each buffer is a forward pointer to the next buffer.
212 	 */
213 	for (i = 0; i < mp->fc_numblks; i++, mbox++) {
214 		mbox->flag |= MBQ_POOL_ALLOCATED;
215 
216 		oldbp = mp->fc_memget_ptr;
217 		bp = (uint8_t *)mbox;
218 		if (oldbp == NULL) {
219 			mp->fc_memget_end = bp;
220 		}
221 		mp->fc_memget_ptr = bp;
222 		*((uint8_t **)bp) = oldbp;
223 	}
224 
225 	/*
226 	 * Initialize fc_table
227 	 */
228 	fcp_rp = &hba->ring[FC_FCP_RING];
229 	ip_rp = &hba->ring[FC_IP_RING];
230 	els_rp = &hba->ring[FC_ELS_RING];
231 	ct_rp = &hba->ring[FC_CT_RING];
232 
233 	fcp_rp->max_iotag = cfg[CFG_NUM_IOTAGS].current;
234 	ip_rp->max_iotag = hba->max_nodes;
235 	els_rp->max_iotag = hba->max_nodes;
236 	ct_rp->max_iotag = hba->max_nodes;
237 
238 	/* Allocate the fc_table */
239 	total_iotags = fcp_rp->max_iotag + ip_rp->max_iotag +
240 	    els_rp->max_iotag + ct_rp->max_iotag;
241 
242 	bzero(buf_info, sizeof (MBUF_INFO));
243 	buf_info->size = total_iotags * sizeof (emlxs_buf_t *);
244 	buf_info->align = sizeof (void *);
245 
246 	(void) emlxs_mem_alloc(hba, buf_info);
247 	if (buf_info->virt == NULL) {
248 		mutex_exit(&EMLXS_MEMGET_LOCK);
249 
250 		(void) emlxs_mem_free_buffer(hba);
251 
252 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
253 		    "fc_table buffer.");
254 
255 		return (0);
256 	}
257 	hba->iotag_table = buf_info->virt;
258 	fcp_rp->fc_table = &hba->iotag_table[0];
259 	ip_rp->fc_table = &hba->iotag_table[fcp_rp->max_iotag];
260 	els_rp->fc_table =
261 	    &hba->iotag_table[fcp_rp->max_iotag + ip_rp->max_iotag];
262 	ct_rp->fc_table =
263 	    &hba->iotag_table[fcp_rp->max_iotag + ip_rp->max_iotag +
264 	    els_rp->max_iotag];
265 
266 
267 #ifdef EMLXS_SPARC
268 	/*
269 	 * Allocate and Initialize FCP MEM_BPL's.
270 	 * This is for increased performance on sparc
271 	 */
272 
273 	bzero(buf_info, sizeof (MBUF_INFO));
274 	buf_info->size = fcp_rp->max_iotag * sizeof (MATCHMAP);
275 	buf_info->align = sizeof (void *);
276 
277 	(void) emlxs_mem_alloc(hba, buf_info);
278 	if (buf_info->virt == NULL) {
279 		mutex_exit(&EMLXS_MEMGET_LOCK);
280 
281 		(void) emlxs_mem_free_buffer(hba);
282 
283 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
284 		    "FCP BPL table buffer.");
285 
286 		return (0);
287 	}
288 	hba->fcp_bpl_table = buf_info->virt;
289 	bzero(hba->fcp_bpl_table, buf_info->size);
290 
291 	bzero(buf_info, sizeof (MBUF_INFO));
292 	buf_info->size = (fcp_rp->max_iotag * (3 * sizeof (ULP_BDE64)));
293 	buf_info->flags = FC_MBUF_DMA;
294 	buf_info->align = 32;
295 
296 	(void) emlxs_mem_alloc(hba, buf_info);
297 	if (buf_info->virt == NULL) {
298 		mutex_exit(&EMLXS_MEMGET_LOCK);
299 
300 		(void) emlxs_mem_free_buffer(hba);
301 
302 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
303 		    "FCP BPL DMA buffers.");
304 
305 		return (0);
306 	}
307 	bzero(buf_info->virt, buf_info->size);
308 
309 	hba->fcp_bpl_mp.size = buf_info->size;
310 	hba->fcp_bpl_mp.virt = buf_info->virt;
311 	hba->fcp_bpl_mp.phys = buf_info->phys;
312 	hba->fcp_bpl_mp.data_handle = buf_info->data_handle;
313 	hba->fcp_bpl_mp.dma_handle = buf_info->dma_handle;
314 	hba->fcp_bpl_mp.tag = NULL;
315 
316 	v_bpl = (ULP_BDE64 *)hba->fcp_bpl_mp.virt;
317 	p_bpl = (ULP_BDE64 *)hba->fcp_bpl_mp.phys;
318 	for (i = 0, j = 0; i < fcp_rp->max_iotag; i++, j += 3) {
319 		matp = &hba->fcp_bpl_table[i];
320 
321 		matp->fc_mptr = NULL;
322 		matp->size = (3 * sizeof (ULP_BDE64));
323 		matp->virt = (uint8_t *)&v_bpl[j];
324 		matp->phys = (uint64_t)&p_bpl[j];
325 		matp->dma_handle = NULL;
326 		matp->data_handle = NULL;
327 		matp->tag = MEM_BPL;
328 		matp->flag |= MAP_TABLE_ALLOCATED;
329 	}
330 #endif /* EMLXS_SPARC */
331 
332 	/*
333 	 * Allocate and Initialize MEM_BPL (3)
334 	 */
335 
336 	mp = &hba->memseg[MEM_BPL];
337 	mp->fc_memsize = hba->mem_bpl_size;	/* Set during attach */
338 	mp->fc_numblks = (uint16_t)cfg[CFG_NUM_IOCBS].current;
339 	mp->fc_memflag = FC_MEM_DMA;
340 	mp->fc_lowmem = (mp->fc_numblks >> 4);
341 	mp->fc_memstart_virt = 0;
342 	mp->fc_memstart_phys = 0;
343 	mp->fc_mem_dma_handle = 0;
344 	mp->fc_mem_dat_handle = 0;
345 	mp->fc_memget_ptr = 0;
346 	mp->fc_memget_end = 0;
347 	mp->fc_memput_ptr = 0;
348 	mp->fc_memput_end = 0;
349 	mp->fc_total_memsize = 0;
350 	mp->fc_memget_cnt = mp->fc_numblks;
351 	mp->fc_memput_cnt = 0;
352 
353 	/* Allocate buffer pools for above buffer structures */
354 	for (i = 0; i < mp->fc_numblks; i++) {
355 		/*
356 		 * If this is a DMA buffer we need alignment on a page
357 		 * so we don't want to worry about buffers spanning page
358 		 * boundries when mapping memory for the adapter.
359 		 */
360 		bzero(buf_info, sizeof (MBUF_INFO));
361 		buf_info->size = sizeof (MATCHMAP);
362 		buf_info->align = sizeof (void *);
363 
364 		(void) emlxs_mem_alloc(hba, buf_info);
365 		if (buf_info->virt == NULL) {
366 			mutex_exit(&EMLXS_MEMGET_LOCK);
367 
368 			(void) emlxs_mem_free_buffer(hba);
369 
370 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
371 			    "BPL segment buffer.");
372 
373 			return (0);
374 		}
375 
376 		matp = (MATCHMAP *)buf_info->virt;
377 		bzero(matp, sizeof (MATCHMAP));
378 
379 		bzero(buf_info, sizeof (MBUF_INFO));
380 		buf_info->size = mp->fc_memsize;
381 		buf_info->flags = FC_MBUF_DMA;
382 		buf_info->align = 32;
383 
384 		(void) emlxs_mem_alloc(hba, buf_info);
385 		if (buf_info->virt == NULL) {
386 			mutex_exit(&EMLXS_MEMGET_LOCK);
387 
388 			(void) emlxs_mem_free_buffer(hba);
389 
390 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
391 			    "BPL DMA buffer.");
392 
393 			return (0);
394 		}
395 		bp = (uint8_t *)buf_info->virt;
396 		bzero(bp, mp->fc_memsize);
397 
398 		/*
399 		 * Link buffer into beginning of list. The first pointer
400 		 * in each buffer is a forward pointer to the next buffer.
401 		 */
402 		oldbp = mp->fc_memget_ptr;
403 
404 		if (oldbp == 0) {
405 			mp->fc_memget_end = (uint8_t *)matp;
406 		}
407 
408 		mp->fc_memget_ptr = (uint8_t *)matp;
409 		matp->fc_mptr = oldbp;
410 		matp->virt = buf_info->virt;
411 		matp->phys = buf_info->phys;
412 		matp->size = buf_info->size;
413 		matp->dma_handle = buf_info->dma_handle;
414 		matp->data_handle = buf_info->data_handle;
415 		matp->tag = MEM_BPL;
416 		matp->flag |= MAP_POOL_ALLOCATED;
417 	}
418 
419 
420 	/*
421 	 * These represent the unsolicited ELS buffers we preallocate.
422 	 */
423 
424 	mp = &hba->memseg[MEM_BUF];
425 	mp->fc_memsize = MEM_BUF_SIZE;
426 	mp->fc_numblks = MEM_ELSBUF_COUNT + MEM_BUF_COUNT;
427 	mp->fc_memflag = FC_MEM_DMA;
428 	mp->fc_lowmem = 3;
429 	mp->fc_memstart_virt = 0;
430 	mp->fc_memstart_phys = 0;
431 	mp->fc_mem_dma_handle = 0;
432 	mp->fc_mem_dat_handle = 0;
433 	mp->fc_memget_ptr = 0;
434 	mp->fc_memget_end = 0;
435 	mp->fc_memput_ptr = 0;
436 	mp->fc_memput_end = 0;
437 	mp->fc_total_memsize = 0;
438 	mp->fc_memget_cnt = mp->fc_numblks;
439 	mp->fc_memput_cnt = 0;
440 
441 	/* Allocate buffer pools for above buffer structures */
442 	for (i = 0; i < mp->fc_numblks; i++) {
443 		/*
444 		 * If this is a DMA buffer we need alignment on a page
445 		 * so we don't want to worry about buffers spanning page
446 		 * boundries when mapping memory for the adapter.
447 		 */
448 		bzero(buf_info, sizeof (MBUF_INFO));
449 		buf_info->size = sizeof (MATCHMAP);
450 		buf_info->align = sizeof (void *);
451 
452 		(void) emlxs_mem_alloc(hba, buf_info);
453 		if (buf_info->virt == NULL) {
454 			mutex_exit(&EMLXS_MEMGET_LOCK);
455 
456 			(void) emlxs_mem_free_buffer(hba);
457 
458 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
459 			    "MEM_BUF Segment buffer.");
460 
461 			return (0);
462 		}
463 
464 		matp = (MATCHMAP *)buf_info->virt;
465 		bzero(matp, sizeof (MATCHMAP));
466 
467 		bzero(buf_info, sizeof (MBUF_INFO));
468 		buf_info->size = mp->fc_memsize;
469 		buf_info->flags = FC_MBUF_DMA;
470 		buf_info->align = 32;
471 
472 		(void) emlxs_mem_alloc(hba, buf_info);
473 		if (buf_info->virt == NULL) {
474 			mutex_exit(&EMLXS_MEMGET_LOCK);
475 
476 			(void) emlxs_mem_free_buffer(hba);
477 
478 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
479 			    "MEM_BUF DMA buffer.");
480 
481 			return (0);
482 		}
483 		bp = (uint8_t *)buf_info->virt;
484 		bzero(bp, mp->fc_memsize);
485 
486 		/*
487 		 * Link buffer into beginning of list. The first pointer
488 		 * in each buffer is a forward pointer to the next buffer.
489 		 */
490 		oldbp = mp->fc_memget_ptr;
491 
492 		if (oldbp == 0) {
493 			mp->fc_memget_end = (uint8_t *)matp;
494 		}
495 
496 		mp->fc_memget_ptr = (uint8_t *)matp;
497 		matp->fc_mptr = oldbp;
498 		matp->virt = buf_info->virt;
499 		matp->phys = buf_info->phys;
500 		matp->size = buf_info->size;
501 		matp->dma_handle = buf_info->dma_handle;
502 		matp->data_handle = buf_info->data_handle;
503 		matp->tag = MEM_BUF;
504 		matp->flag |= MAP_POOL_ALLOCATED;
505 	}
506 
507 
508 	/*
509 	 * These represent the unsolicited IP buffers we preallocate.
510 	 */
511 
512 	mp = &hba->memseg[MEM_IPBUF];
513 	mp->fc_memsize = MEM_IPBUF_SIZE;
514 	mp->fc_numblks = MEM_IPBUF_COUNT;
515 	mp->fc_memflag = FC_MEM_DMA;
516 	mp->fc_lowmem = 3;
517 	mp->fc_memstart_virt = 0;
518 	mp->fc_memstart_phys = 0;
519 	mp->fc_mem_dma_handle = 0;
520 	mp->fc_mem_dat_handle = 0;
521 	mp->fc_memget_ptr = 0;
522 	mp->fc_memget_end = 0;
523 	mp->fc_memput_ptr = 0;
524 	mp->fc_memput_end = 0;
525 	mp->fc_total_memsize = 0;
526 	mp->fc_memget_cnt = mp->fc_numblks;
527 	mp->fc_memput_cnt = 0;
528 
529 	/* Allocate buffer pools for above buffer structures */
530 	for (i = 0; i < mp->fc_numblks; i++) {
531 		/*
532 		 * If this is a DMA buffer we need alignment on a page
533 		 * so we don't want to worry about buffers spanning page
534 		 * boundries when mapping memory for the adapter.
535 		 */
536 		bzero(buf_info, sizeof (MBUF_INFO));
537 		buf_info->size = sizeof (MATCHMAP);
538 		buf_info->align = sizeof (void *);
539 
540 		(void) emlxs_mem_alloc(hba, buf_info);
541 		if (buf_info->virt == NULL) {
542 			mutex_exit(&EMLXS_MEMGET_LOCK);
543 
544 			(void) emlxs_mem_free_buffer(hba);
545 
546 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
547 			    "IP_BUF Segment buffer.");
548 
549 			return (0);
550 		}
551 
552 		matp = (MATCHMAP *)buf_info->virt;
553 		bzero(matp, sizeof (MATCHMAP));
554 
555 		bzero(buf_info, sizeof (MBUF_INFO));
556 		buf_info->size = mp->fc_memsize;
557 		buf_info->flags = FC_MBUF_DMA;
558 		buf_info->align = 32;
559 
560 		(void) emlxs_mem_alloc(hba, buf_info);
561 		if (buf_info->virt == NULL) {
562 			mutex_exit(&EMLXS_MEMGET_LOCK);
563 
564 			(void) emlxs_mem_free_buffer(hba);
565 
566 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
567 			    "IP_BUF DMA buffer.");
568 
569 			return (0);
570 		}
571 		bp = (uint8_t *)buf_info->virt;
572 		bzero(bp, mp->fc_memsize);
573 
574 		/*
575 		 * Link buffer into beginning of list. The first pointer
576 		 * in each buffer is a forward pointer to the next buffer.
577 		 */
578 		oldbp = mp->fc_memget_ptr;
579 
580 		if (oldbp == 0) {
581 			mp->fc_memget_end = (uint8_t *)matp;
582 		}
583 
584 		mp->fc_memget_ptr = (uint8_t *)matp;
585 		matp->fc_mptr = oldbp;
586 		matp->virt = buf_info->virt;
587 		matp->phys = buf_info->phys;
588 		matp->size = buf_info->size;
589 		matp->dma_handle = buf_info->dma_handle;
590 		matp->data_handle = buf_info->data_handle;
591 		matp->tag = MEM_IPBUF;
592 		matp->flag |= MAP_POOL_ALLOCATED;
593 	}
594 
595 	/*
596 	 * These represent the unsolicited CT buffers we preallocate.
597 	 */
598 	mp = &hba->memseg[MEM_CTBUF];
599 	mp->fc_memsize = MEM_CTBUF_SIZE;
600 	mp->fc_numblks = MEM_CTBUF_COUNT;
601 	mp->fc_memflag = FC_MEM_DMA;
602 	mp->fc_lowmem = 0;
603 	mp->fc_memstart_virt = 0;
604 	mp->fc_memstart_phys = 0;
605 	mp->fc_mem_dma_handle = 0;
606 	mp->fc_mem_dat_handle = 0;
607 	mp->fc_memget_ptr = 0;
608 	mp->fc_memget_end = 0;
609 	mp->fc_memput_ptr = 0;
610 	mp->fc_memput_end = 0;
611 	mp->fc_total_memsize = 0;
612 	mp->fc_memget_cnt = mp->fc_numblks;
613 	mp->fc_memput_cnt = 0;
614 
615 	/* Allocate buffer pools for above buffer structures */
616 	for (i = 0; i < mp->fc_numblks; i++) {
617 		/*
618 		 * If this is a DMA buffer we need alignment on a page
619 		 * so we don't want to worry about buffers spanning page
620 		 * boundries when mapping memory for the adapter.
621 		 */
622 		bzero(buf_info, sizeof (MBUF_INFO));
623 		buf_info->size = sizeof (MATCHMAP);
624 		buf_info->align = sizeof (void *);
625 
626 		(void) emlxs_mem_alloc(hba, buf_info);
627 		if (buf_info->virt == NULL) {
628 			mutex_exit(&EMLXS_MEMGET_LOCK);
629 
630 			(void) emlxs_mem_free_buffer(hba);
631 
632 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
633 			    "CT_BUF Segment buffer.");
634 
635 			return (0);
636 		}
637 
638 		matp = (MATCHMAP *)buf_info->virt;
639 		bzero(matp, sizeof (MATCHMAP));
640 
641 		bzero(buf_info, sizeof (MBUF_INFO));
642 		buf_info->size = mp->fc_memsize;
643 		buf_info->flags = FC_MBUF_DMA;
644 		buf_info->align = 32;
645 
646 		(void) emlxs_mem_alloc(hba, buf_info);
647 		if (buf_info->virt == NULL) {
648 			mutex_exit(&EMLXS_MEMGET_LOCK);
649 
650 			(void) emlxs_mem_free_buffer(hba);
651 
652 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
653 			    "CT_BUF DMA buffer.");
654 
655 			return (0);
656 		}
657 		bp = (uint8_t *)buf_info->virt;
658 		bzero(bp, mp->fc_memsize);
659 
660 		/*
661 		 * Link buffer into beginning of list. The first pointer
662 		 * in each buffer is a forward pointer to the next buffer.
663 		 */
664 		oldbp = mp->fc_memget_ptr;
665 
666 		if (oldbp == 0) {
667 			mp->fc_memget_end = (uint8_t *)matp;
668 		}
669 
670 		mp->fc_memget_ptr = (uint8_t *)matp;
671 		matp->fc_mptr = oldbp;
672 		matp->virt = buf_info->virt;
673 		matp->phys = buf_info->phys;
674 		matp->size = buf_info->size;
675 		matp->dma_handle = buf_info->dma_handle;
676 		matp->data_handle = buf_info->data_handle;
677 		matp->tag = MEM_CTBUF;
678 		matp->flag |= MAP_POOL_ALLOCATED;
679 	}
680 
681 #ifdef SFCT_SUPPORT
682 
683 	/*
684 	 * These represent the unsolicited FCT buffers we preallocate.
685 	 */
686 	mp = &hba->memseg[MEM_FCTBUF];
687 	mp->fc_memsize = MEM_FCTBUF_SIZE;
688 	mp->fc_numblks = (hba->tgt_mode) ? MEM_FCTBUF_COUNT : 0;
689 	mp->fc_memflag = FC_MEM_DMA;
690 	mp->fc_lowmem = 0;
691 	mp->fc_memstart_virt = 0;
692 	mp->fc_memstart_phys = 0;
693 	mp->fc_mem_dma_handle = 0;
694 	mp->fc_mem_dat_handle = 0;
695 	mp->fc_memget_ptr = 0;
696 	mp->fc_memget_end = 0;
697 	mp->fc_memput_ptr = 0;
698 	mp->fc_memput_end = 0;
699 	mp->fc_total_memsize = 0;
700 	mp->fc_memget_cnt = mp->fc_numblks;
701 	mp->fc_memput_cnt = 0;
702 
703 	/* Allocate buffer pools for above buffer structures */
704 	for (i = 0; i < mp->fc_numblks; i++) {
705 		/*
706 		 * If this is a DMA buffer we need alignment on a page
707 		 * so we don't want to worry about buffers spanning page
708 		 * boundries when mapping memory for the adapter.
709 		 */
710 		bzero(buf_info, sizeof (MBUF_INFO));
711 		buf_info->size = sizeof (MATCHMAP);
712 		buf_info->align = sizeof (void *);
713 
714 		(void) emlxs_mem_alloc(hba, buf_info);
715 		if (buf_info->virt == NULL) {
716 			mutex_exit(&EMLXS_MEMGET_LOCK);
717 
718 			(void) emlxs_mem_free_buffer(hba);
719 
720 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
721 			    "FCT_BUF Segment buffer.");
722 
723 			return (0);
724 		}
725 
726 		matp = (MATCHMAP *)buf_info->virt;
727 		bzero(matp, sizeof (MATCHMAP));
728 
729 		bzero(buf_info, sizeof (MBUF_INFO));
730 		buf_info->size = mp->fc_memsize;
731 		buf_info->flags = FC_MBUF_DMA;
732 		buf_info->align = 32;
733 
734 		(void) emlxs_mem_alloc(hba, buf_info);
735 		if (buf_info->virt == NULL) {
736 			mutex_exit(&EMLXS_MEMGET_LOCK);
737 
738 			(void) emlxs_mem_free_buffer(hba);
739 
740 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
741 			    "FCT_BUF DMA buffer.");
742 
743 			return (0);
744 		}
745 		bp = (uint8_t *)buf_info->virt;
746 		bzero(bp, mp->fc_memsize);
747 
748 		/*
749 		 * Link buffer into beginning of list. The first pointer
750 		 * in each buffer is a forward pointer to the next buffer.
751 		 */
752 		oldbp = mp->fc_memget_ptr;
753 
754 		if (oldbp == 0) {
755 			mp->fc_memget_end = (uint8_t *)matp;
756 		}
757 
758 		mp->fc_memget_ptr = (uint8_t *)matp;
759 		matp->fc_mptr = oldbp;
760 		matp->virt = buf_info->virt;
761 		matp->phys = buf_info->phys;
762 		matp->size = buf_info->size;
763 		matp->dma_handle = buf_info->dma_handle;
764 		matp->data_handle = buf_info->data_handle;
765 		matp->tag = MEM_FCTBUF;
766 		matp->flag |= MAP_POOL_ALLOCATED;
767 	}
768 #endif /* SFCT_SUPPORT */
769 
770 	for (i = 0; i < FC_MAX_SEG; i++) {
771 		char *seg;
772 
773 		switch (i) {
774 		case MEM_NLP:
775 			seg = "MEM_NLP";
776 			break;
777 		case MEM_IOCB:
778 			seg = "MEM_IOCB";
779 			break;
780 		case MEM_MBOX:
781 			seg = "MEM_MBOX";
782 			break;
783 		case MEM_BPL:
784 			seg = "MEM_BPL";
785 			break;
786 		case MEM_BUF:
787 			seg = "MEM_BUF";
788 			break;
789 		case MEM_IPBUF:
790 			seg = "MEM_IPBUF";
791 			break;
792 		case MEM_CTBUF:
793 			seg = "MEM_CTBUF";
794 			break;
795 #ifdef SFCT_SUPPORT
796 		case MEM_FCTBUF:
797 			seg = "MEM_FCTBUF";
798 			break;
799 #endif /* SFCT_SUPPORT */
800 		default:
801 			break;
802 		}
803 
804 		mp = &hba->memseg[i];
805 
806 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
807 		    "Segment: %s mp=%p size=%x count=%d flags=%x base=%p",
808 		    seg, mp, mp->fc_memsize, mp->fc_numblks, mp->fc_memflag,
809 		    mp->fc_memget_ptr);
810 	}
811 
812 	mutex_exit(&EMLXS_MEMGET_LOCK);
813 
814 	return (1);
815 
816 }  /* emlxs_mem_alloc_buffer() */
817 
818 
819 
820 /*
821  * emlxs_mem_free_buffer
822  *
823  * This routine will free iocb/data buffer space
824  * and TGTM resource.
825  */
826 extern int
827 emlxs_mem_free_buffer(emlxs_hba_t *hba)
828 {
829 	emlxs_port_t *port = &PPORT;
830 	emlxs_port_t *vport;
831 	int32_t j;
832 	uint8_t *bp;
833 	MEMSEG *mp;
834 	MATCHMAP *mm;
835 	RING *rp;
836 	IOCBQ *iocbq;
837 	IOCB *iocb;
838 	MAILBOXQ *mbox, *mbsave;
839 	MBUF_INFO *buf_info;
840 	MBUF_INFO bufinfo;
841 	emlxs_buf_t *sbp;
842 	fc_unsol_buf_t *ubp;
843 	RING *fcp_rp;
844 	RING *ip_rp;
845 	RING *els_rp;
846 	RING *ct_rp;
847 	uint32_t total_iotags;
848 	emlxs_ub_priv_t *ub_priv;
849 
850 	buf_info = &bufinfo;
851 
852 	/* Check for deferred pkt completion */
853 	if (hba->mbox_sbp) {
854 		sbp = (emlxs_buf_t *)hba->mbox_sbp;
855 		hba->mbox_sbp = 0;
856 
857 		emlxs_pkt_complete(sbp, -1, 0, 1);
858 	}
859 
860 	/* Check for deferred ub completion */
861 	if (hba->mbox_ubp) {
862 		ubp = (fc_unsol_buf_t *)hba->mbox_ubp;
863 		ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private;
864 		port = ub_priv->port;
865 		hba->mbox_ubp = 0;
866 
867 		emlxs_ub_callback(port, ubp);
868 	}
869 
870 #ifdef NPIV_SUPPORT
871 	/* Special handle for vport PLOGI */
872 	if (hba->mbox_iocbq == (uint8_t *)1) {
873 		hba->mbox_iocbq = NULL;
874 	}
875 #endif /* NPIV_SUPPORT */
876 
877 	/* Check for deferred iocb tx */
878 	if (hba->mbox_iocbq) {	/* iocb */
879 		iocbq = (IOCBQ *)hba->mbox_iocbq;
880 		hba->mbox_iocbq = 0;
881 		iocb = &iocbq->iocb;
882 
883 		/* Set the error status of the iocb */
884 		iocb->ulpStatus = IOSTAT_LOCAL_REJECT;
885 		iocb->un.grsp.perr.statLocalError = IOERR_ABORT_REQUESTED;
886 
887 		switch (iocb->ulpCommand) {
888 		case CMD_FCP_ICMND_CR:
889 		case CMD_FCP_ICMND_CX:
890 		case CMD_FCP_IREAD_CR:
891 		case CMD_FCP_IREAD_CX:
892 		case CMD_FCP_IWRITE_CR:
893 		case CMD_FCP_IWRITE_CX:
894 		case CMD_FCP_ICMND64_CR:
895 		case CMD_FCP_ICMND64_CX:
896 		case CMD_FCP_IREAD64_CR:
897 		case CMD_FCP_IREAD64_CX:
898 		case CMD_FCP_IWRITE64_CR:
899 		case CMD_FCP_IWRITE64_CX:
900 			rp = &hba->ring[FC_FCP_RING];
901 			emlxs_handle_fcp_event(hba, rp, iocbq);
902 			break;
903 
904 		case CMD_ELS_REQUEST_CR:
905 		case CMD_ELS_REQUEST_CX:
906 		case CMD_XMIT_ELS_RSP_CX:
907 		case CMD_ELS_REQUEST64_CR:	/* This is the only one used */
908 						/* for deferred iocb tx */
909 		case CMD_ELS_REQUEST64_CX:
910 		case CMD_XMIT_ELS_RSP64_CX:
911 			rp = &hba->ring[FC_ELS_RING];
912 			(void) emlxs_els_handle_event(hba, rp, iocbq);
913 			break;
914 
915 		case CMD_GEN_REQUEST64_CR:
916 		case CMD_GEN_REQUEST64_CX:
917 			rp = &hba->ring[FC_CT_RING];
918 			(void) emlxs_ct_handle_event(hba, rp, iocbq);
919 			break;
920 
921 		default:
922 			rp = (RING *)iocbq->ring;
923 
924 			if (rp) {
925 				if (rp->ringno == FC_ELS_RING) {
926 					(void) emlxs_mem_put(hba, MEM_ELSBUF,
927 					    (uint8_t *)iocbq->bp);
928 				} else if (rp->ringno == FC_CT_RING) {
929 					(void) emlxs_mem_put(hba, MEM_CTBUF,
930 					    (uint8_t *)iocbq->bp);
931 				} else if (rp->ringno == FC_IP_RING) {
932 					(void) emlxs_mem_put(hba, MEM_IPBUF,
933 					    (uint8_t *)iocbq->bp);
934 				}
935 #ifdef SFCT_SUPPORT
936 				else if (rp->ringno == FC_FCT_RING) {
937 					(void) emlxs_mem_put(hba, MEM_FCTBUF,
938 					    (uint8_t *)iocbq->bp);
939 				}
940 #endif /* SFCT_SUPPORT */
941 
942 			} else if (iocbq->bp) {
943 				(void) emlxs_mem_put(hba, MEM_BUF,
944 				    (uint8_t *)iocbq->bp);
945 			}
946 
947 			if (!iocbq->sbp) {
948 				(void) emlxs_mem_put(hba, MEM_IOCB,
949 				    (uint8_t *)iocbq);
950 			}
951 		}
952 	}
953 
954 	/* free the mapped address match area for each ring */
955 	for (j = 0; j < hba->ring_count; j++) {
956 		rp = &hba->ring[j];
957 
958 		/* Flush the ring */
959 		(void) emlxs_tx_ring_flush(hba, rp, 0);
960 
961 		while (rp->fc_mpoff) {
962 			uint64_t addr;
963 
964 			addr = 0;
965 			mm = (MATCHMAP *)(rp->fc_mpoff);
966 
967 			if ((j == FC_ELS_RING) || (j == FC_CT_RING) ||
968 #ifdef SFCT_SUPPORT
969 			    (j == FC_FCT_RING) ||
970 #endif /* SFCT_SUPPORT */
971 			    (j == FC_IP_RING)) {
972 				addr = mm->phys;
973 			}
974 
975 			if ((mm = emlxs_mem_get_vaddr(hba, rp, addr))) {
976 				if (j == FC_ELS_RING) {
977 					(void) emlxs_mem_put(hba, MEM_ELSBUF,
978 					    (uint8_t *)mm);
979 				} else if (j == FC_CT_RING) {
980 					(void) emlxs_mem_put(hba, MEM_CTBUF,
981 					    (uint8_t *)mm);
982 				} else if (j == FC_IP_RING) {
983 					(void) emlxs_mem_put(hba, MEM_IPBUF,
984 					    (uint8_t *)mm);
985 				}
986 #ifdef SFCT_SUPPORT
987 				else if (j == FC_FCT_RING) {
988 					(void) emlxs_mem_put(hba, MEM_FCTBUF,
989 					    (uint8_t *)mm);
990 				}
991 #endif /* SFCT_SUPPORT */
992 
993 			}
994 		}
995 	}
996 
997 #ifdef SLI3_SUPPORT
998 	if (hba->flag & FC_HBQ_ENABLED) {
999 		emlxs_hbq_free_all(hba, EMLXS_ELS_HBQ_ID);
1000 		emlxs_hbq_free_all(hba, EMLXS_IP_HBQ_ID);
1001 		emlxs_hbq_free_all(hba, EMLXS_CT_HBQ_ID);
1002 #ifdef SFCT_SUPPORT
1003 		if (hba->tgt_mode) {
1004 			emlxs_hbq_free_all(hba, EMLXS_FCT_HBQ_ID);
1005 		}
1006 #endif /* SFCT_SUPPORT */
1007 
1008 	}
1009 #endif /* SLI3_SUPPORT */
1010 
1011 	/* Free everything on mbox queue */
1012 	mbox = (MAILBOXQ *)(hba->mbox_queue.q_first);
1013 	while (mbox) {
1014 		mbsave = mbox;
1015 		mbox = (MAILBOXQ *)mbox->next;
1016 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbsave);
1017 	}
1018 	hba->mbox_queue.q_first = NULL;
1019 	hba->mbox_queue.q_last = NULL;
1020 	hba->mbox_queue.q_cnt = 0;
1021 	hba->mbox_queue_flag = 0;
1022 
1023 	/* Free the nodes */
1024 	for (j = 0; j < MAX_VPORTS; j++) {
1025 		vport = &VPORT(j);
1026 		if (vport->node_count) {
1027 			emlxs_node_destroy_all(vport);
1028 		}
1029 	}
1030 
1031 	/* Free memory associated with all buffers on get buffer pool */
1032 	if (hba->iotag_table) {
1033 		fcp_rp = &hba->ring[FC_FCP_RING];
1034 		ip_rp = &hba->ring[FC_IP_RING];
1035 		els_rp = &hba->ring[FC_ELS_RING];
1036 		ct_rp = &hba->ring[FC_CT_RING];
1037 
1038 		total_iotags = fcp_rp->max_iotag + ip_rp->max_iotag +
1039 		    els_rp->max_iotag + ct_rp->max_iotag;
1040 
1041 		bzero(buf_info, sizeof (MBUF_INFO));
1042 		buf_info->size = total_iotags * sizeof (emlxs_buf_t *);
1043 		buf_info->virt = hba->iotag_table;
1044 		emlxs_mem_free(hba, buf_info);
1045 
1046 		hba->iotag_table = 0;
1047 	}
1048 #ifdef EMLXS_SPARC
1049 	if (hba->fcp_bpl_table) {
1050 		bzero(buf_info, sizeof (MBUF_INFO));
1051 		buf_info->size = fcp_rp->max_iotag * sizeof (MATCHMAP);
1052 		buf_info->virt = hba->fcp_bpl_table;
1053 		emlxs_mem_free(hba, buf_info);
1054 
1055 		hba->fcp_bpl_table = 0;
1056 	}
1057 
1058 	if (hba->fcp_bpl_mp.virt) {
1059 		bzero(buf_info, sizeof (MBUF_INFO));
1060 		buf_info->size = hba->fcp_bpl_mp.size;
1061 		buf_info->virt = hba->fcp_bpl_mp.virt;
1062 		buf_info->phys = hba->fcp_bpl_mp.phys;
1063 		buf_info->dma_handle = hba->fcp_bpl_mp.dma_handle;
1064 		buf_info->data_handle = hba->fcp_bpl_mp.data_handle;
1065 		buf_info->flags = FC_MBUF_DMA;
1066 		emlxs_mem_free(hba, buf_info);
1067 
1068 		bzero(&hba->fcp_bpl_mp, sizeof (MATCHMAP));
1069 	}
1070 #endif /* EMLXS_SPARC */
1071 
1072 	/* Free the memory segments */
1073 	for (j = 0; j < FC_MAX_SEG; j++) {
1074 		mp = &hba->memseg[j];
1075 
1076 		/* MEM_NLP, MEM_IOCB, MEM_MBOX */
1077 		if (j < MEM_BPL) {
1078 			if (mp->fc_memstart_virt) {
1079 				kmem_free(mp->fc_memstart_virt,
1080 				    mp->fc_total_memsize);
1081 				bzero((char *)mp, sizeof (MEMSEG));
1082 			}
1083 
1084 			continue;
1085 		}
1086 
1087 		/*
1088 		 * MEM_BPL, MEM_BUF, MEM_ELSBUF,
1089 		 * MEM_IPBUF, MEM_CTBUF, MEM_FCTBUF
1090 		 */
1091 
1092 		/* Free memory associated with all buffers on get buffer pool */
1093 		mutex_enter(&EMLXS_MEMGET_LOCK);
1094 		while ((bp = mp->fc_memget_ptr) != NULL) {
1095 			mp->fc_memget_ptr = *((uint8_t **)bp);
1096 			mm = (MATCHMAP *)bp;
1097 
1098 			bzero(buf_info, sizeof (MBUF_INFO));
1099 			buf_info->size = mm->size;
1100 			buf_info->virt = mm->virt;
1101 			buf_info->phys = mm->phys;
1102 			buf_info->dma_handle = mm->dma_handle;
1103 			buf_info->data_handle = mm->data_handle;
1104 			buf_info->flags = FC_MBUF_DMA;
1105 			emlxs_mem_free(hba, buf_info);
1106 
1107 			bzero(buf_info, sizeof (MBUF_INFO));
1108 			buf_info->size = sizeof (MATCHMAP);
1109 			buf_info->virt = (uint32_t *)mm;
1110 			emlxs_mem_free(hba, buf_info);
1111 		}
1112 		mutex_exit(&EMLXS_MEMGET_LOCK);
1113 
1114 		/* Free memory associated with all buffers on put buffer pool */
1115 		mutex_enter(&EMLXS_MEMPUT_LOCK);
1116 		while ((bp = mp->fc_memput_ptr) != NULL) {
1117 			mp->fc_memput_ptr = *((uint8_t **)bp);
1118 			mm = (MATCHMAP *)bp;
1119 
1120 			bzero(buf_info, sizeof (MBUF_INFO));
1121 			buf_info->size = mm->size;
1122 			buf_info->virt = mm->virt;
1123 			buf_info->phys = mm->phys;
1124 			buf_info->dma_handle = mm->dma_handle;
1125 			buf_info->data_handle = mm->data_handle;
1126 			buf_info->flags = FC_MBUF_DMA;
1127 			emlxs_mem_free(hba, buf_info);
1128 
1129 			bzero(buf_info, sizeof (MBUF_INFO));
1130 			buf_info->size = sizeof (MATCHMAP);
1131 			buf_info->virt = (uint32_t *)mm;
1132 			emlxs_mem_free(hba, buf_info);
1133 		}
1134 		mutex_exit(&EMLXS_MEMPUT_LOCK);
1135 		bzero((char *)mp, sizeof (MEMSEG));
1136 	}
1137 
1138 	return (0);
1139 
1140 }  /* emlxs_mem_free_buffer() */
1141 
1142 
1143 extern uint8_t *
1144 emlxs_mem_buf_alloc(emlxs_hba_t *hba)
1145 {
1146 	emlxs_port_t *port = &PPORT;
1147 	uint8_t *bp = NULL;
1148 	MATCHMAP *matp = NULL;
1149 	MBUF_INFO *buf_info;
1150 	MBUF_INFO bufinfo;
1151 
1152 	buf_info = &bufinfo;
1153 
1154 	bzero(buf_info, sizeof (MBUF_INFO));
1155 	buf_info->size = sizeof (MATCHMAP);
1156 	buf_info->align = sizeof (void *);
1157 
1158 	(void) emlxs_mem_alloc(hba, buf_info);
1159 	if (buf_info->virt == NULL) {
1160 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
1161 		    "MEM_BUF_ALLOC buffer.");
1162 
1163 		return (0);
1164 	}
1165 
1166 	matp = (MATCHMAP *)buf_info->virt;
1167 	bzero(matp, sizeof (MATCHMAP));
1168 
1169 	bzero(buf_info, sizeof (MBUF_INFO));
1170 	buf_info->size = MEM_BUF_SIZE;
1171 	buf_info->flags = FC_MBUF_DMA;
1172 	buf_info->align = 32;
1173 
1174 	(void) emlxs_mem_alloc(hba, buf_info);
1175 	if (buf_info->virt == NULL) {
1176 
1177 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
1178 		    "MEM_BUF_ALLOC DMA buffer.");
1179 
1180 		/* Free the matp object */
1181 		bzero(buf_info, sizeof (MBUF_INFO));
1182 		buf_info->size = sizeof (MATCHMAP);
1183 		buf_info->virt = (uint32_t *)matp;
1184 		emlxs_mem_free(hba, buf_info);
1185 
1186 		return (0);
1187 	}
1188 	bp = (uint8_t *)buf_info->virt;
1189 	bzero(bp, MEM_BUF_SIZE);
1190 
1191 	matp->fc_mptr = NULL;
1192 	matp->virt = buf_info->virt;
1193 	matp->phys = buf_info->phys;
1194 	matp->size = buf_info->size;
1195 	matp->dma_handle = buf_info->dma_handle;
1196 	matp->data_handle = buf_info->data_handle;
1197 	matp->tag = MEM_BUF;
1198 	matp->flag |= MAP_BUF_ALLOCATED;
1199 
1200 	return ((uint8_t *)matp);
1201 
1202 }  /* emlxs_mem_buf_alloc() */
1203 
1204 
1205 extern uint8_t *
1206 emlxs_mem_buf_free(emlxs_hba_t *hba, uint8_t *bp)
1207 {
1208 	MATCHMAP *matp;
1209 	MBUF_INFO bufinfo;
1210 	MBUF_INFO *buf_info;
1211 
1212 	buf_info = &bufinfo;
1213 
1214 	matp = (MATCHMAP *)bp;
1215 
1216 	if (!(matp->flag & MAP_BUF_ALLOCATED)) {
1217 		return (NULL);
1218 	}
1219 
1220 	bzero(buf_info, sizeof (MBUF_INFO));
1221 	buf_info->size = matp->size;
1222 	buf_info->virt = matp->virt;
1223 	buf_info->phys = matp->phys;
1224 	buf_info->dma_handle = matp->dma_handle;
1225 	buf_info->data_handle = matp->data_handle;
1226 	buf_info->flags = FC_MBUF_DMA;
1227 	emlxs_mem_free(hba, buf_info);
1228 
1229 	bzero(buf_info, sizeof (MBUF_INFO));
1230 	buf_info->size = sizeof (MATCHMAP);
1231 	buf_info->virt = (uint32_t *)matp;
1232 	emlxs_mem_free(hba, buf_info);
1233 
1234 	return (bp);
1235 
1236 }  /* emlxs_mem_buf_free() */
1237 
1238 
1239 
1240 /*
1241  * emlxs_mem_get
1242  *
1243  * This routine will get a free memory buffer.
1244  * seg identifies which buffer pool to use.
1245  * Returns the free buffer ptr or 0 for no buf
1246  */
1247 extern uint8_t *
1248 emlxs_mem_get(emlxs_hba_t *hba, uint32_t arg)
1249 {
1250 	emlxs_port_t *port = &PPORT;
1251 	MEMSEG *mp;
1252 	uint8_t *bp = NULL;
1253 	uint32_t seg = arg & MEM_SEG_MASK;
1254 	MAILBOXQ *mbq;
1255 	MATCHMAP *matp;
1256 	IOCBQ *iocbq;
1257 	NODELIST *node;
1258 	uint8_t *base;
1259 	uint8_t *end;
1260 
1261 	/* range check on seg argument */
1262 	if (seg >= FC_MAX_SEG) {
1263 		return (NULL);
1264 	}
1265 
1266 	mp = &hba->memseg[seg];
1267 
1268 	/* Check if memory segment destroyed! */
1269 	if (mp->fc_memsize == 0) {
1270 		return (NULL);
1271 	}
1272 
1273 	mutex_enter(&EMLXS_MEMGET_LOCK);
1274 
1275 top:
1276 
1277 	if (mp->fc_memget_ptr) {
1278 		bp = mp->fc_memget_ptr;
1279 
1280 		/* Checking if seg == MEM_MBOX, MEM_IOCB or MEM_NLP */
1281 		/* Verify buffer is in this memory region */
1282 		if (mp->fc_memstart_virt && mp->fc_total_memsize) {
1283 			base = mp->fc_memstart_virt;
1284 			end = mp->fc_memstart_virt + mp->fc_total_memsize;
1285 			if (bp < base || bp >= end) {
1286 				/* Invalidate the the get list */
1287 				mp->fc_memget_ptr = NULL;
1288 				mp->fc_memget_end = NULL;
1289 				mp->fc_memget_cnt = 0;
1290 
1291 				EMLXS_MSGF(EMLXS_CONTEXT,
1292 				    &emlxs_pool_error_msg,
1293 				    "Corruption detected: seg=%x bp=%p "
1294 				    "base=%p end=%p.", seg, bp, base, end);
1295 
1296 				emlxs_ffstate_change(hba, FC_ERROR);
1297 
1298 				mutex_exit(&EMLXS_MEMGET_LOCK);
1299 
1300 				thread_create(NULL, 0, emlxs_shutdown_thread,
1301 				    (char *)hba, 0, &p0, TS_RUN,
1302 				    v.v_maxsyspri - 2);
1303 
1304 				return (NULL);
1305 			}
1306 		}
1307 
1308 		/*
1309 		 * If a memory block exists, take it off freelist
1310 		 * and return it to the user.
1311 		 */
1312 		if (mp->fc_memget_end == bp) {
1313 			mp->fc_memget_ptr = NULL;
1314 			mp->fc_memget_end = NULL;
1315 			mp->fc_memget_cnt = 0;
1316 
1317 		} else {
1318 			/*
1319 			 * Pointer to the next free buffer
1320 			 */
1321 			mp->fc_memget_ptr = *((uint8_t **)bp);
1322 			mp->fc_memget_cnt--;
1323 		}
1324 
1325 		switch (seg) {
1326 		case MEM_MBOX:
1327 			bzero(bp, sizeof (MAILBOXQ));
1328 
1329 			mbq = (MAILBOXQ *)bp;
1330 			mbq->flag |= MBQ_POOL_ALLOCATED;
1331 			break;
1332 
1333 		case MEM_IOCB:
1334 			bzero(bp, sizeof (IOCBQ));
1335 
1336 			iocbq = (IOCBQ *)bp;
1337 			iocbq->flag |= IOCB_POOL_ALLOCATED;
1338 			break;
1339 
1340 		case MEM_NLP:
1341 			bzero(bp, sizeof (NODELIST));
1342 
1343 			node = (NODELIST *)bp;
1344 			node->flag |= NODE_POOL_ALLOCATED;
1345 			break;
1346 
1347 		case MEM_BPL:
1348 		case MEM_BUF:	/* MEM_ELSBUF */
1349 		case MEM_IPBUF:
1350 		case MEM_CTBUF:
1351 #ifdef SFCT_SUPPORT
1352 		case MEM_FCTBUF:
1353 #endif /* SFCT_SUPPORT */
1354 		default:
1355 			matp = (MATCHMAP *)bp;
1356 			matp->fc_mptr = NULL;
1357 			matp->flag |= MAP_POOL_ALLOCATED;
1358 			break;
1359 		}
1360 	} else {
1361 		mutex_enter(&EMLXS_MEMPUT_LOCK);
1362 		if (mp->fc_memput_ptr) {
1363 			/*
1364 			 * Move buffer from memput to memget
1365 			 */
1366 			mp->fc_memget_ptr = mp->fc_memput_ptr;
1367 			mp->fc_memget_end = mp->fc_memput_end;
1368 			mp->fc_memget_cnt = mp->fc_memput_cnt;
1369 			mp->fc_memput_ptr = NULL;
1370 			mp->fc_memput_end = NULL;
1371 			mp->fc_memput_cnt = 0;
1372 			mutex_exit(&EMLXS_MEMPUT_LOCK);
1373 
1374 			goto top;
1375 		}
1376 		mutex_exit(&EMLXS_MEMPUT_LOCK);
1377 
1378 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_alloc_failed_msg,
1379 		    "Pool empty: seg=%x lowmem=%x free=%x", seg,
1380 		    mp->fc_lowmem, mp->fc_memget_cnt);
1381 
1382 		/* HBASTATS.memAllocErr++; */
1383 	}
1384 
1385 	mutex_exit(&EMLXS_MEMGET_LOCK);
1386 
1387 	return (bp);
1388 
1389 }  /* emlxs_mem_get() */
1390 
1391 
1392 
1393 extern uint8_t *
1394 emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg, uint8_t *bp)
1395 {
1396 	emlxs_port_t *port = &PPORT;
1397 	MEMSEG *mp;
1398 	uint8_t *oldbp;
1399 	MATCHMAP *matp;
1400 	IOCBQ *iocbq;
1401 	MAILBOXQ *mbq;
1402 	NODELIST *node;
1403 	uint8_t *base;
1404 	uint8_t *end;
1405 
1406 	if (!bp) {
1407 		return (NULL);
1408 	}
1409 
1410 	/* Check on seg argument */
1411 	if (seg >= FC_MAX_SEG) {
1412 		return (NULL);
1413 	}
1414 
1415 	mp = &hba->memseg[seg];
1416 
1417 	switch (seg) {
1418 	case MEM_MBOX:
1419 		mbq = (MAILBOXQ *)bp;
1420 
1421 		if (!(mbq->flag & MBQ_POOL_ALLOCATED)) {
1422 			return (bp);
1423 		}
1424 		break;
1425 
1426 	case MEM_IOCB:
1427 		iocbq = (IOCBQ *)bp;
1428 
1429 		/* Check to make sure the IOCB is pool allocated */
1430 		if (!(iocbq->flag & IOCB_POOL_ALLOCATED)) {
1431 			return (bp);
1432 		}
1433 
1434 		/* Any IOCBQ with a packet attached did not come */
1435 		/* from our pool */
1436 		if (iocbq->sbp) {
1437 			return (bp);
1438 		}
1439 		break;
1440 
1441 	case MEM_NLP:
1442 		node = (NODELIST *)bp;
1443 
1444 		/* Check to make sure the NODE is pool allocated */
1445 		if (!(node->flag & NODE_POOL_ALLOCATED)) {
1446 			return (bp);
1447 		}
1448 		break;
1449 
1450 	case MEM_BPL:
1451 	case MEM_BUF:	/* MEM_ELSBUF */
1452 	case MEM_IPBUF:
1453 	case MEM_CTBUF:
1454 #ifdef SFCT_SUPPORT
1455 	case MEM_FCTBUF:
1456 #endif /* SFCT_SUPPORT */
1457 	default:
1458 		matp = (MATCHMAP *)bp;
1459 
1460 		if (matp->flag & MAP_BUF_ALLOCATED) {
1461 			return (emlxs_mem_buf_free(hba, bp));
1462 		}
1463 
1464 		if (matp->flag & MAP_TABLE_ALLOCATED) {
1465 			return (bp);
1466 		}
1467 
1468 		/* Check to make sure the MATCHMAP is pool allocated */
1469 		if (!(matp->flag & MAP_POOL_ALLOCATED)) {
1470 			return (bp);
1471 		}
1472 		break;
1473 	}
1474 
1475 	/* Free the pool object */
1476 	mutex_enter(&EMLXS_MEMPUT_LOCK);
1477 
1478 	/* Check if memory segment destroyed! */
1479 	if (mp->fc_memsize == 0) {
1480 		mutex_exit(&EMLXS_MEMPUT_LOCK);
1481 		return (NULL);
1482 	}
1483 
1484 	/* Check if buffer was just freed */
1485 	if (mp->fc_memput_ptr == bp) {
1486 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1487 		    "Freeing Free object: seg=%x bp=%p", seg, bp);
1488 
1489 		mutex_exit(&EMLXS_MEMPUT_LOCK);
1490 		return (NULL);
1491 	}
1492 
1493 	/* Validate the buffer */
1494 
1495 	/* Checking if seg == MEM_BUF, MEM_BPL, MEM_CTBUF, */
1496 	/* MEM_IPBUF or MEM_FCTBUF */
1497 	if (mp->fc_memflag & FC_MEM_DMA) {
1498 		if (matp->tag != seg) {
1499 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1500 			    "Corruption detected: seg=%x tag=%x bp=%p", seg,
1501 			    matp->tag, bp);
1502 
1503 			emlxs_ffstate_change(hba, FC_ERROR);
1504 
1505 			mutex_exit(&EMLXS_MEMPUT_LOCK);
1506 
1507 			thread_create(NULL, 0, emlxs_shutdown_thread,
1508 			    (char *)hba, 0, &p0, TS_RUN, v.v_maxsyspri - 2);
1509 
1510 			return (NULL);
1511 		}
1512 	}
1513 
1514 	/* Checking (seg == MEM_MBOX || seg == MEM_IOCB || seg == MEM_NLP) */
1515 	else if (mp->fc_memstart_virt && mp->fc_total_memsize) {
1516 		base = mp->fc_memstart_virt;
1517 		end = mp->fc_memstart_virt + mp->fc_total_memsize;
1518 		if (bp < base || bp >= end) {
1519 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1520 			    "Corruption detected: seg=%x bp=%p base=%p end=%p",
1521 			    seg, bp, base, end);
1522 
1523 			emlxs_ffstate_change(hba, FC_ERROR);
1524 
1525 			mutex_exit(&EMLXS_MEMPUT_LOCK);
1526 
1527 			thread_create(NULL, 0, emlxs_shutdown_thread,
1528 			    (char *)hba, 0, &p0, TS_RUN, v.v_maxsyspri - 2);
1529 
1530 			return (NULL);
1531 		}
1532 	}
1533 
1534 	/* Release to the first place of the freelist */
1535 	oldbp = mp->fc_memput_ptr;
1536 	mp->fc_memput_ptr = bp;
1537 	*((uint8_t **)bp) = oldbp;
1538 
1539 	if (oldbp == NULL) {
1540 		mp->fc_memput_end = bp;
1541 		mp->fc_memput_cnt = 1;
1542 	} else {
1543 		mp->fc_memput_cnt++;
1544 	}
1545 
1546 	mutex_exit(&EMLXS_MEMPUT_LOCK);
1547 
1548 	return (bp);
1549 
1550 }  /* emlxs_mem_put() */
1551 
1552 
1553 
1554 /*
1555  * Look up the virtual address given a mapped address
1556  */
1557 extern MATCHMAP *
1558 emlxs_mem_get_vaddr(emlxs_hba_t *hba, RING *rp, uint64_t mapbp)
1559 {
1560 	emlxs_port_t *port = &PPORT;
1561 	MATCHMAP *prev;
1562 	MATCHMAP *mp;
1563 
1564 	switch (rp->ringno) {
1565 	case FC_ELS_RING:
1566 		mp = (MATCHMAP *)rp->fc_mpoff;
1567 		prev = 0;
1568 
1569 		while (mp) {
1570 			if (mp->phys == mapbp) {
1571 				if (prev == 0) {
1572 					rp->fc_mpoff = mp->fc_mptr;
1573 				} else {
1574 					prev->fc_mptr = mp->fc_mptr;
1575 				}
1576 
1577 				if (rp->fc_mpon == (uint8_t *)mp) {
1578 					rp->fc_mpon = (uint8_t *)prev;
1579 				}
1580 
1581 				mp->fc_mptr = 0;
1582 
1583 				emlxs_mpdata_sync(mp->dma_handle, 0, mp->size,
1584 				    DDI_DMA_SYNC_FORKERNEL);
1585 
1586 				HBASTATS.ElsUbPosted--;
1587 
1588 				return (mp);
1589 			}
1590 
1591 			prev = mp;
1592 			mp = (MATCHMAP *)mp->fc_mptr;
1593 		}
1594 
1595 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1596 		    "ELS Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1597 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1598 
1599 		break;
1600 
1601 	case FC_CT_RING:
1602 		mp = (MATCHMAP *)rp->fc_mpoff;
1603 		prev = 0;
1604 
1605 		while (mp) {
1606 			if (mp->phys == mapbp) {
1607 				if (prev == 0) {
1608 					rp->fc_mpoff = mp->fc_mptr;
1609 				} else {
1610 					prev->fc_mptr = mp->fc_mptr;
1611 				}
1612 
1613 				if (rp->fc_mpon == (uint8_t *)mp) {
1614 					rp->fc_mpon = (uint8_t *)prev;
1615 				}
1616 
1617 				mp->fc_mptr = 0;
1618 
1619 				emlxs_mpdata_sync(mp->dma_handle, 0, mp->size,
1620 				    DDI_DMA_SYNC_FORKERNEL);
1621 
1622 				HBASTATS.CtUbPosted--;
1623 
1624 				return (mp);
1625 			}
1626 
1627 			prev = mp;
1628 			mp = (MATCHMAP *)mp->fc_mptr;
1629 		}
1630 
1631 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1632 		    "CT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1633 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1634 
1635 		break;
1636 
1637 	case FC_IP_RING:
1638 		mp = (MATCHMAP *)rp->fc_mpoff;
1639 		prev = 0;
1640 
1641 		while (mp) {
1642 			if (mp->phys == mapbp) {
1643 				if (prev == 0) {
1644 					rp->fc_mpoff = mp->fc_mptr;
1645 				} else {
1646 					prev->fc_mptr = mp->fc_mptr;
1647 				}
1648 
1649 				if (rp->fc_mpon == (uint8_t *)mp) {
1650 					rp->fc_mpon = (uint8_t *)prev;
1651 				}
1652 
1653 				mp->fc_mptr = 0;
1654 
1655 				emlxs_mpdata_sync(mp->dma_handle, 0, mp->size,
1656 				    DDI_DMA_SYNC_FORKERNEL);
1657 
1658 				HBASTATS.IpUbPosted--;
1659 
1660 				return (mp);
1661 			}
1662 
1663 			prev = mp;
1664 			mp = (MATCHMAP *)mp->fc_mptr;
1665 		}
1666 
1667 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1668 		    "IP Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1669 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1670 
1671 		break;
1672 
1673 #ifdef SFCT_SUPPORT
1674 	case FC_FCT_RING:
1675 		mp = (MATCHMAP *)rp->fc_mpoff;
1676 		prev = 0;
1677 
1678 		while (mp) {
1679 			if (mp->phys == mapbp) {
1680 				if (prev == 0) {
1681 					rp->fc_mpoff = mp->fc_mptr;
1682 				} else {
1683 					prev->fc_mptr = mp->fc_mptr;
1684 				}
1685 
1686 				if (rp->fc_mpon == (uint8_t *)mp) {
1687 					rp->fc_mpon = (uint8_t *)prev;
1688 				}
1689 
1690 				mp->fc_mptr = 0;
1691 
1692 				emlxs_mpdata_sync(mp->dma_handle, 0, mp->size,
1693 				    DDI_DMA_SYNC_FORKERNEL);
1694 
1695 				HBASTATS.FctUbPosted--;
1696 
1697 				return (mp);
1698 			}
1699 
1700 			prev = mp;
1701 			mp = (MATCHMAP *)mp->fc_mptr;
1702 		}
1703 
1704 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg,
1705 		    "FCT Buffer not mapped: bp=%lx ringno=%x mpoff=%p mpon=%p",
1706 		    mapbp, rp->ringno, rp->fc_mpoff, rp->fc_mpon);
1707 
1708 		break;
1709 #endif /* SFCT_SUPPORT */
1710 	}
1711 
1712 	return (0);
1713 
1714 }  /* emlxs_mem_get_vaddr() */
1715 
1716 
1717 /*
1718  * Given a virtual address bp, generate the physical mapped address and
1719  * place it where addr points to. Save the address pair for lookup later.
1720  */
1721 extern void
1722 emlxs_mem_map_vaddr(emlxs_hba_t *hba, RING *rp, MATCHMAP *mp,
1723     uint32_t *haddr, uint32_t *laddr)
1724 {
1725 	switch (rp->ringno) {
1726 	case FC_ELS_RING:
1727 		/*
1728 		 * Update slot fc_mpon points to then bump it
1729 		 * fc_mpoff is pointer head of the list.
1730 		 * fc_mpon is pointer tail of the list.
1731 		 */
1732 		mp->fc_mptr = 0;
1733 		if (rp->fc_mpoff == 0) {
1734 			rp->fc_mpoff = (uint8_t *)mp;
1735 			rp->fc_mpon = (uint8_t *)mp;
1736 		} else {
1737 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1738 			    (uint8_t *)mp;
1739 			rp->fc_mpon = (uint8_t *)mp;
1740 		}
1741 
1742 		if (hba->flag & FC_SLIM2_MODE) {
1743 
1744 			/* return mapped address */
1745 			*haddr = putPaddrHigh(mp->phys);
1746 			/* return mapped address */
1747 			*laddr = putPaddrLow(mp->phys);
1748 		} else {
1749 			/* return mapped address */
1750 			*laddr = putPaddrLow(mp->phys);
1751 		}
1752 
1753 		HBASTATS.ElsUbPosted++;
1754 
1755 		break;
1756 
1757 	case FC_CT_RING:
1758 		/*
1759 		 * Update slot fc_mpon points to then bump it
1760 		 * fc_mpoff is pointer head of the list.
1761 		 * fc_mpon is pointer tail of the list.
1762 		 */
1763 		mp->fc_mptr = 0;
1764 		if (rp->fc_mpoff == 0) {
1765 			rp->fc_mpoff = (uint8_t *)mp;
1766 			rp->fc_mpon = (uint8_t *)mp;
1767 		} else {
1768 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1769 			    (uint8_t *)mp;
1770 			rp->fc_mpon = (uint8_t *)mp;
1771 		}
1772 
1773 		if (hba->flag & FC_SLIM2_MODE) {
1774 			/* return mapped address */
1775 			*haddr = putPaddrHigh(mp->phys);
1776 			/* return mapped address */
1777 			*laddr = putPaddrLow(mp->phys);
1778 		} else {
1779 			/* return mapped address */
1780 			*laddr = putPaddrLow(mp->phys);
1781 		}
1782 
1783 		HBASTATS.CtUbPosted++;
1784 
1785 		break;
1786 
1787 
1788 	case FC_IP_RING:
1789 		/*
1790 		 * Update slot fc_mpon points to then bump it
1791 		 * fc_mpoff is pointer head of the list.
1792 		 * fc_mpon is pointer tail of the list.
1793 		 */
1794 		mp->fc_mptr = 0;
1795 		if (rp->fc_mpoff == 0) {
1796 			rp->fc_mpoff = (uint8_t *)mp;
1797 			rp->fc_mpon = (uint8_t *)mp;
1798 		} else {
1799 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1800 			    (uint8_t *)mp;
1801 			rp->fc_mpon = (uint8_t *)mp;
1802 		}
1803 
1804 		if (hba->flag & FC_SLIM2_MODE) {
1805 			/* return mapped address */
1806 			*haddr = putPaddrHigh(mp->phys);
1807 			*laddr = putPaddrLow(mp->phys);
1808 		} else {
1809 			*laddr = putPaddrLow(mp->phys);
1810 		}
1811 
1812 		HBASTATS.IpUbPosted++;
1813 		break;
1814 
1815 
1816 #ifdef SFCT_SUPPORT
1817 	case FC_FCT_RING:
1818 		/*
1819 		 * Update slot fc_mpon points to then bump it
1820 		 * fc_mpoff is pointer head of the list.
1821 		 * fc_mpon is pointer tail of the list.
1822 		 */
1823 		mp->fc_mptr = 0;
1824 		if (rp->fc_mpoff == 0) {
1825 			rp->fc_mpoff = (uint8_t *)mp;
1826 			rp->fc_mpon = (uint8_t *)mp;
1827 		} else {
1828 			((MATCHMAP *)(rp->fc_mpon))->fc_mptr =
1829 			    (uint8_t *)mp;
1830 			rp->fc_mpon = (uint8_t *)mp;
1831 		}
1832 
1833 		if (hba->flag & FC_SLIM2_MODE) {
1834 			/* return mapped address */
1835 			*haddr = putPaddrHigh(mp->phys);
1836 			/* return mapped address */
1837 			*laddr = putPaddrLow(mp->phys);
1838 		} else {
1839 			/* return mapped address */
1840 			*laddr = putPaddrLow(mp->phys);
1841 		}
1842 
1843 		HBASTATS.FctUbPosted++;
1844 		break;
1845 #endif /* SFCT_SUPPORT */
1846 	}
1847 }  /* emlxs_mem_map_vaddr() */
1848 
1849 
1850 #ifdef SLI3_SUPPORT
1851 
1852 uint32_t
1853 emlxs_hbq_alloc(emlxs_hba_t *hba, uint32_t hbq_id)
1854 {
1855 	emlxs_port_t *port = &PPORT;
1856 	HBQ_INIT_t *hbq;
1857 	MBUF_INFO *buf_info;
1858 	MBUF_INFO bufinfo;
1859 
1860 	hbq = &hba->hbq_table[hbq_id];
1861 
1862 	if (hbq->HBQ_host_buf.virt == 0) {
1863 		buf_info = &bufinfo;
1864 
1865 		/* Get the system's page size in a DDI-compliant way. */
1866 		bzero(buf_info, sizeof (MBUF_INFO));
1867 		buf_info->size = hbq->HBQ_numEntries * sizeof (HBQE_t);
1868 		buf_info->flags = FC_MBUF_DMA;
1869 		buf_info->align = 4096;
1870 
1871 		(void) emlxs_mem_alloc(hba, buf_info);
1872 
1873 		if (buf_info->virt == NULL) {
1874 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
1875 			    "Unable to alloc HBQ.");
1876 			return (ENOMEM);
1877 		}
1878 
1879 		hbq->HBQ_host_buf.virt = (void *)buf_info->virt;
1880 		hbq->HBQ_host_buf.phys = buf_info->phys;
1881 		hbq->HBQ_host_buf.data_handle = buf_info->data_handle;
1882 		hbq->HBQ_host_buf.dma_handle = buf_info->dma_handle;
1883 		hbq->HBQ_host_buf.size = buf_info->size;
1884 		hbq->HBQ_host_buf.tag = hbq_id;
1885 
1886 		bzero((char *)hbq->HBQ_host_buf.virt, buf_info->size);
1887 	}
1888 
1889 	return (0);
1890 
1891 }  /* emlxs_hbq_alloc() */
1892 
1893 
1894 #endif /* SLI3_SUPPORT */
1895