3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/dev/hfa/fore_buffer.c,v 1.5 2000/01/15 21:01:04 mks Exp $
27 * @(#) $DragonFly: src/sys/dev/atm/hfa/fore_buffer.c,v 1.6 2008/06/05 18:06:31 swildner Exp $
31 * FORE Systems 200-Series Adapter Support
32 * ---------------------------------------
34 * Buffer Supply queue management
38 #include "fore_include.h"
43 static void fore_buf_drain (Fore_unit *);
44 static void fore_buf_supply_1s (Fore_unit *);
45 static void fore_buf_supply_1l (Fore_unit *);
49 * Allocate Buffer Supply Queues Data Structures
51 * Here we are allocating memory for both Strategy 1 Small and Large
52 * structures contiguously.
55 * fup pointer to device unit structure
58 * 0 allocations successful
59 * else allocation failed
62 fore_buf_allocate(Fore_unit *fup)
67 * Allocate non-cacheable memory for buffer supply status words
70 sizeof(Q_status) * (BUF1_SM_QUELEN + BUF1_LG_QUELEN),
71 QSTAT_ALIGN, ATM_DEV_NONCACHE);
75 fup->fu_buf1s_stat = (Q_status *) memp;
76 fup->fu_buf1l_stat = ((Q_status *) memp) + BUF1_SM_QUELEN;
78 memp = DMA_GET_ADDR(fup->fu_buf1s_stat,
79 sizeof(Q_status) * (BUF1_SM_QUELEN + BUF1_LG_QUELEN),
80 QSTAT_ALIGN, ATM_DEV_NONCACHE);
84 fup->fu_buf1s_statd = (Q_status *) memp;
85 fup->fu_buf1l_statd = ((Q_status *) memp) + BUF1_SM_QUELEN;
88 * Allocate memory for buffer supply descriptors
90 memp = atm_dev_alloc(sizeof(Buf_descr) *
91 ((BUF1_SM_QUELEN * BUF1_SM_ENTSIZE) +
92 (BUF1_LG_QUELEN * BUF1_LG_ENTSIZE)),
97 fup->fu_buf1s_desc = (Buf_descr *) memp;
98 fup->fu_buf1l_desc = ((Buf_descr *) memp) +
99 (BUF1_SM_QUELEN * BUF1_SM_ENTSIZE);
101 memp = DMA_GET_ADDR(fup->fu_buf1s_desc, sizeof(Buf_descr) *
102 ((BUF1_SM_QUELEN * BUF1_SM_ENTSIZE) +
103 (BUF1_LG_QUELEN * BUF1_LG_ENTSIZE)),
108 fup->fu_buf1s_descd = (Buf_descr *) memp;
109 fup->fu_buf1l_descd = ((Buf_descr *) memp) +
110 (BUF1_SM_QUELEN * BUF1_SM_ENTSIZE);
117 * Buffer Supply Queues Initialization
119 * Allocate and initialize the host-resident buffer supply queue structures
120 * and then initialize the CP-resident queue structures.
122 * Called at interrupt level.
125 * fup pointer to device unit structure
131 fore_buf_initialize(Fore_unit *fup)
133 Aali *aap = fup->fu_aali;
143 * Initialize Strategy 1 Small Queues
147 * Point to CP-resident buffer supply queue
149 cqp = (Buf_queue *)(fup->fu_ram + CP_READ(aap->aali_buf1s_q));
152 * Point to host-resident buffer supply queue structures
154 hbp = fup->fu_buf1s_q;
155 qsp = fup->fu_buf1s_stat;
156 qsp_dma = fup->fu_buf1s_statd;
157 bdp = fup->fu_buf1s_desc;
158 bdp_dma = fup->fu_buf1s_descd;
161 * Loop thru all queue entries and do whatever needs doing
163 for (i = 0; i < BUF1_SM_QUELEN; i++) {
166 * Set queue status word to free
171 * Set up host queue entry and link into ring
173 hbp->hbq_cpelem = cqp;
174 hbp->hbq_status = qsp;
175 hbp->hbq_descr = bdp;
176 hbp->hbq_descr_dma = bdp_dma;
177 if (i == (BUF1_SM_QUELEN - 1))
178 hbp->hbq_next = fup->fu_buf1s_q;
180 hbp->hbq_next = hbp + 1;
183 * Now let the CP into the game
185 cqp->cq_status = (CP_dma) CP_WRITE(qsp_dma);
188 * Bump all queue pointers
193 bdp += BUF1_SM_ENTSIZE;
194 bdp_dma += BUF1_SM_ENTSIZE;
199 * Initialize queue pointers
201 fup->fu_buf1s_head = fup->fu_buf1s_tail = fup->fu_buf1s_q;
205 * Initialize Strategy 1 Large Queues
209 * Point to CP-resident buffer supply queue
211 cqp = (Buf_queue *)(fup->fu_ram + CP_READ(aap->aali_buf1l_q));
214 * Point to host-resident buffer supply queue structures
216 hbp = fup->fu_buf1l_q;
217 qsp = fup->fu_buf1l_stat;
218 qsp_dma = fup->fu_buf1l_statd;
219 bdp = fup->fu_buf1l_desc;
220 bdp_dma = fup->fu_buf1l_descd;
223 * Loop thru all queue entries and do whatever needs doing
225 for (i = 0; i < BUF1_LG_QUELEN; i++) {
228 * Set queue status word to free
233 * Set up host queue entry and link into ring
235 hbp->hbq_cpelem = cqp;
236 hbp->hbq_status = qsp;
237 hbp->hbq_descr = bdp;
238 hbp->hbq_descr_dma = bdp_dma;
239 if (i == (BUF1_LG_QUELEN - 1))
240 hbp->hbq_next = fup->fu_buf1l_q;
242 hbp->hbq_next = hbp + 1;
245 * Now let the CP into the game
247 cqp->cq_status = (CP_dma) CP_WRITE(qsp_dma);
250 * Bump all queue pointers
255 bdp += BUF1_LG_ENTSIZE;
256 bdp_dma += BUF1_LG_ENTSIZE;
261 * Initialize queue pointers
263 fup->fu_buf1l_head = fup->fu_buf1l_tail = fup->fu_buf1l_q;
270 * Supply Buffers to CP
272 * This function will resupply the CP with buffers to be used to
273 * store incoming data.
275 * May be called in interrupt state.
276 * Must be called with interrupts locked out.
279 * fup pointer to device unit structure
285 fore_buf_supply(Fore_unit *fup)
289 * First, clean out the supply queues
294 * Then, supply the buffers for each queue
296 fore_buf_supply_1s(fup);
297 fore_buf_supply_1l(fup);
304 * Supply Strategy 1 Small Buffers to CP
306 * May be called in interrupt state.
307 * Must be called with interrupts locked out.
310 * fup pointer to device unit structure
316 fore_buf_supply_1s(Fore_unit *fup)
326 * Figure out how many buffers we should be giving to the CP.
327 * We're basing this calculation on the current number of open
328 * VCCs thru this device, with certain minimum and maximum values
329 * enforced. This will then allow us to figure out how many more
330 * buffers we need to supply to the CP. This will be rounded up
331 * to fill a supply queue entry.
333 nvcc = MAX(fup->fu_open_vcc, BUF_MIN_VCC);
335 nbuf = MIN(nbuf, BUF1_SM_CPPOOL);
336 nbuf -= fup->fu_buf1s_cnt;
337 nbuf = roundup(nbuf, BUF1_SM_ENTSIZE);
340 * OK, now supply the buffers to the CP
345 * Acquire a supply queue entry
347 hbp = fup->fu_buf1s_tail;
348 if (!((*hbp->hbq_status) & QSTAT_FREE))
350 bdp = hbp->hbq_descr;
353 * Get a buffer for each descriptor in the queue entry
355 for (i = 0; i < BUF1_SM_ENTSIZE; i++, bdp++) {
361 KB_ALLOCPKT(m, BUF1_SM_SIZE, KB_F_NOWAIT, KB_T_DATA);
365 KB_HEADSET(m, BUF1_SM_DOFF);
368 * Point to buffer handle structure
370 bhp = (Buf_handle *)((caddr_t)m + BUF1_SM_HOFF);
371 bhp->bh_type = BHT_S1_SMALL;
374 * Setup buffer descriptor
376 bdp->bsd_handle = bhp;
377 KB_DATASTART(m, cp, caddr_t);
378 bhp->bh_dma = bdp->bsd_buffer = (H_dma) DMA_GET_ADDR(
379 cp, BUF1_SM_SIZE, BUF_DATA_ALIGN, 0);
380 if (bdp->bsd_buffer == 0) {
382 * Unable to assign dma address - free up
383 * this descriptor's buffer
385 fup->fu_stats->st_drv.drv_bf_segdma++;
391 * All set, so queue buffer (handle)
393 ENQUEUE(bhp, Buf_handle, bh_qelem, fup->fu_buf1s_bq);
397 * If we we're not able to fill all the descriptors for
398 * an entry, free up what's been partially built
400 if (i != BUF1_SM_ENTSIZE) {
404 * Clean up each used descriptor
406 for (bdp = hbp->hbq_descr; i; i--, bdp++) {
408 bhp = bdp->bsd_handle;
410 DEQUEUE(bhp, Buf_handle, bh_qelem,
414 ((caddr_t)bhp - BUF1_SM_HOFF);
415 KB_DATASTART(m, cp, caddr_t);
416 DMA_FREE_ADDR(cp, bhp->bh_dma, BUF1_SM_SIZE, 0);
423 * Finally, we've got an entry ready for the CP.
424 * So claim the host queue entry and setup the CP-resident
425 * queue entry. The CP will (potentially) grab the supplied
426 * buffers when the descriptor pointer is set.
428 fup->fu_buf1s_tail = hbp->hbq_next;
429 (*hbp->hbq_status) = QSTAT_PENDING;
430 cqp = hbp->hbq_cpelem;
431 cqp->cq_descr = (CP_dma) CP_WRITE((u_long)hbp->hbq_descr_dma);
434 * Update counters, etc for supplied buffers
436 fup->fu_buf1s_cnt += BUF1_SM_ENTSIZE;
437 nbuf -= BUF1_SM_ENTSIZE;
445 * Supply Strategy 1 Large Buffers to CP
447 * May be called in interrupt state.
448 * Must be called with interrupts locked out.
451 * fup pointer to device unit structure
457 fore_buf_supply_1l(Fore_unit *fup)
467 * Figure out how many buffers we should be giving to the CP.
468 * We're basing this calculation on the current number of open
469 * VCCs thru this device, with certain minimum and maximum values
470 * enforced. This will then allow us to figure out how many more
471 * buffers we need to supply to the CP. This will be rounded up
472 * to fill a supply queue entry.
474 nvcc = MAX(fup->fu_open_vcc, BUF_MIN_VCC);
475 nbuf = nvcc * 4 * RECV_MAX_SEGS;
476 nbuf = MIN(nbuf, BUF1_LG_CPPOOL);
477 nbuf -= fup->fu_buf1l_cnt;
478 nbuf = roundup(nbuf, BUF1_LG_ENTSIZE);
481 * OK, now supply the buffers to the CP
486 * Acquire a supply queue entry
488 hbp = fup->fu_buf1l_tail;
489 if (!((*hbp->hbq_status) & QSTAT_FREE))
491 bdp = hbp->hbq_descr;
494 * Get a buffer for each descriptor in the queue entry
496 for (i = 0; i < BUF1_LG_ENTSIZE; i++, bdp++) {
500 * Get a cluster buffer
502 KB_ALLOCEXT(m, BUF1_LG_SIZE, KB_F_NOWAIT, KB_T_DATA);
506 KB_HEADSET(m, BUF1_LG_DOFF);
509 * Point to buffer handle structure
511 bhp = (Buf_handle *)((caddr_t)m + BUF1_LG_HOFF);
512 bhp->bh_type = BHT_S1_LARGE;
515 * Setup buffer descriptor
517 bdp->bsd_handle = bhp;
518 KB_DATASTART(m, cp, caddr_t);
519 bhp->bh_dma = bdp->bsd_buffer = (H_dma) DMA_GET_ADDR(
520 cp, BUF1_LG_SIZE, BUF_DATA_ALIGN, 0);
521 if (bdp->bsd_buffer == 0) {
523 * Unable to assign dma address - free up
524 * this descriptor's buffer
526 fup->fu_stats->st_drv.drv_bf_segdma++;
532 * All set, so queue buffer (handle)
534 ENQUEUE(bhp, Buf_handle, bh_qelem, fup->fu_buf1l_bq);
538 * If we we're not able to fill all the descriptors for
539 * an entry, free up what's been partially built
541 if (i != BUF1_LG_ENTSIZE) {
545 * Clean up each used descriptor
547 for (bdp = hbp->hbq_descr; i; i--, bdp++) {
548 bhp = bdp->bsd_handle;
550 DEQUEUE(bhp, Buf_handle, bh_qelem,
554 ((caddr_t)bhp - BUF1_LG_HOFF);
555 KB_DATASTART(m, cp, caddr_t);
556 DMA_FREE_ADDR(cp, bhp->bh_dma, BUF1_LG_SIZE, 0);
563 * Finally, we've got an entry ready for the CP.
564 * So claim the host queue entry and setup the CP-resident
565 * queue entry. The CP will (potentially) grab the supplied
566 * buffers when the descriptor pointer is set.
568 fup->fu_buf1l_tail = hbp->hbq_next;
569 (*hbp->hbq_status) = QSTAT_PENDING;
570 cqp = hbp->hbq_cpelem;
571 cqp->cq_descr = (CP_dma) CP_WRITE((u_long)hbp->hbq_descr_dma);
574 * Update counters, etc for supplied buffers
576 fup->fu_buf1l_cnt += BUF1_LG_ENTSIZE;
577 nbuf -= BUF1_LG_ENTSIZE;
585 * Drain Buffer Supply Queues
587 * This function will free all completed entries at the head of each
588 * buffer supply queue. Since we consider the CP to "own" the buffers
589 * once we put them on a supply queue and since a completed supply queue
590 * entry is only telling us that the CP has accepted the buffers that we
591 * gave to it, there's not much to do here.
593 * May be called in interrupt state.
594 * Must be called with interrupts locked out.
597 * fup pointer to device unit structure
603 fore_buf_drain(Fore_unit *fup)
608 * Drain Strategy 1 Small Queue
612 * Process each completed entry
614 while (*fup->fu_buf1s_head->hbq_status & QSTAT_COMPLETED) {
616 hbp = fup->fu_buf1s_head;
618 if (*hbp->hbq_status & QSTAT_ERROR) {
620 * XXX - what does this mean???
622 log(LOG_ERR, "fore_buf_drain: buf1s queue error\n");
626 * Mark this entry free for use and bump head pointer
627 * to the next entry in the queue
629 *hbp->hbq_status = QSTAT_FREE;
630 fup->fu_buf1s_head = hbp->hbq_next;
635 * Drain Strategy 1 Large Queue
639 * Process each completed entry
641 while (*fup->fu_buf1l_head->hbq_status & QSTAT_COMPLETED) {
643 hbp = fup->fu_buf1l_head;
645 if (*hbp->hbq_status & QSTAT_ERROR) {
647 * XXX - what does this mean???
649 log(LOG_ERR, "fore_buf_drain: buf1l queue error\n");
653 * Mark this entry free for use and bump head pointer
654 * to the next entry in the queue
656 *hbp->hbq_status = QSTAT_FREE;
657 fup->fu_buf1l_head = hbp->hbq_next;
665 * Free Buffer Supply Queue Data Structures
668 * fup pointer to device unit structure
674 fore_buf_free(Fore_unit *fup)
680 * Free any previously supplied and not returned buffers
682 if (fup->fu_flags & CUF_INITED) {
685 * Run through Strategy 1 Small queue
687 while ((bhp = Q_HEAD(fup->fu_buf1s_bq, Buf_handle)) != NULL) {
693 m = (KBuffer *)((caddr_t)bhp - BUF1_SM_HOFF);
696 * Dequeue handle and free buffer
698 DEQUEUE(bhp, Buf_handle, bh_qelem, fup->fu_buf1s_bq);
700 KB_DATASTART(m, cp, caddr_t);
701 DMA_FREE_ADDR(cp, bhp->bh_dma, BUF1_SM_SIZE, 0);
707 * Run through Strategy 1 Large queue
709 while ((bhp = Q_HEAD(fup->fu_buf1l_bq, Buf_handle)) != NULL) {
715 m = (KBuffer *)((caddr_t)bhp - BUF1_LG_HOFF);
718 * Dequeue handle and free buffer
720 DEQUEUE(bhp, Buf_handle, bh_qelem, fup->fu_buf1l_bq);
722 KB_DATASTART(m, cp, caddr_t);
723 DMA_FREE_ADDR(cp, bhp->bh_dma, BUF1_LG_SIZE, 0);
730 * Free the status words
732 if (fup->fu_buf1s_stat) {
733 if (fup->fu_buf1s_statd) {
734 DMA_FREE_ADDR(fup->fu_buf1s_stat, fup->fu_buf1s_statd,
736 (BUF1_SM_QUELEN + BUF1_LG_QUELEN),
739 atm_dev_free((volatile void *)fup->fu_buf1s_stat);
740 fup->fu_buf1s_stat = NULL;
741 fup->fu_buf1s_statd = NULL;
742 fup->fu_buf1l_stat = NULL;
743 fup->fu_buf1l_statd = NULL;
747 * Free the transmit descriptors
749 if (fup->fu_buf1s_desc) {
750 if (fup->fu_buf1s_descd) {
751 DMA_FREE_ADDR(fup->fu_buf1s_desc, fup->fu_buf1s_descd,
753 ((BUF1_SM_QUELEN * BUF1_SM_ENTSIZE) +
754 (BUF1_LG_QUELEN * BUF1_LG_ENTSIZE)),
757 atm_dev_free(fup->fu_buf1s_desc);
758 fup->fu_buf1s_desc = NULL;
759 fup->fu_buf1s_descd = NULL;
760 fup->fu_buf1l_desc = NULL;
761 fup->fu_buf1l_descd = NULL;