1 /*
2 *
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
6 *
7 *
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.
12 *
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.
20 *
21 * Copyright 1994-1998 Network Computing Services, Inc.
22 *
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
25 *
26 * @(#) $FreeBSD: releng/5.3/sys/dev/hfa/fore_init.c 126075 2004-02-21 19:08:23Z harti $
27 *
28 */
29
30 /*
31 * FORE Systems 200-Series Adapter Support
32 * ---------------------------------------
33 *
34 * Cell Processor (CP) initialization routines
35 *
36 */
37
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>
44 #include <vm/vm.h>
45 #include <vm/pmap.h>
46 #include <net/if.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 <dev/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>
64
65 #ifndef lint
66 __RCSID("@(#) $FreeBSD: releng/5.3/sys/dev/hfa/fore_init.c 126075 2004-02-21 19:08:23Z harti $");
67 #endif
68
69
70 /*
71 * Local functions
72 */
73 static void fore_get_prom(Fore_unit *);
74
75
76 /*
77 * Begin CP Initialization
78 *
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.
83 *
84 * Arguments:
85 * fup pointer to device unit structure
86 *
87 * Returns:
88 * none
89 */
90 void
91 fore_initialize(fup)
92 Fore_unit *fup;
93 {
94 Aali *aap;
95 Init_parms *inp;
96 caddr_t errmsg;
97 u_long vers;
98 u_int c, wait;
99 #define MAX_WAIT 100
100
101 /*
102 * Must wait until firmware has been downloaded and is running
103 */
104 if (CP_READ(fup->fu_mon->mon_bstat) != BOOT_RUNNING) {
105
106 /*
107 * Try again later
108 */
109 fup->fu_thandle =
110 timeout((KTimeout_ret(*)(void *))fore_initialize,
111 (void *)fup, hz);
112 return;
113 } else
114 callout_handle_init(&fup->fu_thandle);
115
116 /*
117 * Allocate queues and whatever else is needed
118 */
119 if (fore_xmit_allocate(fup)) {
120 errmsg = "transmit queue allocation";
121 goto failed;
122 }
123 if (fore_recv_allocate(fup)) {
124 errmsg = "receive queue allocation";
125 goto failed;
126 }
127 if (fore_buf_allocate(fup)) {
128 errmsg = "buffer supply queue allocation";
129 goto failed;
130 }
131 if (fore_cmd_allocate(fup)) {
132 errmsg = "command queue allocation";
133 goto failed;
134 }
135
136 /*
137 * CP microcode is downloaded - locate shared memory interface
138 */
139 aap = (Aali *)(fup->fu_ram + CP_READ(fup->fu_mon->mon_appl));
140 fup->fu_aali = aap;
141
142 /*
143 * Pick out any interesting info from the microcode
144 */
145 vers = CP_READ(aap->aali_ucode_ver);
146 if (vers < FORE_MIN_UCODE) {
147 errmsg = "unsupported microcode version";
148 goto failed;
149 }
150 snprintf(fup->fu_config.ac_firm_vers,
151 sizeof(fup->fu_config.ac_firm_vers), "%ld.%ld.%ld",
152 (vers >> 16) & 0xff, (vers >> 8) & 0xff, vers & 0xff);
153
154 if (((vers >> 16) & 0xff) == 4)
155 fup->fu_ft4 = 1;
156 else
157 fup->fu_ft4 = 0;
158
159 #ifdef notdef
160 /*
161 * Turn on CP debugging
162 */
163 aap->aali_hostlog = 1;
164 #endif
165
166 /*
167 * Build the initialization block
168 */
169 inp = &aap->aali_init;
170 inp->init_numvcc = CP_WRITE(FORE_MAX_VCC);
171 inp->init_cmd_elem = CP_WRITE(CMD_QUELEN);
172 inp->init_xmit_elem = CP_WRITE(XMIT_QUELEN);
173 inp->init_recv_elem = CP_WRITE(RECV_QUELEN);
174 inp->init_recv_ext = CP_WRITE(RECV_EXTRA_SEGS);
175 inp->init_xmit_ext = CP_WRITE(XMIT_EXTRA_SEGS);
176 inp->init_buf1s.bfs_quelen = CP_WRITE(BUF1_SM_QUELEN);
177 inp->init_buf1s.bfs_bufsize = CP_WRITE(BUF1_SM_SIZE);
178 inp->init_buf1s.bfs_cppool = CP_WRITE(BUF1_SM_CPPOOL);
179 inp->init_buf1s.bfs_entsize = CP_WRITE(BUF1_SM_ENTSIZE);
180 inp->init_buf1l.bfs_quelen = CP_WRITE(BUF1_LG_QUELEN);
181 inp->init_buf1l.bfs_bufsize = CP_WRITE(BUF1_LG_SIZE);
182 inp->init_buf1l.bfs_cppool = CP_WRITE(BUF1_LG_CPPOOL);
183 inp->init_buf1l.bfs_entsize = CP_WRITE(BUF1_LG_ENTSIZE);
184 inp->init_buf2s.bfs_quelen = CP_WRITE(0);
185 inp->init_buf2s.bfs_bufsize = CP_WRITE(0);
186 inp->init_buf2s.bfs_cppool = CP_WRITE(0);
187 inp->init_buf2s.bfs_entsize = CP_WRITE(0);
188 inp->init_buf2l.bfs_quelen = CP_WRITE(0);
189 inp->init_buf2l.bfs_bufsize = CP_WRITE(0);
190 inp->init_buf2l.bfs_cppool = CP_WRITE(0);
191 inp->init_buf2l.bfs_entsize = CP_WRITE(0);
192
193 /*
194 * Enable device interrupts
195 */
196 aap->aali_intr_ena = CP_WRITE(1);
197
198 /*
199 * Issue the Initialize command to the CP and wait for
200 * the CP to interrupt to signal completion
201 */
202 inp->init_status = CP_WRITE(QSTAT_PENDING);
203
204 if (!fup->fu_ft4) {
205 inp->init_cmd = CP_WRITE(CMD_INIT | CMD_INTR_REQ);
206 return;
207 }
208 inp->init_cmd = CP_WRITE(CMD_INIT);
209
210 /*
211 * With the ForeThought 4.X image it appears that we need to
212 * busy wait on the initializisation command to complete.
213 * Otherwise the command queue address (the first word
214 * of the queue structure) will be mangled.
215 */
216 c = 0;
217 for (wait = 0; wait < MAX_WAIT; wait++) {
218 c = CP_READ(inp->init_status);
219 if (c & QSTAT_COMPLETED)
220 break;
221 DELAY(1000);
222 }
223 if (c & QSTAT_ERROR) {
224 log(LOG_ERR, "fore initialization failed: intf=%s%d, "
225 "hbeat=0x%lx\n", fup->fu_pif.pif_name,
226 fup->fu_pif.pif_unit, (u_long)CP_READ(aap->aali_heartbeat));
227 fore_interface_free(fup);
228 return;
229 }
230 if (!(c & QSTAT_COMPLETED)) {
231 log(LOG_ERR, "fore initialization timed out: intf=%s%d, "
232 "hbeat=0x%lx\n", fup->fu_pif.pif_name, fup->fu_pif.pif_unit,
233 (u_long)CP_READ(aap->aali_heartbeat));
234 fore_interface_free(fup);
235 return;
236 }
237 fore_initialize_complete(fup);
238 return;
239
240 failed:
241 /*
242 * Initialization failure
243 */
244 fore_interface_free(fup);
245 log(LOG_ERR, "fore initialization failed: intf=%s%d, err=%s\n",
246 fup->fu_pif.pif_name, fup->fu_pif.pif_unit, errmsg);
247 return;
248 }
249
250
251 /*
252 * Complete CP Initialization
253 *
254 * Called after the CP has successfully completed processing of the
255 * Initialize command. We will now finish off our part of the
256 * initialization process by setting up all the host-based queue
257 * management structures.
258 *
259 * Called at interrupt level.
260 *
261 * Arguments:
262 * fup pointer to device unit structure
263 *
264 * Returns:
265 * none
266 */
267 void
268 fore_initialize_complete(fup)
269 Fore_unit *fup;
270 {
271 Aali *aap = fup->fu_aali;
272
273 /*
274 * Log an initialization failure
275 */
276 if (CP_READ(aap->aali_init.init_status) & QSTAT_ERROR) {
277
278 log(LOG_ERR,
279 "fore initialization failed: intf=%s%d, hbeat=0x%lx\n",
280 fup->fu_pif.pif_name, fup->fu_pif.pif_unit,
281 (u_long)CP_READ(aap->aali_heartbeat));
282 return;
283 }
284
285 ATM_DEBUG1("heap=0x%lx\n", aap->aali_heap);
286 ATM_DEBUG1("heaplen=0x%lx\n", aap->aali_heaplen);
287 ATM_DEBUG1("cmd_q=0x%lx\n", aap->aali_cmd_q);
288 ATM_DEBUG1("xmit_q=0x%lx\n", aap->aali_xmit_q);
289 ATM_DEBUG1("recv_q=0x%lx\n", aap->aali_recv_q);
290 ATM_DEBUG1("buf1s_q=0x%lx\n", aap->aali_buf1s_q);
291 ATM_DEBUG1("buf1l_q=0x%lx\n", aap->aali_buf1l_q);
292 ATM_DEBUG1("buf2s_q=0x%lx\n", aap->aali_buf2s_q);
293 ATM_DEBUG1("buf2l_q=0x%lx\n", aap->aali_buf2l_q);
294
295 /*
296 * Initialize all of our queues
297 */
298 fore_xmit_initialize(fup);
299 fore_recv_initialize(fup);
300 fore_buf_initialize(fup);
301 fore_cmd_initialize(fup);
302
303 /*
304 * Mark device initialization completed
305 */
306 fup->fu_flags |= CUF_INITED;
307
308 fore_get_prom(fup);
309 return;
310 }
311
312
313 /*
314 * Get device PROM values from CP
315 *
316 * This function will issue a GET_PROM command to the CP in order to
317 * initiate the DMA transfer of the CP's PROM structure to the host.
318 * This will be called after CP initialization has completed.
319 * There is (currently) no retry if this fails.
320 *
321 * It took me some time to find out that FT3 and FT4 use different
322 * operation codes for GET_PROM.
323 *
324 * Called at interrupt level.
325 *
326 * Arguments:
327 * fup pointer to device unit structure
328 *
329 * Returns:
330 * none
331 *
332 */
333 static void
334 fore_get_prom(fup)
335 Fore_unit *fup;
336 {
337 H_cmd_queue *hcp;
338 Cmd_queue *cqp;
339
340 /*
341 * Queue command at end of command queue
342 */
343 hcp = fup->fu_cmd_tail;
344 if ((*hcp->hcq_status) & QSTAT_FREE) {
345
346 /*
347 * Queue entry available, so set our view of things up
348 */
349 if (fup->fu_ft4)
350 hcp->hcq_code = CMD_GET_PROM4;
351 else
352 hcp->hcq_code = CMD_GET_PROM;
353 hcp->hcq_arg = NULL;
354 fup->fu_cmd_tail = hcp->hcq_next;
355
356 /*
357 * Now set the CP-resident queue entry - the CP will grab
358 * the command when the op-code is set.
359 */
360 cqp = hcp->hcq_cpelem;
361 (*hcp->hcq_status) = QSTAT_PENDING;
362
363 fup->fu_promd = vtophys(fup->fu_prom);
364 if (fup->fu_promd == 0) {
365 fup->fu_stats->st_drv.drv_cm_nodma++;
366 return;
367 }
368 cqp->cmdq_prom.prom_buffer = (CP_dma) CP_WRITE(fup->fu_promd);
369 cqp->cmdq_prom.prom_cmd = CP_WRITE(hcp->hcq_code | CMD_INTR_REQ);
370
371 } else {
372 /*
373 * Command queue full
374 */
375 fup->fu_stats->st_drv.drv_cm_full++;
376 }
377
378 return;
379 }
380
Cache object: ce040a50f564b77a54c400b290c7c097
|