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.3 2003/08/07 21:16:49 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;
95 * Allocate memory for PROM buffer
97 memp = atm_dev_alloc(sizeof(Fore_prom), FORE_PROM_ALIGN, 0);
101 fup->fu_prom = (Fore_prom *) memp;
109 * Command Queue Initialization
111 * Allocate and initialize the host-resident command queue structures
112 * and then initialize the CP-resident queue structures.
114 * Called at interrupt level.
117 * fup pointer to device unit structure
123 fore_cmd_initialize(fup)
126 Aali *aap = fup->fu_aali;
134 * Point to CP-resident command queue
136 cqp = (Cmd_queue *)(fup->fu_ram + CP_READ(aap->aali_cmd_q));
139 * Point to host-resident command queue structures
142 qsp = fup->fu_cmd_stat;
143 qsp_dma = fup->fu_cmd_statd;
146 * Loop thru all queue entries and do whatever needs doing
148 for (i = 0; i < CMD_QUELEN; i++) {
151 * Set queue status word to free
156 * Set up host queue entry and link into ring
158 hcp->hcq_cpelem = cqp;
159 hcp->hcq_status = qsp;
160 if (i == (CMD_QUELEN - 1))
161 hcp->hcq_next = fup->fu_cmd_q;
163 hcp->hcq_next = hcp + 1;
166 * Now let the CP into the game
168 cqp->cmdq_status = (CP_dma) CP_WRITE(qsp_dma);
171 * Bump all queue pointers
180 * Initialize queue pointers
182 fup->fu_cmd_head = fup->fu_cmd_tail = fup->fu_cmd_q;
189 * Drain Command Queue
191 * This function will process and free all completed entries at the head
192 * of the command queue.
194 * May be called in interrupt state.
195 * Must be called with interrupts locked out.
198 * fup pointer to device unit structure
211 * Process each completed entry
213 while (*fup->fu_cmd_head->hcq_status & QSTAT_COMPLETED) {
215 hcp = fup->fu_cmd_head;
218 * Process command completion
220 switch (hcp->hcq_code) {
225 if (*hcp->hcq_status & QSTAT_ERROR) {
227 * VCC activation failed - just abort vcc
230 atm_cm_abort(fvp->fv_connvc,
232 fup->fu_pif.pif_cmderrors++;
235 * Successful VCC activation
238 fvp->fv_state = CVS_ACTIVE;
245 case CMD_DACT_VCCOUT:
247 if (*hcp->hcq_status & QSTAT_ERROR) {
249 * VCC dactivation failed - whine
252 "fore_cmd_drain: DACT failed, vcc=(%d,%d)\n",
253 fvp->fv_connvc->cvc_vcc->vc_vpi,
254 fvp->fv_connvc->cvc_vcc->vc_vci);
255 fup->fu_pif.pif_cmderrors++;
258 * Successful VCC dactivation - so what?
264 if (*hcp->hcq_status & QSTAT_ERROR) {
268 fup->fu_pif.pif_cmderrors++;
269 fup->fu_stats_ret = EIO;
272 * Stats are now in unit buffer
274 fup->fu_stats_ret = 0;
276 DMA_FREE_ADDR(fup->fu_stats, fup->fu_statsd,
277 sizeof(Fore_cp_stats), 0);
278 fup->fu_flags &= ~FUF_STATCMD;
281 * Flush received stats data
285 vac_pageflush((addr_t)fup->fu_stats);
288 #if BYTE_ORDER == LITTLE_ENDIAN
290 * Little endian machines receives the stats in
291 * wrong byte order. Instead of swapping in user
292 * land, swap here so that everything going out
293 * of the kernel is in correct host order.
296 u_long *bp = (u_long *)fup->fu_stats;
299 for ( loop = 0; loop < sizeof(Fore_cp_stats)/
300 sizeof(long); loop++, bp++ )
303 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
306 * Poke whoever is waiting on the stats
308 wakeup((caddr_t)&fup->fu_stats);
313 if (*hcp->hcq_status & QSTAT_ERROR) {
315 * Couldn't get PROM data
317 fup->fu_pif.pif_cmderrors++;
319 "fore_cmd_drain: %s%d: GET_PROM failed\n",
320 fup->fu_pif.pif_name,
321 fup->fu_pif.pif_unit);
323 Fore_prom *fp = fup->fu_prom;
326 * Flush received PROM data
330 vac_pageflush((addr_t)fp);
333 * Copy PROM info into config areas
335 KM_COPY(&fp->pr_mac[2],
336 &fup->fu_pif.pif_macaddr,
337 sizeof(struct mac_addr));
338 fup->fu_config.ac_macaddr =
339 fup->fu_pif.pif_macaddr;
340 snprintf(fup->fu_config.ac_hard_vers,
341 sizeof(fup->fu_config.ac_hard_vers),
343 (fp->pr_hwver >> 16) & 0xff,
344 (fp->pr_hwver >> 8) & 0xff,
345 fp->pr_hwver & 0xff);
346 fup->fu_config.ac_serial = fp->pr_serno;
349 DMA_FREE_ADDR(fup->fu_prom, fup->fu_promd,
350 sizeof(Fore_prom), 0);
352 #endif /* FORE_PCI */
355 log(LOG_ERR, "fore_cmd_drain: unknown command %ld\n",
360 * Mark this entry free for use and bump head pointer
361 * to the next entry in the queue
363 *hcp->hcq_status = QSTAT_FREE;
364 fup->fu_cmd_head = hcp->hcq_next;
372 * Free Command Queue Data Structures
375 * fup pointer to device unit structure
387 * Deal with any commands left on the queue
389 if (fup->fu_flags & CUF_INITED) {
390 while (*fup->fu_cmd_head->hcq_status != QSTAT_FREE) {
391 hcp = fup->fu_cmd_head;
393 switch (hcp->hcq_code) {
397 * Just in case someone is sleeping on this
399 fup->fu_stats_ret = EIO;
400 wakeup((caddr_t)&fup->fu_stats);
404 *hcp->hcq_status = QSTAT_FREE;
405 fup->fu_cmd_head = hcp->hcq_next;
410 * Free the statistics buffer
413 atm_dev_free(fup->fu_stats);
414 fup->fu_stats = NULL;
419 * Free the PROM buffer
422 atm_dev_free(fup->fu_prom);
428 * Free the status words
430 if (fup->fu_cmd_stat) {
431 if (fup->fu_cmd_statd) {
432 DMA_FREE_ADDR(fup->fu_cmd_stat, fup->fu_cmd_statd,
433 sizeof(Q_status) * CMD_QUELEN,
436 atm_dev_free((volatile void *)fup->fu_cmd_stat);
437 fup->fu_cmd_stat = NULL;
438 fup->fu_cmd_statd = NULL;