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: releng/5.3/sys/dev/hfa/fore_command.c 126122 2004-02-22 16:27:28Z mux $
27 *
28 */
29
30 /*
31 * FORE Systems 200-Series Adapter Support
32 * ---------------------------------------
33 *
34 * Command queue management
35 *
36 */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
42 #include <sys/syslog.h>
43 #include <vm/vm.h>
44 #include <vm/pmap.h>
45 #include <net/if.h>
46 #include <netatm/port.h>
47 #include <netatm/queue.h>
48 #include <netatm/atm.h>
49 #include <netatm/atm_sys.h>
50 #include <netatm/atm_sap.h>
51 #include <netatm/atm_cm.h>
52 #include <netatm/atm_if.h>
53 #include <netatm/atm_vc.h>
54 #include <netatm/atm_stack.h>
55 #include <netatm/atm_pcb.h>
56 #include <netatm/atm_var.h>
57 #include <dev/pci/pcivar.h>
58 #include <dev/hfa/fore.h>
59 #include <dev/hfa/fore_aali.h>
60 #include <dev/hfa/fore_slave.h>
61 #include <dev/hfa/fore_stats.h>
62 #include <dev/hfa/fore_var.h>
63 #include <dev/hfa/fore_include.h>
64
65 #ifndef lint
66 __RCSID("@(#) $FreeBSD: releng/5.3/sys/dev/hfa/fore_command.c 126122 2004-02-22 16:27:28Z mux $");
67 #endif
68
69 /*
70 * Local variables
71 */
72 static struct t_atm_cause fore_cause = {
73 T_ATM_ITU_CODING,
74 T_ATM_LOC_USER,
75 T_ATM_CAUSE_TEMPORARY_FAILURE,
76 {0, 0, 0, 0}
77 };
78
79
80 /*
81 * Allocate Command Queue Data Structures
82 *
83 * Arguments:
84 * fup pointer to device unit structure
85 *
86 * Returns:
87 * 0 allocations successful
88 * else allocation failed
89 */
90 int
91 fore_cmd_allocate(fup)
92 Fore_unit *fup;
93 {
94 caddr_t memp;
95 vm_paddr_t pmemp;
96
97 /*
98 * Allocate non-cacheable memory for command status words
99 */
100 memp = atm_dev_alloc(sizeof(Q_status) * CMD_QUELEN,
101 QSTAT_ALIGN, ATM_DEV_NONCACHE);
102 if (memp == NULL) {
103 return (1);
104 }
105 fup->fu_cmd_stat = (Q_status *) memp;
106
107 pmemp = vtophys(fup->fu_cmd_stat);
108 if (pmemp == 0) {
109 return (1);
110 }
111 fup->fu_cmd_statd = pmemp;
112
113 /*
114 * Allocate memory for statistics buffer
115 */
116 memp = atm_dev_alloc(sizeof(Fore_stats), FORE_STATS_ALIGN, 0);
117 if (memp == NULL) {
118 return (1);
119 }
120 fup->fu_stats = (Fore_stats *) memp;
121
122 /*
123 * Allocate memory for PROM buffer
124 */
125 memp = atm_dev_alloc(sizeof(Fore_prom), FORE_PROM_ALIGN, 0);
126 if (memp == NULL) {
127 return (1);
128 }
129 fup->fu_prom = (Fore_prom *) memp;
130
131 return (0);
132 }
133
134
135 /*
136 * Command Queue Initialization
137 *
138 * Allocate and initialize the host-resident command queue structures
139 * and then initialize the CP-resident queue structures.
140 *
141 * Called at interrupt level.
142 *
143 * Arguments:
144 * fup pointer to device unit structure
145 *
146 * Returns:
147 * none
148 */
149 void
150 fore_cmd_initialize(fup)
151 Fore_unit *fup;
152 {
153 Aali *aap = fup->fu_aali;
154 Cmd_queue *cqp;
155 H_cmd_queue *hcp;
156 Q_status *qsp;
157 vm_paddr_t qsp_dma;
158 int i;
159
160 /*
161 * Point to CP-resident command queue
162 */
163 cqp = (Cmd_queue *)(fup->fu_ram + CP_READ(aap->aali_cmd_q));
164
165 /*
166 * Point to host-resident command queue structures
167 */
168 hcp = fup->fu_cmd_q;
169 qsp = fup->fu_cmd_stat;
170 qsp_dma = fup->fu_cmd_statd;
171
172 /*
173 * Loop thru all queue entries and do whatever needs doing
174 */
175 for (i = 0; i < CMD_QUELEN; i++) {
176
177 /*
178 * Set queue status word to free
179 */
180 *qsp = QSTAT_FREE;
181
182 /*
183 * Set up host queue entry and link into ring
184 */
185 hcp->hcq_cpelem = cqp;
186 hcp->hcq_status = qsp;
187 if (i == (CMD_QUELEN - 1))
188 hcp->hcq_next = fup->fu_cmd_q;
189 else
190 hcp->hcq_next = hcp + 1;
191
192 /*
193 * Now let the CP into the game
194 */
195 cqp->cmdq_status = (CP_dma) CP_WRITE(qsp_dma);
196
197 /*
198 * Bump all queue pointers
199 */
200 hcp++;
201 qsp++;
202 qsp_dma += sizeof(Q_status);
203 cqp++;
204 }
205
206 /*
207 * Initialize queue pointers
208 */
209 fup->fu_cmd_head = fup->fu_cmd_tail = fup->fu_cmd_q;
210
211 return;
212 }
213
214
215 /*
216 * Drain Command Queue
217 *
218 * This function will process and free all completed entries at the head
219 * of the command queue.
220 *
221 * May be called in interrupt state.
222 * Must be called with interrupts locked out.
223 *
224 * Arguments:
225 * fup pointer to device unit structure
226 *
227 * Returns:
228 * none
229 */
230 void
231 fore_cmd_drain(fup)
232 Fore_unit *fup;
233 {
234 H_cmd_queue *hcp;
235 Fore_vcc *fvp;
236
237 /*
238 * Process each completed entry
239 * ForeThought 4 may set QSTAT_ERROR without QSTAT_COMPLETED.
240 */
241 while (*fup->fu_cmd_head->hcq_status & (QSTAT_COMPLETED | QSTAT_ERROR)) {
242
243 hcp = fup->fu_cmd_head;
244
245 /*
246 * Process command completion
247 */
248 switch (hcp->hcq_code) {
249
250 case CMD_ACT_VCCIN:
251 case CMD_ACT_VCCOUT:
252 fvp = hcp->hcq_arg;
253 if (*hcp->hcq_status & QSTAT_ERROR) {
254 /*
255 * VCC activation failed - just abort vcc
256 */
257 if (fvp)
258 atm_cm_abort(fvp->fv_connvc,
259 &fore_cause);
260 fup->fu_pif.pif_cmderrors++;
261 } else {
262 /*
263 * Successful VCC activation
264 */
265 if (fvp) {
266 fvp->fv_state = CVS_ACTIVE;
267 fup->fu_open_vcc++;
268 }
269 }
270 break;
271
272 case CMD_DACT_VCCIN:
273 case CMD_DACT_VCCOUT:
274 fvp = hcp->hcq_arg;
275 if (*hcp->hcq_status & QSTAT_ERROR) {
276 /*
277 * VCC dactivation failed - whine
278 */
279 log(LOG_ERR,
280 "fore_cmd_drain: DACT failed, vcc=(%d,%d)\n",
281 fvp->fv_connvc->cvc_vcc->vc_vpi,
282 fvp->fv_connvc->cvc_vcc->vc_vci);
283 fup->fu_pif.pif_cmderrors++;
284 } else {
285 /*
286 * Successful VCC dactivation - so what?
287 */
288 }
289 break;
290
291 case CMD_GET_STATS:
292 if (*hcp->hcq_status & QSTAT_ERROR) {
293 /*
294 * Couldn't get stats
295 */
296 fup->fu_pif.pif_cmderrors++;
297 fup->fu_stats_ret = EIO;
298 } else {
299 /*
300 * Stats are now in unit buffer
301 */
302 fup->fu_stats_ret = 0;
303 }
304 fup->fu_flags &= ~FUF_STATCMD;
305
306 /*
307 * Flush received stats data
308 */
309 #ifdef VAC
310 if (vac)
311 vac_pageflush((addr_t)fup->fu_stats);
312 #endif
313
314 #if BYTE_ORDER == LITTLE_ENDIAN
315 /*
316 * Little endian machines receives the stats in
317 * wrong byte order. Instead of swapping in user
318 * land, swap here so that everything going out
319 * of the kernel is in correct host order.
320 */
321 {
322 u_long *bp = (u_long *)fup->fu_stats;
323 int loop;
324
325 for ( loop = 0; loop < sizeof(Fore_cp_stats)/
326 sizeof(long); loop++, bp++ )
327 *bp = ntohl(*bp);
328 }
329 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
330
331 /*
332 * Poke whoever is waiting on the stats
333 */
334 wakeup(&fup->fu_stats);
335 break;
336
337 case CMD_GET_PROM:
338 if (fup->fu_ft4)
339 goto unknown;
340 goto prom;
341
342 case CMD_GET_PROM4:
343 if (!fup->fu_ft4)
344 goto unknown;
345 prom:
346 if (*hcp->hcq_status & QSTAT_ERROR) {
347 /*
348 * Couldn't get PROM data
349 */
350 fup->fu_pif.pif_cmderrors++;
351 log(LOG_ERR,
352 "fore_cmd_drain: %s%d: GET_PROM failed\n",
353 fup->fu_pif.pif_name,
354 fup->fu_pif.pif_unit);
355 } else {
356 Fore_prom *fp = fup->fu_prom;
357
358 /*
359 * Flush received PROM data
360 */
361 #ifdef VAC
362 if (vac)
363 vac_pageflush((addr_t)fp);
364 #endif
365 /*
366 * Copy PROM info into config areas
367 */
368 bcopy(&fp->pr_mac[2],
369 &fup->fu_pif.pif_macaddr,
370 sizeof(struct mac_addr));
371 fup->fu_config.ac_macaddr =
372 fup->fu_pif.pif_macaddr;
373 snprintf(fup->fu_config.ac_hard_vers,
374 sizeof(fup->fu_config.ac_hard_vers),
375 "%ld.%ld.%ld",
376 (fp->pr_hwver >> 16) & 0xff,
377 (fp->pr_hwver >> 8) & 0xff,
378 fp->pr_hwver & 0xff);
379 fup->fu_config.ac_serial = fp->pr_serno;
380 }
381 break;
382
383 default:
384 unknown:
385 log(LOG_ERR, "fore_cmd_drain: unknown command %ld\n",
386 hcp->hcq_code);
387 }
388
389 /*
390 * Mark this entry free for use and bump head pointer
391 * to the next entry in the queue
392 */
393 *hcp->hcq_status = QSTAT_FREE;
394 fup->fu_cmd_head = hcp->hcq_next;
395 }
396
397 return;
398 }
399
400
401 /*
402 * Free Command Queue Data Structures
403 *
404 * Arguments:
405 * fup pointer to device unit structure
406 *
407 * Returns:
408 * none
409 */
410 void
411 fore_cmd_free(fup)
412 Fore_unit *fup;
413 {
414 H_cmd_queue *hcp;
415
416 /*
417 * Deal with any commands left on the queue
418 */
419 if (fup->fu_flags & CUF_INITED) {
420 while (*fup->fu_cmd_head->hcq_status != QSTAT_FREE) {
421 hcp = fup->fu_cmd_head;
422
423 switch (hcp->hcq_code) {
424
425 case CMD_GET_STATS:
426 /*
427 * Just in case someone is sleeping on this
428 */
429 fup->fu_stats_ret = EIO;
430 wakeup(&fup->fu_stats);
431 break;
432 }
433
434 *hcp->hcq_status = QSTAT_FREE;
435 fup->fu_cmd_head = hcp->hcq_next;
436 }
437 }
438
439 /*
440 * Free the statistics buffer
441 */
442 if (fup->fu_stats) {
443 atm_dev_free(fup->fu_stats);
444 fup->fu_stats = NULL;
445 }
446
447 /*
448 * Free the PROM buffer
449 */
450 if (fup->fu_prom) {
451 atm_dev_free(fup->fu_prom);
452 fup->fu_prom = NULL;
453 }
454
455 /*
456 * Free the status words
457 */
458 if (fup->fu_cmd_stat) {
459 atm_dev_free((volatile void *)fup->fu_cmd_stat);
460 fup->fu_cmd_stat = NULL;
461 fup->fu_cmd_statd = 0;
462 }
463
464 return;
465 }
466
Cache object: efb99a103b4f4b545dd895d9484e1f0f
|