]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hfa/fore_init.c
This commit was generated by cvs2svn to compensate for changes in r155094,
[FreeBSD/FreeBSD.git] / sys / dev / hfa / fore_init.c
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$
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$");
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