added -y/--side-by-side option
[dfdiff.git] / sys / dev / atm / hfa / fore_command.c
blob0f41c8c8cdeecb3e6a435df3fba8045f336add18
1 /*
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_command.c,v 1.6 1999/08/28 00:41:49 peter Exp $
27 * @(#) $DragonFly: src/sys/dev/atm/hfa/fore_command.c,v 1.6 2008/03/01 22:03:13 swildner Exp $
31 * FORE Systems 200-Series Adapter Support
32 * ---------------------------------------
34 * Command queue management
38 #include "fore_include.h"
41 * Local variables
43 static struct t_atm_cause fore_cause = {
44 T_ATM_ITU_CODING,
45 T_ATM_LOC_USER,
46 T_ATM_CAUSE_TEMPORARY_FAILURE,
47 {0, 0, 0, 0}
52 * Allocate Command Queue Data Structures
54 * Arguments:
55 * fup pointer to device unit structure
57 * Returns:
58 * 0 allocations successful
59 * else allocation failed
61 int
62 fore_cmd_allocate(Fore_unit *fup)
64 caddr_t memp;
67 * Allocate non-cacheable memory for command status words
69 memp = atm_dev_alloc(sizeof(Q_status) * CMD_QUELEN,
70 QSTAT_ALIGN, ATM_DEV_NONCACHE);
71 if (memp == NULL) {
72 return (1);
74 fup->fu_cmd_stat = (Q_status *) memp;
76 memp = DMA_GET_ADDR(fup->fu_cmd_stat, sizeof(Q_status) * CMD_QUELEN,
77 QSTAT_ALIGN, ATM_DEV_NONCACHE);
78 if (memp == NULL) {
79 return (1);
81 fup->fu_cmd_statd = (Q_status *) memp;
84 * Allocate memory for statistics buffer
86 memp = atm_dev_alloc(sizeof(Fore_stats), FORE_STATS_ALIGN, 0);
87 if (memp == NULL) {
88 return (1);
90 fup->fu_stats = (Fore_stats *) memp;
93 * Allocate memory for PROM buffer
95 memp = atm_dev_alloc(sizeof(Fore_prom), FORE_PROM_ALIGN, 0);
96 if (memp == NULL) {
97 return (1);
99 fup->fu_prom = (Fore_prom *) memp;
101 return (0);
106 * Command Queue Initialization
108 * Allocate and initialize the host-resident command queue structures
109 * and then initialize the CP-resident queue structures.
111 * Called at interrupt level.
113 * Arguments:
114 * fup pointer to device unit structure
116 * Returns:
117 * none
119 void
120 fore_cmd_initialize(Fore_unit *fup)
122 Aali *aap = fup->fu_aali;
123 Cmd_queue *cqp;
124 H_cmd_queue *hcp;
125 Q_status *qsp;
126 Q_status *qsp_dma;
127 int i;
130 * Point to CP-resident command queue
132 cqp = (Cmd_queue *)(fup->fu_ram + CP_READ(aap->aali_cmd_q));
135 * Point to host-resident command queue structures
137 hcp = fup->fu_cmd_q;
138 qsp = fup->fu_cmd_stat;
139 qsp_dma = fup->fu_cmd_statd;
142 * Loop thru all queue entries and do whatever needs doing
144 for (i = 0; i < CMD_QUELEN; i++) {
147 * Set queue status word to free
149 *qsp = QSTAT_FREE;
152 * Set up host queue entry and link into ring
154 hcp->hcq_cpelem = cqp;
155 hcp->hcq_status = qsp;
156 if (i == (CMD_QUELEN - 1))
157 hcp->hcq_next = fup->fu_cmd_q;
158 else
159 hcp->hcq_next = hcp + 1;
162 * Now let the CP into the game
164 cqp->cmdq_status = (CP_dma) CP_WRITE(qsp_dma);
167 * Bump all queue pointers
169 hcp++;
170 qsp++;
171 qsp_dma++;
172 cqp++;
176 * Initialize queue pointers
178 fup->fu_cmd_head = fup->fu_cmd_tail = fup->fu_cmd_q;
180 return;
185 * Drain Command Queue
187 * This function will process and free all completed entries at the head
188 * of the command queue.
190 * May be called in interrupt state.
191 * Must be called with interrupts locked out.
193 * Arguments:
194 * fup pointer to device unit structure
196 * Returns:
197 * none
199 void
200 fore_cmd_drain(Fore_unit *fup)
202 H_cmd_queue *hcp;
203 Fore_vcc *fvp;
206 * Process each completed entry
208 while (*fup->fu_cmd_head->hcq_status & QSTAT_COMPLETED) {
210 hcp = fup->fu_cmd_head;
213 * Process command completion
215 switch (hcp->hcq_code) {
217 case CMD_ACT_VCCIN:
218 case CMD_ACT_VCCOUT:
219 fvp = hcp->hcq_arg;
220 if (*hcp->hcq_status & QSTAT_ERROR) {
222 * VCC activation failed - just abort vcc
224 if (fvp)
225 atm_cm_abort(fvp->fv_connvc,
226 &fore_cause);
227 fup->fu_pif.pif_cmderrors++;
228 } else {
230 * Successful VCC activation
232 if (fvp) {
233 fvp->fv_state = CVS_ACTIVE;
234 fup->fu_open_vcc++;
237 break;
239 case CMD_DACT_VCCIN:
240 case CMD_DACT_VCCOUT:
241 fvp = hcp->hcq_arg;
242 if (*hcp->hcq_status & QSTAT_ERROR) {
244 * VCC dactivation failed - whine
246 log(LOG_ERR,
247 "fore_cmd_drain: DACT failed, vcc=(%d,%d)\n",
248 fvp->fv_connvc->cvc_vcc->vc_vpi,
249 fvp->fv_connvc->cvc_vcc->vc_vci);
250 fup->fu_pif.pif_cmderrors++;
251 } else {
253 * Successful VCC dactivation - so what?
256 break;
258 case CMD_GET_STATS:
259 if (*hcp->hcq_status & QSTAT_ERROR) {
261 * Couldn't get stats
263 fup->fu_pif.pif_cmderrors++;
264 fup->fu_stats_ret = EIO;
265 } else {
267 * Stats are now in unit buffer
269 fup->fu_stats_ret = 0;
271 DMA_FREE_ADDR(fup->fu_stats, fup->fu_statsd,
272 sizeof(Fore_cp_stats), 0);
273 fup->fu_flags &= ~FUF_STATCMD;
276 * Flush received stats data
278 #ifdef VAC
279 if (vac)
280 vac_pageflush((addr_t)fup->fu_stats);
281 #endif
283 #if BYTE_ORDER == LITTLE_ENDIAN
285 * Little endian machines receives the stats in
286 * wrong byte order. Instead of swapping in user
287 * land, swap here so that everything going out
288 * of the kernel is in correct host order.
291 u_long *bp = (u_long *)fup->fu_stats;
292 int loop;
294 for ( loop = 0; loop < sizeof(Fore_cp_stats)/
295 sizeof(long); loop++, bp++ )
296 *bp = ntohl(*bp);
298 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
301 * Poke whoever is waiting on the stats
303 wakeup((caddr_t)&fup->fu_stats);
304 break;
306 case CMD_GET_PROM:
307 if (*hcp->hcq_status & QSTAT_ERROR) {
309 * Couldn't get PROM data
311 fup->fu_pif.pif_cmderrors++;
312 log(LOG_ERR,
313 "fore_cmd_drain: %s%d: GET_PROM failed\n",
314 fup->fu_pif.pif_name,
315 fup->fu_pif.pif_unit);
316 } else {
317 Fore_prom *fp = fup->fu_prom;
320 * Flush received PROM data
322 #ifdef VAC
323 if (vac)
324 vac_pageflush((addr_t)fp);
325 #endif
327 * Copy PROM info into config areas
329 KM_COPY(&fp->pr_mac[2],
330 &fup->fu_pif.pif_macaddr,
331 sizeof(struct mac_addr));
332 fup->fu_config.ac_macaddr =
333 fup->fu_pif.pif_macaddr;
334 ksnprintf(fup->fu_config.ac_hard_vers,
335 sizeof(fup->fu_config.ac_hard_vers),
336 "%ld.%ld.%ld",
337 (fp->pr_hwver >> 16) & 0xff,
338 (fp->pr_hwver >> 8) & 0xff,
339 fp->pr_hwver & 0xff);
340 fup->fu_config.ac_serial = fp->pr_serno;
343 DMA_FREE_ADDR(fup->fu_prom, fup->fu_promd,
344 sizeof(Fore_prom), 0);
345 break;
347 default:
348 log(LOG_ERR, "fore_cmd_drain: unknown command %ld\n",
349 hcp->hcq_code);
353 * Mark this entry free for use and bump head pointer
354 * to the next entry in the queue
356 *hcp->hcq_status = QSTAT_FREE;
357 fup->fu_cmd_head = hcp->hcq_next;
360 return;
365 * Free Command Queue Data Structures
367 * Arguments:
368 * fup pointer to device unit structure
370 * Returns:
371 * none
373 void
374 fore_cmd_free(Fore_unit *fup)
376 H_cmd_queue *hcp;
379 * Deal with any commands left on the queue
381 if (fup->fu_flags & CUF_INITED) {
382 while (*fup->fu_cmd_head->hcq_status != QSTAT_FREE) {
383 hcp = fup->fu_cmd_head;
385 switch (hcp->hcq_code) {
387 case CMD_GET_STATS:
389 * Just in case someone is sleeping on this
391 fup->fu_stats_ret = EIO;
392 wakeup((caddr_t)&fup->fu_stats);
393 break;
396 *hcp->hcq_status = QSTAT_FREE;
397 fup->fu_cmd_head = hcp->hcq_next;
402 * Free the statistics buffer
404 if (fup->fu_stats) {
405 atm_dev_free(fup->fu_stats);
406 fup->fu_stats = NULL;
410 * Free the PROM buffer
412 if (fup->fu_prom) {
413 atm_dev_free(fup->fu_prom);
414 fup->fu_prom = NULL;
418 * Free the status words
420 if (fup->fu_cmd_stat) {
421 if (fup->fu_cmd_statd) {
422 DMA_FREE_ADDR(fup->fu_cmd_stat, fup->fu_cmd_statd,
423 sizeof(Q_status) * CMD_QUELEN,
424 ATM_DEV_NONCACHE);
426 atm_dev_free((volatile void *)fup->fu_cmd_stat);
427 fup->fu_cmd_stat = NULL;
428 fup->fu_cmd_statd = NULL;
431 return;