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