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.5 2006/12/20 18:14:38 dillon Exp $
31 * FORE Systems 200-Series Adapter Support
32 * ---------------------------------------
34 * Command queue management
38 #include "fore_include.h"
43 static struct t_atm_cause fore_cause
= {
46 T_ATM_CAUSE_TEMPORARY_FAILURE
,
52 * Allocate Command Queue Data Structures
55 * fup pointer to device unit structure
58 * 0 allocations successful
59 * else allocation failed
62 fore_cmd_allocate(fup
)
68 * Allocate non-cacheable memory for command status words
70 memp
= atm_dev_alloc(sizeof(Q_status
) * CMD_QUELEN
,
71 QSTAT_ALIGN
, ATM_DEV_NONCACHE
);
75 fup
->fu_cmd_stat
= (Q_status
*) memp
;
77 memp
= DMA_GET_ADDR(fup
->fu_cmd_stat
, sizeof(Q_status
) * CMD_QUELEN
,
78 QSTAT_ALIGN
, ATM_DEV_NONCACHE
);
82 fup
->fu_cmd_statd
= (Q_status
*) memp
;
85 * Allocate memory for statistics buffer
87 memp
= atm_dev_alloc(sizeof(Fore_stats
), FORE_STATS_ALIGN
, 0);
91 fup
->fu_stats
= (Fore_stats
*) memp
;
94 * Allocate memory for PROM buffer
96 memp
= atm_dev_alloc(sizeof(Fore_prom
), FORE_PROM_ALIGN
, 0);
100 fup
->fu_prom
= (Fore_prom
*) memp
;
107 * Command Queue Initialization
109 * Allocate and initialize the host-resident command queue structures
110 * and then initialize the CP-resident queue structures.
112 * Called at interrupt level.
115 * fup pointer to device unit structure
121 fore_cmd_initialize(fup
)
124 Aali
*aap
= fup
->fu_aali
;
132 * Point to CP-resident command queue
134 cqp
= (Cmd_queue
*)(fup
->fu_ram
+ CP_READ(aap
->aali_cmd_q
));
137 * Point to host-resident command queue structures
140 qsp
= fup
->fu_cmd_stat
;
141 qsp_dma
= fup
->fu_cmd_statd
;
144 * Loop thru all queue entries and do whatever needs doing
146 for (i
= 0; i
< CMD_QUELEN
; i
++) {
149 * Set queue status word to free
154 * Set up host queue entry and link into ring
156 hcp
->hcq_cpelem
= cqp
;
157 hcp
->hcq_status
= qsp
;
158 if (i
== (CMD_QUELEN
- 1))
159 hcp
->hcq_next
= fup
->fu_cmd_q
;
161 hcp
->hcq_next
= hcp
+ 1;
164 * Now let the CP into the game
166 cqp
->cmdq_status
= (CP_dma
) CP_WRITE(qsp_dma
);
169 * Bump all queue pointers
178 * Initialize queue pointers
180 fup
->fu_cmd_head
= fup
->fu_cmd_tail
= fup
->fu_cmd_q
;
187 * Drain Command Queue
189 * This function will process and free all completed entries at the head
190 * of the command queue.
192 * May be called in interrupt state.
193 * Must be called with interrupts locked out.
196 * fup pointer to device unit structure
209 * Process each completed entry
211 while (*fup
->fu_cmd_head
->hcq_status
& QSTAT_COMPLETED
) {
213 hcp
= fup
->fu_cmd_head
;
216 * Process command completion
218 switch (hcp
->hcq_code
) {
223 if (*hcp
->hcq_status
& QSTAT_ERROR
) {
225 * VCC activation failed - just abort vcc
228 atm_cm_abort(fvp
->fv_connvc
,
230 fup
->fu_pif
.pif_cmderrors
++;
233 * Successful VCC activation
236 fvp
->fv_state
= CVS_ACTIVE
;
243 case CMD_DACT_VCCOUT
:
245 if (*hcp
->hcq_status
& QSTAT_ERROR
) {
247 * VCC dactivation failed - whine
250 "fore_cmd_drain: DACT failed, vcc=(%d,%d)\n",
251 fvp
->fv_connvc
->cvc_vcc
->vc_vpi
,
252 fvp
->fv_connvc
->cvc_vcc
->vc_vci
);
253 fup
->fu_pif
.pif_cmderrors
++;
256 * Successful VCC dactivation - so what?
262 if (*hcp
->hcq_status
& QSTAT_ERROR
) {
266 fup
->fu_pif
.pif_cmderrors
++;
267 fup
->fu_stats_ret
= EIO
;
270 * Stats are now in unit buffer
272 fup
->fu_stats_ret
= 0;
274 DMA_FREE_ADDR(fup
->fu_stats
, fup
->fu_statsd
,
275 sizeof(Fore_cp_stats
), 0);
276 fup
->fu_flags
&= ~FUF_STATCMD
;
279 * Flush received stats data
283 vac_pageflush((addr_t
)fup
->fu_stats
);
286 #if BYTE_ORDER == LITTLE_ENDIAN
288 * Little endian machines receives the stats in
289 * wrong byte order. Instead of swapping in user
290 * land, swap here so that everything going out
291 * of the kernel is in correct host order.
294 u_long
*bp
= (u_long
*)fup
->fu_stats
;
297 for ( loop
= 0; loop
< sizeof(Fore_cp_stats
)/
298 sizeof(long); loop
++, bp
++ )
301 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
304 * Poke whoever is waiting on the stats
306 wakeup((caddr_t
)&fup
->fu_stats
);
310 if (*hcp
->hcq_status
& QSTAT_ERROR
) {
312 * Couldn't get PROM data
314 fup
->fu_pif
.pif_cmderrors
++;
316 "fore_cmd_drain: %s%d: GET_PROM failed\n",
317 fup
->fu_pif
.pif_name
,
318 fup
->fu_pif
.pif_unit
);
320 Fore_prom
*fp
= fup
->fu_prom
;
323 * Flush received PROM data
327 vac_pageflush((addr_t
)fp
);
330 * Copy PROM info into config areas
332 KM_COPY(&fp
->pr_mac
[2],
333 &fup
->fu_pif
.pif_macaddr
,
334 sizeof(struct mac_addr
));
335 fup
->fu_config
.ac_macaddr
=
336 fup
->fu_pif
.pif_macaddr
;
337 ksnprintf(fup
->fu_config
.ac_hard_vers
,
338 sizeof(fup
->fu_config
.ac_hard_vers
),
340 (fp
->pr_hwver
>> 16) & 0xff,
341 (fp
->pr_hwver
>> 8) & 0xff,
342 fp
->pr_hwver
& 0xff);
343 fup
->fu_config
.ac_serial
= fp
->pr_serno
;
346 DMA_FREE_ADDR(fup
->fu_prom
, fup
->fu_promd
,
347 sizeof(Fore_prom
), 0);
351 log(LOG_ERR
, "fore_cmd_drain: unknown command %ld\n",
356 * Mark this entry free for use and bump head pointer
357 * to the next entry in the queue
359 *hcp
->hcq_status
= QSTAT_FREE
;
360 fup
->fu_cmd_head
= hcp
->hcq_next
;
368 * Free Command Queue Data Structures
371 * fup pointer to device unit structure
383 * Deal with any commands left on the queue
385 if (fup
->fu_flags
& CUF_INITED
) {
386 while (*fup
->fu_cmd_head
->hcq_status
!= QSTAT_FREE
) {
387 hcp
= fup
->fu_cmd_head
;
389 switch (hcp
->hcq_code
) {
393 * Just in case someone is sleeping on this
395 fup
->fu_stats_ret
= EIO
;
396 wakeup((caddr_t
)&fup
->fu_stats
);
400 *hcp
->hcq_status
= QSTAT_FREE
;
401 fup
->fu_cmd_head
= hcp
->hcq_next
;
406 * Free the statistics buffer
409 atm_dev_free(fup
->fu_stats
);
410 fup
->fu_stats
= NULL
;
414 * Free the PROM buffer
417 atm_dev_free(fup
->fu_prom
);
422 * Free the status words
424 if (fup
->fu_cmd_stat
) {
425 if (fup
->fu_cmd_statd
) {
426 DMA_FREE_ADDR(fup
->fu_cmd_stat
, fup
->fu_cmd_statd
,
427 sizeof(Q_status
) * CMD_QUELEN
,
430 atm_dev_free((volatile void *)fup
->fu_cmd_stat
);
431 fup
->fu_cmd_stat
= NULL
;
432 fup
->fu_cmd_statd
= NULL
;