Ansify some remaining function definitions in the kernel.
[dragonfly.git] / sys / dev / atm / hfa / fore_transmit.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
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.
12  *
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.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/dev/hfa/fore_transmit.c,v 1.4 1999/08/28 00:41:53 peter Exp $
27  *      @(#) $DragonFly: src/sys/dev/atm/hfa/fore_transmit.c,v 1.5 2008/03/01 22:03:13 swildner Exp $
28  */
29
30 /*
31  * FORE Systems 200-Series Adapter Support
32  * ---------------------------------------
33  *
34  * Transmit queue management
35  *
36  */
37
38 #include "fore_include.h"
39
40 /*
41  * Allocate Transmit Queue Data Structures
42  *
43  * Arguments:
44  *      fup             pointer to device unit structure
45  *
46  * Returns:
47  *      0               allocations successful
48  *      else            allocation failed
49  */
50 int
51 fore_xmit_allocate(Fore_unit *fup)
52 {
53         void            *memp;
54         H_xmit_queue    *hxp;
55         int             i;
56
57         /*
58          * Allocate non-cacheable memory for transmit status words
59          */
60         memp = atm_dev_alloc(sizeof(Q_status) * XMIT_QUELEN,
61                         QSTAT_ALIGN, ATM_DEV_NONCACHE);
62         if (memp == NULL) {
63                 return (1);
64         }
65         fup->fu_xmit_stat = (Q_status *) memp;
66
67         memp = DMA_GET_ADDR(fup->fu_xmit_stat, sizeof(Q_status) * XMIT_QUELEN,
68                         QSTAT_ALIGN, ATM_DEV_NONCACHE);
69         if (memp == NULL) {
70                 return (1);
71         }
72         fup->fu_xmit_statd = (Q_status *) memp;
73
74         /*
75          * Allocate memory for transmit descriptors
76          *
77          * We will allocate the transmit descriptors individually rather than 
78          * as a single memory block, which will often be larger than a memory
79          * page.  On some systems (eg. FreeBSD) the physical addresses of 
80          * adjacent virtual memory pages are not contiguous.
81          */
82         hxp = fup->fu_xmit_q;
83         for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
84
85                 /*
86                  * Allocate a transmit descriptor for this queue entry
87                  */
88                 hxp->hxq_descr = atm_dev_alloc(sizeof(Xmit_descr),
89                         XMIT_DESCR_ALIGN, 0);
90                 if (hxp->hxq_descr == NULL) {
91                         return (1);
92                 }
93
94                 hxp->hxq_descr_dma = DMA_GET_ADDR(hxp->hxq_descr,
95                         sizeof(Xmit_descr), XMIT_DESCR_ALIGN, 0);
96                 if (hxp->hxq_descr_dma == NULL) {
97                         return (1);
98                 }
99         }
100
101         return (0);
102 }
103
104
105 /*
106  * Transmit Queue Initialization
107  *
108  * Allocate and initialize the host-resident transmit queue structures
109  * and then initialize the CP-resident queue structures.
110  * 
111  * Called at interrupt level.
112  *
113  * Arguments:
114  *      fup             pointer to device unit structure
115  *
116  * Returns:
117  *      none
118  */
119 void
120 fore_xmit_initialize(Fore_unit *fup)
121 {
122         Aali            *aap = fup->fu_aali;
123         Xmit_queue      *cqp;
124         H_xmit_queue    *hxp;
125         Q_status        *qsp;
126         Q_status        *qsp_dma;
127         int             i;
128
129         /*
130          * Point to CP-resident transmit queue
131          */
132         cqp = (Xmit_queue *)(fup->fu_ram + CP_READ(aap->aali_xmit_q));
133
134         /*
135          * Point to host-resident transmit queue structures
136          */
137         hxp = fup->fu_xmit_q;
138         qsp = fup->fu_xmit_stat;
139         qsp_dma = fup->fu_xmit_statd;
140
141         /*
142          * Loop thru all queue entries and do whatever needs doing
143          */
144         for (i = 0; i < XMIT_QUELEN; i++) {
145
146                 /*
147                  * Set queue status word to free
148                  */
149                 *qsp = QSTAT_FREE;
150
151                 /*
152                  * Set up host queue entry and link into ring
153                  */
154                 hxp->hxq_cpelem = cqp;
155                 hxp->hxq_status = qsp;
156                 if (i == (XMIT_QUELEN - 1))
157                         hxp->hxq_next = fup->fu_xmit_q;
158                 else
159                         hxp->hxq_next = hxp + 1;
160
161                 /*
162                  * Now let the CP into the game
163                  */
164                 cqp->cq_status = (CP_dma) CP_WRITE(qsp_dma);
165
166                 /*
167                  * Bump all queue pointers
168                  */
169                 hxp++;
170                 qsp++;
171                 qsp_dma++;
172                 cqp++;
173         }
174
175         /*
176          * Initialize queue pointers
177          */
178         fup->fu_xmit_head = fup->fu_xmit_tail = fup->fu_xmit_q;
179
180         return;
181 }
182
183
184 /*
185  * Drain Transmit Queue
186  *
187  * This function will free all completed entries at the head of the
188  * transmit queue.  Freeing the entry includes releasing the transmit
189  * buffers (buffer chain) back to the kernel.  
190  *
191  * May be called in interrupt state.
192  * Must be called with interrupts locked out.
193  *
194  * Arguments:
195  *      fup             pointer to device unit structure
196  *
197  * Returns:
198  *      none
199  */
200 void
201 fore_xmit_drain(Fore_unit *fup)
202 {
203         H_xmit_queue    *hxp;
204         H_dma           *sdmap;
205         Fore_vcc        *fvp;
206         struct vccb     *vcp;
207         KBuffer         *m;
208
209         /*
210          * Process each completed entry
211          */
212         while (*fup->fu_xmit_head->hxq_status & QSTAT_COMPLETED) {
213
214                 hxp = fup->fu_xmit_head;
215
216                 /*
217                  * Release the entry's DMA addresses and buffer chain
218                  */
219                 for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
220                                 m = KB_NEXT(m), sdmap++) {
221                         caddr_t         cp;
222
223                         KB_DATASTART(m, cp, caddr_t);
224                         DMA_FREE_ADDR(cp, *sdmap, KB_LEN(m), 0);
225                 }
226                 KB_FREEALL(hxp->hxq_buf);
227
228                 /*
229                  * Get VCC over which data was sent (may be null if
230                  * VCC has been closed in the meantime)
231                  */
232                 fvp = hxp->hxq_vcc;
233
234                 /*
235                  * Now collect some statistics
236                  */
237                 if (*hxp->hxq_status & QSTAT_ERROR) {
238                         /*
239                          * CP ran into problems, not much we can do
240                          * other than record the event
241                          */
242                         fup->fu_pif.pif_oerrors++;
243                         if (fvp) {
244                                 vcp = fvp->fv_connvc->cvc_vcc;
245                                 vcp->vc_oerrors++;
246                                 if (vcp->vc_nif)
247                                         vcp->vc_nif->nif_if.if_oerrors++;
248                         }
249                 } else {
250                         /*
251                          * Good transmission
252                          */
253                         int     len = XDS_GET_LEN(hxp->hxq_descr->xd_spec);
254
255                         fup->fu_pif.pif_opdus++;
256                         fup->fu_pif.pif_obytes += len;
257                         if (fvp) {
258                                 vcp = fvp->fv_connvc->cvc_vcc;
259                                 vcp->vc_opdus++;
260                                 vcp->vc_obytes += len;
261                                 if (vcp->vc_nif) {
262                                         vcp->vc_nif->nif_obytes += len;
263                                         vcp->vc_nif->nif_if.if_opackets++;
264                                         vcp->vc_nif->nif_if.if_obytes += len;
265                                 }
266                         }
267                 }
268
269                 /*
270                  * Mark this entry free for use and bump head pointer
271                  * to the next entry in the queue
272                  */
273                 *hxp->hxq_status = QSTAT_FREE;
274                 fup->fu_xmit_head = hxp->hxq_next;
275         }
276
277         return;
278 }
279
280
281 /*
282  * Free Transmit Queue Data Structures
283  *
284  * Arguments:
285  *      fup             pointer to device unit structure
286  *
287  * Returns:
288  *      none
289  */
290 void
291 fore_xmit_free(Fore_unit *fup)
292 {
293         H_xmit_queue    *hxp;
294         H_dma           *sdmap;
295         KBuffer         *m;
296         int             i;
297
298         /*
299          * Free any transmit buffers left on the queue
300          */
301         if (fup->fu_flags & CUF_INITED) {
302                 while (*fup->fu_xmit_head->hxq_status != QSTAT_FREE) {
303
304                         hxp = fup->fu_xmit_head;
305
306                         /*
307                          * Release the entry's DMA addresses and buffer chain
308                          */
309                         for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
310                                         m = KB_NEXT(m), sdmap++) {
311                                 caddr_t         cp;
312
313                                 KB_DATASTART(m, cp, caddr_t);
314                                 DMA_FREE_ADDR(cp, *sdmap, KB_LEN(m), 0);
315                         }
316                         KB_FREEALL(hxp->hxq_buf);
317
318                         *hxp->hxq_status = QSTAT_FREE;
319                         fup->fu_xmit_head = hxp->hxq_next;
320                 }
321         }
322
323         /*
324          * Free the status words
325          */
326         if (fup->fu_xmit_stat) {
327                 if (fup->fu_xmit_statd) {
328                         DMA_FREE_ADDR(fup->fu_xmit_stat, fup->fu_xmit_statd,
329                                 sizeof(Q_status) * XMIT_QUELEN,
330                                 ATM_DEV_NONCACHE);
331                 }
332                 atm_dev_free((volatile void *)fup->fu_xmit_stat);
333                 fup->fu_xmit_stat = NULL;
334                 fup->fu_xmit_statd = NULL;
335         }
336
337         /*
338          * Free the transmit descriptors
339          */
340         hxp = fup->fu_xmit_q;
341         for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
342
343                 /*
344                  * Free the transmit descriptor for this queue entry
345                  */
346                 if (hxp->hxq_descr_dma) {
347                         DMA_FREE_ADDR(hxp->hxq_descr, hxp->hxq_descr_dma,
348                                 sizeof(Xmit_descr), 0);
349                         hxp->hxq_descr_dma = NULL;
350                 }
351
352                 if (hxp->hxq_descr) {
353                         atm_dev_free(hxp->hxq_descr);
354                         hxp->hxq_descr = NULL;
355                 }
356         }
357
358         return;
359 }
360