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: releng/5.3/sys/dev/hfa/fore_transmit.c 126122 2004-02-22 16:27:28Z mux $");
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: releng/5.3/sys/dev/hfa/fore_transmit.c 126122 2004-02-22 16:27:28Z mux $");
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 vcp->vc_nif->nif_if.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 vcp->vc_nif->nif_if.if_opackets++;
292 #if (defined(BSD) && (BSD >= 199103))
293 vcp->vc_nif->nif_if.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
Cache object: e5e796106857073b91c90f0b2018d713
|