summaryrefslogtreecommitdiffstats
path: root/sys/dev/hfa/fore_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/hfa/fore_init.c')
-rw-r--r--sys/dev/hfa/fore_init.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/sys/dev/hfa/fore_init.c b/sys/dev/hfa/fore_init.c
new file mode 100644
index 0000000..61f4f01
--- /dev/null
+++ b/sys/dev/hfa/fore_init.c
@@ -0,0 +1,314 @@
+/*
+ *
+ * ===================================
+ * HARP | Host ATM Research Platform
+ * ===================================
+ *
+ *
+ * This Host ATM Research Platform ("HARP") file (the "Software") is
+ * made available by Network Computing Services, Inc. ("NetworkCS")
+ * "AS IS". NetworkCS does not provide maintenance, improvements or
+ * support of any kind.
+ *
+ * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
+ * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
+ * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
+ * In no event shall NetworkCS be responsible for any damages, including
+ * but not limited to consequential damages, arising from or relating to
+ * any use of the Software or related support.
+ *
+ * Copyright 1994-1998 Network Computing Services, Inc.
+ *
+ * Copies of this Software may be made, however, the above copyright
+ * notice must be reproduced on all copies.
+ *
+ * @(#) $Id: fore_init.c,v 1.7 1997/05/06 22:09:43 mks Exp $
+ *
+ */
+
+/*
+ * FORE Systems 200-Series Adapter Support
+ * ---------------------------------------
+ *
+ * Cell Processor (CP) initialization routines
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: fore_init.c,v 1.7 1997/05/06 22:09:43 mks Exp $";
+#endif
+
+#include <dev/hfa/fore_include.h>
+
+
+/*
+ * Local functions
+ */
+#ifdef FORE_PCI
+static void fore_get_prom __P((Fore_unit *));
+#endif
+
+
+/*
+ * Begin CP Initialization
+ *
+ * This function will poll for the successful downloading and starting of
+ * the CP microcode program. After the microcode is running, we will allocate
+ * any needed kernel memory (must do it in non-interrupt mode), build the CP
+ * queue configurations and issue an Initialize command to the CP.
+ *
+ * Arguments:
+ * fup pointer to device unit structure
+ *
+ * Returns:
+ * none
+ */
+void
+fore_initialize(fup)
+ Fore_unit *fup;
+{
+ Aali *aap;
+ Init_parms *inp;
+ caddr_t errmsg;
+ u_long vers;
+
+ /*
+ * Must wait until firmware has been downloaded and is running
+ */
+ if (CP_READ(fup->fu_mon->mon_bstat) != BOOT_RUNNING) {
+
+ /*
+ * Try again later
+ */
+ fup->fu_thandle =
+ timeout((KTimeout_ret(*) __P((void *)))fore_initialize,
+ (void *)fup, hz);
+ return;
+ } else
+ callout_handle_init(&fup->fu_thandle);
+
+ /*
+ * Allocate queues and whatever else is needed
+ */
+ if (fore_xmit_allocate(fup)) {
+ errmsg = "transmit queue allocation";
+ goto failed;
+ }
+ if (fore_recv_allocate(fup)) {
+ errmsg = "receive queue allocation";
+ goto failed;
+ }
+ if (fore_buf_allocate(fup)) {
+ errmsg = "buffer supply queue allocation";
+ goto failed;
+ }
+ if (fore_cmd_allocate(fup)) {
+ errmsg = "command queue allocation";
+ goto failed;
+ }
+
+ /*
+ * CP microcode is downloaded - locate shared memory interface
+ */
+ aap = (Aali *)(fup->fu_ram + CP_READ(fup->fu_mon->mon_appl));
+ fup->fu_aali = aap;
+
+ /*
+ * Pick out any interesting info from the microcode
+ */
+ vers = CP_READ(aap->aali_ucode_ver);
+ if (vers < FORE_MIN_UCODE) {
+ errmsg = "unsupported microcode version";
+ goto failed;
+ }
+ sprintf(fup->fu_config.ac_firm_vers, "%d.%d.%d",
+ (vers >> 16) & 0xff, (vers >> 8) & 0xff, vers & 0xff);
+
+#ifdef notdef
+ /*
+ * Turn on CP debugging
+ */
+ aap->aali_hostlog = 1;
+#endif
+
+ /*
+ * Build the initialization block
+ */
+ inp = &aap->aali_init;
+ inp->init_numvcc = CP_WRITE(FORE_MAX_VCC);
+ inp->init_cmd_elem = CP_WRITE(CMD_QUELEN);
+ inp->init_xmit_elem = CP_WRITE(XMIT_QUELEN);
+ inp->init_recv_elem = CP_WRITE(RECV_QUELEN);
+ inp->init_recv_ext = CP_WRITE(RECV_EXTRA_SEGS);
+ inp->init_xmit_ext = CP_WRITE(XMIT_EXTRA_SEGS);
+ inp->init_buf1s.bfs_quelen = CP_WRITE(BUF1_SM_QUELEN);
+ inp->init_buf1s.bfs_bufsize = CP_WRITE(BUF1_SM_SIZE);
+ inp->init_buf1s.bfs_cppool = CP_WRITE(BUF1_SM_CPPOOL);
+ inp->init_buf1s.bfs_entsize = CP_WRITE(BUF1_SM_ENTSIZE);
+ inp->init_buf1l.bfs_quelen = CP_WRITE(BUF1_LG_QUELEN);
+ inp->init_buf1l.bfs_bufsize = CP_WRITE(BUF1_LG_SIZE);
+ inp->init_buf1l.bfs_cppool = CP_WRITE(BUF1_LG_CPPOOL);
+ inp->init_buf1l.bfs_entsize = CP_WRITE(BUF1_LG_ENTSIZE);
+ inp->init_buf2s.bfs_quelen = CP_WRITE(0);
+ inp->init_buf2s.bfs_bufsize = CP_WRITE(0);
+ inp->init_buf2s.bfs_cppool = CP_WRITE(0);
+ inp->init_buf2s.bfs_entsize = CP_WRITE(0);
+ inp->init_buf2l.bfs_quelen = CP_WRITE(0);
+ inp->init_buf2l.bfs_bufsize = CP_WRITE(0);
+ inp->init_buf2l.bfs_cppool = CP_WRITE(0);
+ inp->init_buf2l.bfs_entsize = CP_WRITE(0);
+
+ /*
+ * Enable device interrupts
+ */
+ aap->aali_intr_ena = CP_WRITE(1);
+
+ /*
+ * Issue the Initialize command to the CP and wait for
+ * the CP to interrupt to signal completion
+ */
+ inp->init_status = CP_WRITE(QSTAT_PENDING);
+ inp->init_cmd = CP_WRITE(CMD_INIT | CMD_INTR_REQ);
+ return;
+
+failed:
+ /*
+ * Initialization failure
+ */
+ fore_interface_free(fup);
+ log(LOG_ERR, "fore initialization failed: intf=%s%d, err=%s\n",
+ fup->fu_pif.pif_name, fup->fu_pif.pif_unit, errmsg);
+ return;
+}
+
+
+/*
+ * Complete CP Initialization
+ *
+ * Called after the CP has successfully completed processing of the
+ * Initialize command. We will now finish off our part of the
+ * initialization process by setting up all the host-based queue
+ * management structures.
+ *
+ * Called at interrupt level.
+ *
+ * Arguments:
+ * fup pointer to device unit structure
+ *
+ * Returns:
+ * none
+ */
+void
+fore_initialize_complete(fup)
+ Fore_unit *fup;
+{
+ Aali *aap = fup->fu_aali;
+
+ /*
+ * Log an initialization failure
+ */
+ if (CP_READ(aap->aali_init.init_status) & QSTAT_ERROR) {
+
+ log(LOG_ERR,
+ "fore initialization failed: intf=%s%d, hbeat=0x%x\n",
+ fup->fu_pif.pif_name, fup->fu_pif.pif_unit,
+ CP_READ(aap->aali_heartbeat));
+ return;
+ }
+
+ ATM_DEBUG1("heap=0x%x\n", aap->aali_heap);
+ ATM_DEBUG1("heaplen=0x%x\n", aap->aali_heaplen);
+ ATM_DEBUG1("cmd_q=0x%x\n", aap->aali_cmd_q);
+ ATM_DEBUG1("xmit_q=0x%x\n", aap->aali_xmit_q);
+ ATM_DEBUG1("recv_q=0x%x\n", aap->aali_recv_q);
+ ATM_DEBUG1("buf1s_q=0x%x\n", aap->aali_buf1s_q);
+ ATM_DEBUG1("buf1l_q=0x%x\n", aap->aali_buf1l_q);
+ ATM_DEBUG1("buf2s_q=0x%x\n", aap->aali_buf2s_q);
+ ATM_DEBUG1("buf2l_q=0x%x\n", aap->aali_buf2l_q);
+
+ /*
+ * Initialize all of our queues
+ */
+ fore_xmit_initialize(fup);
+ fore_recv_initialize(fup);
+ fore_buf_initialize(fup);
+ fore_cmd_initialize(fup);
+
+ /*
+ * Mark device initialization completed
+ */
+ fup->fu_flags |= CUF_INITED;
+
+#ifdef FORE_PCI
+ fore_get_prom(fup);
+#endif
+ return;
+}
+
+
+#ifdef FORE_PCI
+/*
+ * Get device PROM values from CP
+ *
+ * This function will issue a GET_PROM command to the CP in order to
+ * initiate the DMA transfer of the CP's PROM structure to the host.
+ * This will be called after CP initialization has completed.
+ * There is (currently) no retry if this fails.
+ *
+ * Called at interrupt level.
+ *
+ * Arguments:
+ * fup pointer to device unit structure
+ *
+ * Returns:
+ * none
+ *
+ */
+static void
+fore_get_prom(fup)
+ Fore_unit *fup;
+{
+ H_cmd_queue *hcp;
+ Cmd_queue *cqp;
+
+ /*
+ * Queue command at end of command queue
+ */
+ hcp = fup->fu_cmd_tail;
+ if ((*hcp->hcq_status) & QSTAT_FREE) {
+
+ /*
+ * Queue entry available, so set our view of things up
+ */
+ hcp->hcq_code = CMD_GET_PROM;
+ hcp->hcq_arg = NULL;
+ fup->fu_cmd_tail = hcp->hcq_next;
+
+ /*
+ * Now set the CP-resident queue entry - the CP will grab
+ * the command when the op-code is set.
+ */
+ cqp = hcp->hcq_cpelem;
+ (*hcp->hcq_status) = QSTAT_PENDING;
+
+ fup->fu_promd = DMA_GET_ADDR(fup->fu_prom, sizeof(Fore_prom),
+ FORE_PROM_ALIGN, 0);
+ if (fup->fu_promd == NULL) {
+ fup->fu_stats->st_drv.drv_cm_nodma++;
+ return;
+ }
+ cqp->cmdq_prom.prom_buffer = (CP_dma) CP_WRITE(fup->fu_promd);
+ cqp->cmdq_prom.prom_cmd = CP_WRITE(CMD_GET_PROM | CMD_INTR_REQ);
+
+ } else {
+ /*
+ * Command queue full
+ */
+ fup->fu_stats->st_drv.drv_cm_full++;
+ }
+
+ return;
+}
+#endif /* FORE_PCI */
+
OpenPOWER on IntegriCloud