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 $
31 * FORE Systems 200-Series Adapter Support
32 * ---------------------------------------
34 * Command queue management
38 #include <dev/hfa/fore_include.h>
41 __RCSID("@(#) $FreeBSD: src/sys/dev/hfa/fore_command.c,v 1.6 1999/08/28 00:41:49 peter Exp $");
47 static struct t_atm_cause fore_cause = {
50 T_ATM_CAUSE_TEMPORARY_FAILURE,
56 * Allocate Command Queue Data Structures
59 * fup pointer to device unit structure
62 * 0 allocations successful
63 * else allocation failed
66 fore_cmd_allocate(fup)
72 * Allocate non-cacheable memory for command status words
74 memp = atm_dev_alloc(sizeof(Q_status) * CMD_QUELEN,
75 QSTAT_ALIGN, ATM_DEV_NONCACHE);
79 fup->fu_cmd_stat = (Q_status *) memp;
81 memp = DMA_GET_ADDR(fup->fu_cmd_stat, sizeof(Q_status) * CMD_QUELEN,
82 QSTAT_ALIGN, ATM_DEV_NONCACHE);
86 fup->fu_cmd_statd = (Q_status *) memp;
89 * Allocate memory for statistics buffer
91 memp = atm_dev_alloc(sizeof(Fore_stats), FORE_STATS_ALIGN, 0);
95 fup->fu_stats = (Fore_stats *) memp;
99 * Allocate memory for PROM buffer
101 memp = atm_dev_alloc(sizeof(Fore_prom), FORE_PROM_ALIGN, 0);
105 fup->fu_prom = (Fore_prom *) memp;
113 * Command Queue Initialization
115 * Allocate and initialize the host-resident command queue structures
116 * and then initialize the CP-resident queue structures.
118 * Called at interrupt level.
121 * fup pointer to device unit structure
127 fore_cmd_initialize(fup)
130 Aali *aap = fup->fu_aali;
138 * Point to CP-resident command queue
140 cqp = (Cmd_queue *)(fup->fu_ram + CP_READ(aap->aali_cmd_q));
143 * Point to host-resident command queue structures
146 qsp = fup->fu_cmd_stat;
147 qsp_dma = fup->fu_cmd_statd;
150 * Loop thru all queue entries and do whatever needs doing
152 for (i = 0; i < CMD_QUELEN; i++) {
155 * Set queue status word to free
160 * Set up host queue entry and link into ring
162 hcp->hcq_cpelem = cqp;
163 hcp->hcq_status = qsp;
164 if (i == (CMD_QUELEN - 1))
165 hcp->hcq_next = fup->fu_cmd_q;
167 hcp->hcq_next = hcp + 1;
170 * Now let the CP into the game
172 cqp->cmdq_status = (CP_dma) CP_WRITE(qsp_dma);
175 * Bump all queue pointers
184 * Initialize queue pointers
186 fup->fu_cmd_head = fup->fu_cmd_tail = fup->fu_cmd_q;
193 * Drain Command Queue
195 * This function will process and free all completed entries at the head
196 * of the command queue.
198 * May be called in interrupt state.
199 * Must be called with interrupts locked out.
202 * fup pointer to device unit structure
215 * Process each completed entry
217 while (*fup->fu_cmd_head->hcq_status & QSTAT_COMPLETED) {
219 hcp = fup->fu_cmd_head;
222 * Process command completion
224 switch (hcp->hcq_code) {
229 if (*hcp->hcq_status & QSTAT_ERROR) {
231 * VCC activation failed - just abort vcc
234 atm_cm_abort(fvp->fv_connvc,
236 fup->fu_pif.pif_cmderrors++;
239 * Successful VCC activation
242 fvp->fv_state = CVS_ACTIVE;
249 case CMD_DACT_VCCOUT:
251 if (*hcp->hcq_status & QSTAT_ERROR) {
253 * VCC dactivation failed - whine
256 "fore_cmd_drain: DACT failed, vcc=(%d,%d)\n",
257 fvp->fv_connvc->cvc_vcc->vc_vpi,
258 fvp->fv_connvc->cvc_vcc->vc_vci);
259 fup->fu_pif.pif_cmderrors++;
262 * Successful VCC dactivation - so what?
268 if (*hcp->hcq_status & QSTAT_ERROR) {
272 fup->fu_pif.pif_cmderrors++;
273 fup->fu_stats_ret = EIO;
276 * Stats are now in unit buffer
278 fup->fu_stats_ret = 0;
280 DMA_FREE_ADDR(fup->fu_stats, fup->fu_statsd,
281 sizeof(Fore_cp_stats), 0);
282 fup->fu_flags &= ~FUF_STATCMD;
285 * Flush received stats data
289 vac_pageflush((addr_t)fup->fu_stats);
292 #if BYTE_ORDER == LITTLE_ENDIAN
294 * Little endian machines receives the stats in
295 * wrong byte order. Instead of swapping in user
296 * land, swap here so that everything going out
297 * of the kernel is in correct host order.
300 u_long *bp = (u_long *)fup->fu_stats;
303 for ( loop = 0; loop < sizeof(Fore_cp_stats)/
304 sizeof(long); loop++, bp++ )
307 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
310 * Poke whoever is waiting on the stats
312 wakeup((caddr_t)&fup->fu_stats);
317 if (*hcp->hcq_status & QSTAT_ERROR) {
319 * Couldn't get PROM data
321 fup->fu_pif.pif_cmderrors++;
323 "fore_cmd_drain: %s%d: GET_PROM failed\n",
324 fup->fu_pif.pif_name,
325 fup->fu_pif.pif_unit);
327 Fore_prom *fp = fup->fu_prom;
330 * Flush received PROM data
334 vac_pageflush((addr_t)fp);
337 * Copy PROM info into config areas
339 KM_COPY(&fp->pr_mac[2],
340 &fup->fu_pif.pif_macaddr,
341 sizeof(struct mac_addr));
342 fup->fu_config.ac_macaddr =
343 fup->fu_pif.pif_macaddr;
344 snprintf(fup->fu_config.ac_hard_vers,
345 sizeof(fup->fu_config.ac_hard_vers),
347 (fp->pr_hwver >> 16) & 0xff,
348 (fp->pr_hwver >> 8) & 0xff,
349 fp->pr_hwver & 0xff);
350 fup->fu_config.ac_serial = fp->pr_serno;
353 DMA_FREE_ADDR(fup->fu_prom, fup->fu_promd,
354 sizeof(Fore_prom), 0);
356 #endif /* FORE_PCI */
359 log(LOG_ERR, "fore_cmd_drain: unknown command %ld\n",
364 * Mark this entry free for use and bump head pointer
365 * to the next entry in the queue
367 *hcp->hcq_status = QSTAT_FREE;
368 fup->fu_cmd_head = hcp->hcq_next;
376 * Free Command Queue Data Structures
379 * fup pointer to device unit structure
391 * Deal with any commands left on the queue
393 if (fup->fu_flags & CUF_INITED) {
394 while (*fup->fu_cmd_head->hcq_status != QSTAT_FREE) {
395 hcp = fup->fu_cmd_head;
397 switch (hcp->hcq_code) {
401 * Just in case someone is sleeping on this
403 fup->fu_stats_ret = EIO;
404 wakeup((caddr_t)&fup->fu_stats);
408 *hcp->hcq_status = QSTAT_FREE;
409 fup->fu_cmd_head = hcp->hcq_next;
414 * Free the statistics buffer
417 atm_dev_free(fup->fu_stats);
418 fup->fu_stats = NULL;
423 * Free the PROM buffer
426 atm_dev_free(fup->fu_prom);
432 * Free the status words
434 if (fup->fu_cmd_stat) {
435 if (fup->fu_cmd_statd) {
436 DMA_FREE_ADDR(fup->fu_cmd_stat, fup->fu_cmd_statd,
437 sizeof(Q_status) * CMD_QUELEN,
440 atm_dev_free((volatile void *)fup->fu_cmd_stat);
441 fup->fu_cmd_stat = NULL;
442 fup->fu_cmd_statd = NULL;