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.
31 * FORE Systems 200-Series Adapter Support
32 * ---------------------------------------
34 * Cell Processor (CP) initialization routines
38 #include <sys/param.h>
39 #include <sys/kernel.h>
40 #include <sys/systm.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
43 #include <sys/syslog.h>
47 #include <netatm/port.h>
48 #include <netatm/queue.h>
49 #include <netatm/atm.h>
50 #include <netatm/atm_sys.h>
51 #include <netatm/atm_sap.h>
52 #include <netatm/atm_cm.h>
53 #include <netatm/atm_if.h>
54 #include <netatm/atm_stack.h>
55 #include <netatm/atm_pcb.h>
56 #include <netatm/atm_var.h>
57 #include <pci/pcivar.h>
58 #include <dev/hfa/fore.h>
59 #include <dev/hfa/fore_aali.h>
60 #include <dev/hfa/fore_slave.h>
61 #include <dev/hfa/fore_stats.h>
62 #include <dev/hfa/fore_var.h>
63 #include <dev/hfa/fore_include.h>
66 __RCSID("@(#) $FreeBSD$");
73 static void fore_get_prom __P((Fore_unit *));
77 * Begin CP Initialization
79 * This function will poll for the successful downloading and starting of
80 * the CP microcode program. After the microcode is running, we will allocate
81 * any needed kernel memory (must do it in non-interrupt mode), build the CP
82 * queue configurations and issue an Initialize command to the CP.
85 * fup pointer to device unit structure
100 * Must wait until firmware has been downloaded and is running
102 if (CP_READ(fup->fu_mon->mon_bstat) != BOOT_RUNNING) {
108 timeout((KTimeout_ret(*) __P((void *)))fore_initialize,
112 callout_handle_init(&fup->fu_thandle);
115 * Allocate queues and whatever else is needed
117 if (fore_xmit_allocate(fup)) {
118 errmsg = "transmit queue allocation";
121 if (fore_recv_allocate(fup)) {
122 errmsg = "receive queue allocation";
125 if (fore_buf_allocate(fup)) {
126 errmsg = "buffer supply queue allocation";
129 if (fore_cmd_allocate(fup)) {
130 errmsg = "command queue allocation";
135 * CP microcode is downloaded - locate shared memory interface
137 aap = (Aali *)(fup->fu_ram + CP_READ(fup->fu_mon->mon_appl));
141 * Pick out any interesting info from the microcode
143 vers = CP_READ(aap->aali_ucode_ver);
144 if (vers < FORE_MIN_UCODE) {
145 errmsg = "unsupported microcode version";
148 snprintf(fup->fu_config.ac_firm_vers,
149 sizeof(fup->fu_config.ac_firm_vers), "%ld.%ld.%ld",
150 (vers >> 16) & 0xff, (vers >> 8) & 0xff, vers & 0xff);
154 * Turn on CP debugging
156 aap->aali_hostlog = 1;
160 * Build the initialization block
162 inp = &aap->aali_init;
163 inp->init_numvcc = CP_WRITE(FORE_MAX_VCC);
164 inp->init_cmd_elem = CP_WRITE(CMD_QUELEN);
165 inp->init_xmit_elem = CP_WRITE(XMIT_QUELEN);
166 inp->init_recv_elem = CP_WRITE(RECV_QUELEN);
167 inp->init_recv_ext = CP_WRITE(RECV_EXTRA_SEGS);
168 inp->init_xmit_ext = CP_WRITE(XMIT_EXTRA_SEGS);
169 inp->init_buf1s.bfs_quelen = CP_WRITE(BUF1_SM_QUELEN);
170 inp->init_buf1s.bfs_bufsize = CP_WRITE(BUF1_SM_SIZE);
171 inp->init_buf1s.bfs_cppool = CP_WRITE(BUF1_SM_CPPOOL);
172 inp->init_buf1s.bfs_entsize = CP_WRITE(BUF1_SM_ENTSIZE);
173 inp->init_buf1l.bfs_quelen = CP_WRITE(BUF1_LG_QUELEN);
174 inp->init_buf1l.bfs_bufsize = CP_WRITE(BUF1_LG_SIZE);
175 inp->init_buf1l.bfs_cppool = CP_WRITE(BUF1_LG_CPPOOL);
176 inp->init_buf1l.bfs_entsize = CP_WRITE(BUF1_LG_ENTSIZE);
177 inp->init_buf2s.bfs_quelen = CP_WRITE(0);
178 inp->init_buf2s.bfs_bufsize = CP_WRITE(0);
179 inp->init_buf2s.bfs_cppool = CP_WRITE(0);
180 inp->init_buf2s.bfs_entsize = CP_WRITE(0);
181 inp->init_buf2l.bfs_quelen = CP_WRITE(0);
182 inp->init_buf2l.bfs_bufsize = CP_WRITE(0);
183 inp->init_buf2l.bfs_cppool = CP_WRITE(0);
184 inp->init_buf2l.bfs_entsize = CP_WRITE(0);
187 * Enable device interrupts
189 aap->aali_intr_ena = CP_WRITE(1);
192 * Issue the Initialize command to the CP and wait for
193 * the CP to interrupt to signal completion
195 inp->init_status = CP_WRITE(QSTAT_PENDING);
196 inp->init_cmd = CP_WRITE(CMD_INIT | CMD_INTR_REQ);
201 * Initialization failure
203 fore_interface_free(fup);
204 log(LOG_ERR, "fore initialization failed: intf=%s%d, err=%s\n",
205 fup->fu_pif.pif_name, fup->fu_pif.pif_unit, errmsg);
211 * Complete CP Initialization
213 * Called after the CP has successfully completed processing of the
214 * Initialize command. We will now finish off our part of the
215 * initialization process by setting up all the host-based queue
216 * management structures.
218 * Called at interrupt level.
221 * fup pointer to device unit structure
227 fore_initialize_complete(fup)
230 Aali *aap = fup->fu_aali;
233 * Log an initialization failure
235 if (CP_READ(aap->aali_init.init_status) & QSTAT_ERROR) {
238 "fore initialization failed: intf=%s%d, hbeat=0x%lx\n",
239 fup->fu_pif.pif_name, fup->fu_pif.pif_unit,
240 (u_long)CP_READ(aap->aali_heartbeat));
244 ATM_DEBUG1("heap=0x%lx\n", aap->aali_heap);
245 ATM_DEBUG1("heaplen=0x%lx\n", aap->aali_heaplen);
246 ATM_DEBUG1("cmd_q=0x%lx\n", aap->aali_cmd_q);
247 ATM_DEBUG1("xmit_q=0x%lx\n", aap->aali_xmit_q);
248 ATM_DEBUG1("recv_q=0x%lx\n", aap->aali_recv_q);
249 ATM_DEBUG1("buf1s_q=0x%lx\n", aap->aali_buf1s_q);
250 ATM_DEBUG1("buf1l_q=0x%lx\n", aap->aali_buf1l_q);
251 ATM_DEBUG1("buf2s_q=0x%lx\n", aap->aali_buf2s_q);
252 ATM_DEBUG1("buf2l_q=0x%lx\n", aap->aali_buf2l_q);
255 * Initialize all of our queues
257 fore_xmit_initialize(fup);
258 fore_recv_initialize(fup);
259 fore_buf_initialize(fup);
260 fore_cmd_initialize(fup);
263 * Mark device initialization completed
265 fup->fu_flags |= CUF_INITED;
273 * Get device PROM values from CP
275 * This function will issue a GET_PROM command to the CP in order to
276 * initiate the DMA transfer of the CP's PROM structure to the host.
277 * This will be called after CP initialization has completed.
278 * There is (currently) no retry if this fails.
280 * Called at interrupt level.
283 * fup pointer to device unit structure
297 * Queue command at end of command queue
299 hcp = fup->fu_cmd_tail;
300 if ((*hcp->hcq_status) & QSTAT_FREE) {
303 * Queue entry available, so set our view of things up
305 hcp->hcq_code = CMD_GET_PROM;
307 fup->fu_cmd_tail = hcp->hcq_next;
310 * Now set the CP-resident queue entry - the CP will grab
311 * the command when the op-code is set.
313 cqp = hcp->hcq_cpelem;
314 (*hcp->hcq_status) = QSTAT_PENDING;
316 fup->fu_promd = DMA_GET_ADDR(fup->fu_prom, sizeof(Fore_prom),
318 if (fup->fu_promd == NULL) {
319 fup->fu_stats->st_drv.drv_cm_nodma++;
322 cqp->cmdq_prom.prom_buffer = (CP_dma) CP_WRITE(fup->fu_promd);
323 cqp->cmdq_prom.prom_cmd = CP_WRITE(CMD_GET_PROM | CMD_INTR_REQ);
329 fup->fu_stats->st_drv.drv_cm_full++;