1 /*	$OpenBSD: pdq.c,v 1.12 2002/06/02 22:49:59 deraadt Exp $	*/
2 /*	$NetBSD: pdq.c,v 1.9 1996/10/13 01:37:26 christos Exp $	*/
3 
4 /*-
5  * Copyright (c) 1995,1996 Matt Thomas <matt@3am-software.com>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * Id: pdq.c,v 1.27 1996/06/07 20:02:25 thomas Exp
28  *
29  */
30 
31 /*
32  * DEC PDQ FDDI Controller O/S independent code
33  *
34  * This module should work any PDQ based board.  Note that changes for
35  * MIPS and Alpha architectures (or any other architecture which requires
36  * a flushing of memory or write buffers and/or has incoherent caches)
37  * have yet to be made.
38  *
39  * However, it is expected that the PDQ_CSR_WRITE macro will cause a
40  * flushing of the write buffers.
41  */
42 
43 #define	PDQ_HWSUPPORT	/* for pdq.h */
44 
45 #include "pdqvar.h"
46 #include "pdqreg.h"
47 
48 #define	PDQ_ROUNDUP(n, x)	(((n) + ((x) - 1)) & ~((x) - 1))
49 #define	PDQ_CMD_RX_ALIGNMENT	16
50 
51 #if (defined(PDQTEST) && !defined(PDQ_NOPRINTF)) || defined(PDQVERBOSE)
52 #define	PDQ_PRINTF(x)	printf x
53 #else
54 #define	PDQ_PRINTF(x)	do { } while (0)
55 #endif
56 
57 static const char * const pdq_halt_codes[] = {
58     "Selftest Timeout", "Host Bus Parity Error", "Host Directed Fault",
59     "Software Fault", "Hardware Fault", "PC Trace Path Test",
60     "DMA Error", "Image CRC Error", "Adapter Processer Error"
61 };
62 
63 static const char * const pdq_adapter_states[] = {
64     "Reset", "Upgrade", "DMA Unavailable", "DMA Available",
65     "Link Available", "Link Unavailable", "Halted", "Ring Member"
66 };
67 
68 /*
69  * The following are used in conjunction with
70  * unsolicited events
71  */
72 static const char * const pdq_entities[] = {
73     "Station", "Link", "Phy Port"
74 };
75 
76 static const char * const pdq_station_events[] = {
77     "Trace Received"
78 };
79 
80 static const char * const pdq_station_arguments[] = {
81     "Reason"
82 };
83 
84 static const char * const pdq_link_events[] = {
85     "Transmit Underrun",
86     "Transmit Failed",
87     "Block Check Error (CRC)",
88     "Frame Status Error",
89     "PDU Length Error",
90     NULL,
91     NULL,
92     "Receive Data Overrun",
93     NULL,
94     "No User Buffer",
95     "Ring Initialization Initiated",
96     "Ring Initialization Received",
97     "Ring Beacon Initiated",
98     "Duplicate Address Failure",
99     "Duplicate Token Detected",
100     "Ring Purger Error",
101     "FCI Strip Error",
102     "Trace Initiated",
103     "Directed Beacon Received",
104 };
105 
106 static const char * const pdq_link_arguments[] = {
107     "Reason",
108     "Data Link Header",
109     "Source",
110     "Upstream Neighbor"
111 };
112 
113 static const char * const pdq_phy_events[] = {
114     "LEM Error Monitor Reject",
115     "Elasticy Buffer Error",
116     "Link Confidence Test Reject"
117 };
118 
119 static const char * const pdq_phy_arguments[] = {
120     "Direction"
121 };
122 
123 static const char * const * const pdq_event_arguments[] = {
124     pdq_station_arguments,
125     pdq_link_arguments,
126     pdq_phy_arguments
127 };
128 
129 static const char * const * const pdq_event_codes[] = {
130     pdq_station_events,
131     pdq_link_events,
132     pdq_phy_events
133 };
134 
135 static const char * const pdq_station_types[] = {
136     "SAS", "DAC", "SAC", "NAC", "DAS"
137 };
138 
139 static const char * const pdq_smt_versions[] = { "", "V6.2", "V7.2", "V7.3" };
140 
141 static const char pdq_phy_types[] = "ABSM";
142 
143 static const char * const pdq_pmd_types0[] = {
144     "ANSI Multi-Mode", "ANSI Single-Mode Type 1", "ANSI Single-Mode Type 2",
145     "ANSI Sonet"
146 };
147 
148 static const char * const pdq_pmd_types100[] = {
149     "Low Power", "Thin Wire", "Shielded Twisted Pair",
150     "Unshielded Twisted Pair"
151 };
152 
153 static const char * const * const pdq_pmd_types[] = {
154     pdq_pmd_types0, pdq_pmd_types100
155 };
156 
157 static const char * const pdq_descriptions[] = {
158     "DEFPA PCI",
159     "DEFEA EISA",
160     "DEFTA TC",
161     "DEFAA Futurebus",
162     "DEFQA Q-bus",
163 };
164 
165 static void
pdq_print_fddi_chars(pdq_t * pdq,const pdq_response_status_chars_get_t * rsp)166 pdq_print_fddi_chars(
167     pdq_t *pdq,
168     const pdq_response_status_chars_get_t *rsp)
169 {
170     const char hexchars[] = "0123456789abcdef";
171 
172     printf(PDQ_OS_PREFIX "DEC %s FDDI %s Controller\n",
173 	   PDQ_OS_PREFIX_ARGS, pdq_descriptions[pdq->pdq_type],
174 	   pdq_station_types[rsp->status_chars_get.station_type]);
175 
176     printf(PDQ_OS_PREFIX "FDDI address %c%c:%c%c:%c%c:%c%c:%c%c:%c%c, FW=%c%c%c%c, HW=%c",
177 	   PDQ_OS_PREFIX_ARGS,
178 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[0] >> 4],
179 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[0] & 0x0F],
180 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[1] >> 4],
181 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[1] & 0x0F],
182 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[2] >> 4],
183 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[2] & 0x0F],
184 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[3] >> 4],
185 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[3] & 0x0F],
186 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[4] >> 4],
187 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[4] & 0x0F],
188 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[5] >> 4],
189 	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[5] & 0x0F],
190 	   pdq->pdq_fwrev.fwrev_bytes[0], pdq->pdq_fwrev.fwrev_bytes[1],
191 	   pdq->pdq_fwrev.fwrev_bytes[2], pdq->pdq_fwrev.fwrev_bytes[3],
192 	   rsp->status_chars_get.module_rev.fwrev_bytes[0]);
193 
194     if (rsp->status_chars_get.smt_version_id < PDQ_ARRAY_SIZE(pdq_smt_versions)) {
195 	printf(", SMT %s\n", pdq_smt_versions[rsp->status_chars_get.smt_version_id]);
196     }
197 
198     printf(PDQ_OS_PREFIX "FDDI Port%s = %c (PMD = %s)",
199 	   PDQ_OS_PREFIX_ARGS,
200 	   rsp->status_chars_get.station_type == PDQ_STATION_TYPE_DAS ? "[A]" : "",
201 	   pdq_phy_types[rsp->status_chars_get.phy_type[0]],
202 	   pdq_pmd_types[rsp->status_chars_get.pmd_type[0] / 100][rsp->status_chars_get.pmd_type[0] % 100]);
203 
204     if (rsp->status_chars_get.station_type == PDQ_STATION_TYPE_DAS)
205 	printf(", FDDI Port[B] = %c (PMD = %s)",
206 	       pdq_phy_types[rsp->status_chars_get.phy_type[1]],
207 	       pdq_pmd_types[rsp->status_chars_get.pmd_type[1] / 100][rsp->status_chars_get.pmd_type[1] % 100]);
208 
209     printf("\n");
210 }
211 
212 static void
pdq_init_csrs(pdq_csrs_t * csrs,pdq_bus_t bus,pdq_bus_memaddr_t csr_base,size_t csrsize)213 pdq_init_csrs(
214     pdq_csrs_t *csrs,
215     pdq_bus_t bus,
216     pdq_bus_memaddr_t csr_base,
217     size_t csrsize)
218 {
219     csrs->csr_bus = bus;
220     csrs->csr_base = csr_base;
221     csrs->csr_port_reset		= PDQ_CSR_OFFSET(csr_base,  0 * csrsize);
222     csrs->csr_host_data			= PDQ_CSR_OFFSET(csr_base,  1 * csrsize);
223     csrs->csr_port_control		= PDQ_CSR_OFFSET(csr_base,  2 * csrsize);
224     csrs->csr_port_data_a		= PDQ_CSR_OFFSET(csr_base,  3 * csrsize);
225     csrs->csr_port_data_b		= PDQ_CSR_OFFSET(csr_base,  4 * csrsize);
226     csrs->csr_port_status		= PDQ_CSR_OFFSET(csr_base,  5 * csrsize);
227     csrs->csr_host_int_type_0		= PDQ_CSR_OFFSET(csr_base,  6 * csrsize);
228     csrs->csr_host_int_enable		= PDQ_CSR_OFFSET(csr_base,  7 * csrsize);
229     csrs->csr_type_2_producer		= PDQ_CSR_OFFSET(csr_base,  8 * csrsize);
230     csrs->csr_cmd_response_producer	= PDQ_CSR_OFFSET(csr_base, 10 * csrsize);
231     csrs->csr_cmd_request_producer	= PDQ_CSR_OFFSET(csr_base, 11 * csrsize);
232     csrs->csr_host_smt_producer		= PDQ_CSR_OFFSET(csr_base, 12 * csrsize);
233     csrs->csr_unsolicited_producer	= PDQ_CSR_OFFSET(csr_base, 13 * csrsize);
234 }
235 
236 static void
pdq_init_pci_csrs(pdq_pci_csrs_t * csrs,pdq_bus_t bus,pdq_bus_memaddr_t csr_base,size_t csrsize)237 pdq_init_pci_csrs(
238     pdq_pci_csrs_t *csrs,
239     pdq_bus_t bus,
240     pdq_bus_memaddr_t csr_base,
241     size_t csrsize)
242 {
243     csrs->csr_bus = bus;
244     csrs->csr_base = csr_base;
245     csrs->csr_pfi_mode_control	= PDQ_CSR_OFFSET(csr_base, 16 * csrsize);
246     csrs->csr_pfi_status	= PDQ_CSR_OFFSET(csr_base, 17 * csrsize);
247     csrs->csr_fifo_write	= PDQ_CSR_OFFSET(csr_base, 18 * csrsize);
248     csrs->csr_fifo_read		= PDQ_CSR_OFFSET(csr_base, 19 * csrsize);
249 }
250 
251 static void
pdq_flush_databuf_queue(pdq_databuf_queue_t * q)252 pdq_flush_databuf_queue(
253     pdq_databuf_queue_t *q)
254 {
255     PDQ_OS_DATABUF_T *pdu;
256     for (;;) {
257 	PDQ_OS_DATABUF_DEQUEUE(q, pdu);
258 	if (pdu == NULL)
259 	    return;
260 	PDQ_OS_DATABUF_FREE(pdu);
261     }
262 }
263 
264 static pdq_boolean_t
pdq_do_port_control(const pdq_csrs_t * const csrs,pdq_uint32_t cmd)265 pdq_do_port_control(
266     const pdq_csrs_t * const csrs,
267     pdq_uint32_t cmd)
268 {
269     int cnt = 0;
270     PDQ_CSR_WRITE(csrs, csr_host_int_type_0, PDQ_HOST_INT_CSR_CMD_DONE);
271     PDQ_CSR_WRITE(csrs, csr_port_control, PDQ_PCTL_CMD_ERROR | cmd);
272     while ((PDQ_CSR_READ(csrs, csr_host_int_type_0) & PDQ_HOST_INT_CSR_CMD_DONE) == 0 && cnt < 33000000)
273 	cnt++;
274     PDQ_PRINTF(("CSR cmd spun %d times\n", cnt));
275     if (PDQ_CSR_READ(csrs, csr_host_int_type_0) & PDQ_HOST_INT_CSR_CMD_DONE) {
276 	PDQ_CSR_WRITE(csrs, csr_host_int_type_0, PDQ_HOST_INT_CSR_CMD_DONE);
277 	return (PDQ_CSR_READ(csrs, csr_port_control) & PDQ_PCTL_CMD_ERROR) ? PDQ_FALSE : PDQ_TRUE;
278     }
279     /* adapter failure */
280     PDQ_ASSERT(0);
281     return PDQ_FALSE;
282 }
283 
284 static void
pdq_read_mla(const pdq_csrs_t * const csrs,pdq_lanaddr_t * hwaddr)285 pdq_read_mla(
286     const pdq_csrs_t * const csrs,
287     pdq_lanaddr_t *hwaddr)
288 {
289     pdq_uint32_t data;
290 
291     PDQ_CSR_WRITE(csrs, csr_port_data_a, 0);
292     pdq_do_port_control(csrs, PDQ_PCTL_MLA_READ);
293     data = PDQ_CSR_READ(csrs, csr_host_data);
294 
295     hwaddr->lanaddr_bytes[0] = (data >> 0) & 0xFF;
296     hwaddr->lanaddr_bytes[1] = (data >> 8) & 0xFF;
297     hwaddr->lanaddr_bytes[2] = (data >> 16) & 0xFF;
298     hwaddr->lanaddr_bytes[3] = (data >> 24) & 0xFF;
299 
300     PDQ_CSR_WRITE(csrs, csr_port_data_a, 1);
301     pdq_do_port_control(csrs, PDQ_PCTL_MLA_READ);
302     data = PDQ_CSR_READ(csrs, csr_host_data);
303 
304     hwaddr->lanaddr_bytes[4] = (data >> 0) & 0xFF;
305     hwaddr->lanaddr_bytes[5] = (data >> 8) & 0xFF;
306 }
307 
308 static void
pdq_read_fwrev(const pdq_csrs_t * const csrs,pdq_fwrev_t * fwrev)309 pdq_read_fwrev(
310     const pdq_csrs_t * const csrs,
311     pdq_fwrev_t *fwrev)
312 {
313     pdq_uint32_t data;
314 
315     pdq_do_port_control(csrs, PDQ_PCTL_FW_REV_READ);
316     data = PDQ_CSR_READ(csrs, csr_host_data);
317 
318     fwrev->fwrev_bytes[3] = (data >> 0) & 0xFF;
319     fwrev->fwrev_bytes[2] = (data >> 8) & 0xFF;
320     fwrev->fwrev_bytes[1] = (data >> 16) & 0xFF;
321     fwrev->fwrev_bytes[0] = (data >> 24) & 0xFF;
322 }
323 
324 static pdq_boolean_t
pdq_read_error_log(pdq_t * pdq,pdq_response_error_log_get_t * log_entry)325 pdq_read_error_log(
326     pdq_t *pdq,
327     pdq_response_error_log_get_t *log_entry)
328 {
329     const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
330     pdq_uint32_t *ptr = (pdq_uint32_t *) log_entry;
331 
332     pdq_do_port_control(csrs, PDQ_PCTL_ERROR_LOG_START);
333 
334     while (pdq_do_port_control(csrs, PDQ_PCTL_FW_REV_READ) == PDQ_TRUE) {
335 	*ptr++ = PDQ_CSR_READ(csrs, csr_host_data);
336 	if ((pdq_uint8_t *) ptr - (pdq_uint8_t *) log_entry == sizeof(*log_entry))
337 	    break;
338     }
339     return (ptr == (pdq_uint32_t *) log_entry) ? PDQ_FALSE : PDQ_TRUE;
340 }
341 
342 static pdq_chip_rev_t
pdq_read_chiprev(const pdq_csrs_t * const csrs)343 pdq_read_chiprev(
344     const pdq_csrs_t * const csrs)
345 {
346     pdq_uint32_t data;
347 
348     PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_SUB_CMD_PDQ_REV_GET);
349     pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD);
350     data = PDQ_CSR_READ(csrs, csr_host_data);
351 
352     return (pdq_chip_rev_t) data;
353 }
354 
355 static const struct {
356     size_t cmd_len;
357     size_t rsp_len;
358     const char *cmd_name;
359 } pdq_cmd_info[] = {
360     { sizeof(pdq_cmd_generic_t),		/* 0 - PDQC_START */
361       sizeof(pdq_response_generic_t),
362       "Start"
363     },
364     { sizeof(pdq_cmd_filter_set_t),		/* 1 - PDQC_FILTER_SET */
365       sizeof(pdq_response_generic_t),
366       "Filter Set"
367     },
368     { sizeof(pdq_cmd_generic_t),		/* 2 - PDQC_FILTER_GET */
369       sizeof(pdq_response_filter_get_t),
370       "Filter Get"
371     },
372     { sizeof(pdq_cmd_chars_set_t),		/* 3 - PDQC_CHARS_SET */
373       sizeof(pdq_response_generic_t),
374       "Chars Set"
375     },
376     { sizeof(pdq_cmd_generic_t),		/* 4 - PDQC_STATUS_CHARS_GET */
377       sizeof(pdq_response_status_chars_get_t),
378       "Status Chars Get"
379     },
380 #if 0
381     { sizeof(pdq_cmd_generic_t),		/* 5 - PDQC_COUNTERS_GET */
382       sizeof(pdq_response_counters_get_t),
383       "Counters Get"
384     },
385     { sizeof(pdq_cmd_counters_set_t),		/* 6 - PDQC_COUNTERS_SET */
386       sizeof(pdq_response_generic_t),
387       "Counters Set"
388     },
389 #else
390     { 0, 0, "Counters Get" },
391     { 0, 0, "Counters Set" },
392 #endif
393     { sizeof(pdq_cmd_addr_filter_set_t),	/* 7 - PDQC_ADDR_FILTER_SET */
394       sizeof(pdq_response_generic_t),
395       "Addr Filter Set"
396     },
397     { sizeof(pdq_cmd_generic_t),		/* 8 - PDQC_ADDR_FILTER_GET */
398       sizeof(pdq_response_addr_filter_get_t),
399       "Addr Filter Get"
400     },
401 #if 0
402     { sizeof(pdq_cmd_generic_t),		/* 9 - PDQC_ERROR_LOG_CLEAR */
403       sizeof(pdq_response_generic_t),
404       "Error Log Clear"
405     },
406     { sizeof(pdq_cmd_generic_t),		/* 10 - PDQC_ERROR_LOG_SET */
407       sizeof(pdq_response_generic_t),
408       "Error Log Set"
409     },
410     { sizeof(pdq_cmd_generic_t),		/* 11 - PDQC_FDDI_MIB_GET */
411       sizeof(pdq_response_generic_t),
412       "FDDI MIB Get"
413     },
414     { sizeof(pdq_cmd_generic_t),		/* 12 - PDQC_DEC_EXT_MIB_GET */
415       sizeof(pdq_response_generic_t),
416       "DEC Ext MIB Get"
417     },
418     { sizeof(pdq_cmd_generic_t),		/* 13 - PDQC_DEC_SPECIFIC_GET */
419       sizeof(pdq_response_generic_t),
420       "DEC Specific Get"
421     },
422     { sizeof(pdq_cmd_generic_t),		/* 14 - PDQC_SNMP_SET */
423       sizeof(pdq_response_generic_t),
424       "SNMP Set"
425     },
426     { 0, 0, "N/A" },
427     { sizeof(pdq_cmd_generic_t),		/* 16 - PDQC_SMT_MIB_GET */
428       sizeof(pdq_response_generic_t),
429       "SMT MIB Get"
430     },
431     { sizeof(pdq_cmd_generic_t),		/* 17 - PDQC_SMT_MIB_SET */
432       sizeof(pdq_response_generic_t),
433       "SMT MIB Set",
434     },
435 #endif
436 };
437 
438 static void
pdq_queue_commands(pdq_t * pdq)439 pdq_queue_commands(
440     pdq_t *pdq)
441 {
442     const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
443     pdq_command_info_t * const ci = &pdq->pdq_command_info;
444     pdq_descriptor_block_t * const dbp = pdq->pdq_dbp;
445     pdq_cmd_code_t op;
446     pdq_uint32_t cmdlen, rsplen, mask;
447 
448     /*
449      * If there are commands or responses active or there aren't
450      * any pending commands, then don't queue any more.
451      */
452     if (ci->ci_command_active || ci->ci_pending_commands == 0)
453 	return;
454 
455     /*
456      * Determine which command needs to be queued.
457      */
458     op = PDQC_SMT_MIB_SET;
459     for (mask = 1 << ((int) op); (mask & ci->ci_pending_commands) == 0; mask >>= 1)
460 	op = (pdq_cmd_code_t) ((int) op - 1);
461     /*
462      * Obtain the sizes needed for the command and response.
463      * Round up to PDQ_CMD_RX_ALIGNMENT so the receive buffer is
464      * always properly aligned.
465      */
466     cmdlen = PDQ_ROUNDUP(pdq_cmd_info[op].cmd_len, PDQ_CMD_RX_ALIGNMENT);
467     rsplen = PDQ_ROUNDUP(pdq_cmd_info[op].rsp_len, PDQ_CMD_RX_ALIGNMENT);
468     if (cmdlen < rsplen)
469 	cmdlen = rsplen;
470     /*
471      * Since only one command at a time will be queued, there will always
472      * be enough space.
473      */
474 
475     /*
476      * Obtain and fill in the descriptor for the command (descriptor is
477      * pre-initialized)
478      */
479     dbp->pdqdb_command_requests[ci->ci_request_producer].txd_seg_len = cmdlen;
480     PDQ_ADVANCE(ci->ci_request_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_requests));
481 
482     /*
483      * Obtain and fill in the descriptor for the response (descriptor is
484      * pre-initialized)
485      */
486     dbp->pdqdb_command_responses[ci->ci_response_producer].rxd_seg_len_hi = cmdlen / 16;
487     PDQ_ADVANCE(ci->ci_response_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_responses));
488 
489     /*
490      * Clear the command area, set the opcode, and the command from the pending
491      * mask.
492      */
493 
494     PDQ_OS_MEMZERO(ci->ci_bufstart, cmdlen);
495     *(pdq_cmd_code_t *) ci->ci_bufstart = op;
496     ci->ci_pending_commands &= ~mask;
497 
498     /*
499      * Fill in the command area, if needed.
500      */
501     switch (op) {
502 	case PDQC_FILTER_SET: {
503 	    pdq_cmd_filter_set_t *filter_set = (pdq_cmd_filter_set_t *) ci->ci_bufstart;
504 	    unsigned idx = 0;
505 	    filter_set->filter_set_items[idx].item_code = PDQI_IND_GROUP_PROM;
506 	    filter_set->filter_set_items[idx].filter_state = (pdq->pdq_flags & PDQ_PROMISC ? PDQ_FILTER_PASS : PDQ_FILTER_BLOCK);
507 	    idx++;
508 	    filter_set->filter_set_items[idx].item_code = PDQI_GROUP_PROM;
509 	    filter_set->filter_set_items[idx].filter_state = (pdq->pdq_flags & PDQ_ALLMULTI ? PDQ_FILTER_PASS : PDQ_FILTER_BLOCK);
510 	    idx++;
511 	    filter_set->filter_set_items[idx].item_code = PDQI_SMT_PROM;
512 	    filter_set->filter_set_items[idx].filter_state = ((pdq->pdq_flags & (PDQ_PROMISC|PDQ_PASS_SMT)) == (PDQ_PROMISC|PDQ_PASS_SMT) ? PDQ_FILTER_PASS : PDQ_FILTER_BLOCK);
513 	    idx++;
514 	    filter_set->filter_set_items[idx].item_code = PDQI_SMT_USER;
515 	    filter_set->filter_set_items[idx].filter_state = (pdq->pdq_flags & PDQ_PASS_SMT ? PDQ_FILTER_PASS : PDQ_FILTER_BLOCK);
516 	    idx++;
517 	    filter_set->filter_set_items[idx].item_code = PDQI_EOL;
518 	    break;
519 	}
520 	case PDQC_ADDR_FILTER_SET: {
521 	    pdq_cmd_addr_filter_set_t *addr_filter_set = (pdq_cmd_addr_filter_set_t *) ci->ci_bufstart;
522 	    pdq_lanaddr_t *addr = addr_filter_set->addr_filter_set_addresses;
523 	    addr->lanaddr_bytes[0] = 0xFF;
524 	    addr->lanaddr_bytes[1] = 0xFF;
525 	    addr->lanaddr_bytes[2] = 0xFF;
526 	    addr->lanaddr_bytes[3] = 0xFF;
527 	    addr->lanaddr_bytes[4] = 0xFF;
528 	    addr->lanaddr_bytes[5] = 0xFF;
529 	    addr++;
530 	    pdq_os_addr_fill(pdq, addr, 61);
531 	    break;
532 	}
533 	default:
534 	    break;
535     }
536     /*
537      * At this point the command is done.  All that needs to be done is to
538      * produce it to the PDQ.
539      */
540     PDQ_PRINTF(("PDQ Queue Command Request: %s queued\n",
541 		pdq_cmd_info[op].cmd_name));
542 
543     ci->ci_command_active++;
544     PDQ_CSR_WRITE(csrs, csr_cmd_response_producer, ci->ci_response_producer | (ci->ci_response_completion << 8));
545     PDQ_CSR_WRITE(csrs, csr_cmd_request_producer, ci->ci_request_producer | (ci->ci_request_completion << 8));
546 }
547 
548 static void
pdq_process_command_responses(pdq_t * const pdq)549 pdq_process_command_responses(
550     pdq_t * const pdq)
551 {
552     const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
553     pdq_command_info_t * const ci = &pdq->pdq_command_info;
554     volatile const pdq_consumer_block_t * const cbp = pdq->pdq_cbp;
555     pdq_descriptor_block_t * const dbp = pdq->pdq_dbp;
556     const pdq_response_generic_t *rspgen;
557 
558     /*
559      * We have to process the command and response in tandem so
560      * just wait for the response to be consumed.  If it has been
561      * consumed then the command must have been as well.
562      */
563 
564     if (cbp->pdqcb_command_response == ci->ci_response_completion)
565 	return;
566 
567     PDQ_ASSERT(cbp->pdqcb_command_request != ci->ci_request_completion);
568 
569     rspgen = (const pdq_response_generic_t *) ci->ci_bufstart;
570     PDQ_ASSERT(rspgen->generic_status == PDQR_SUCCESS);
571     PDQ_PRINTF(("PDQ Process Command Response: %s completed (status=%d)\n",
572 		pdq_cmd_info[rspgen->generic_op].cmd_name,
573 		rspgen->generic_status));
574 
575     if (rspgen->generic_op == PDQC_STATUS_CHARS_GET && (pdq->pdq_flags & PDQ_PRINTCHARS)) {
576 	pdq->pdq_flags &= ~PDQ_PRINTCHARS;
577 	pdq_print_fddi_chars(pdq, (const pdq_response_status_chars_get_t *) rspgen);
578     }
579 
580     PDQ_ADVANCE(ci->ci_request_completion, 1, PDQ_RING_MASK(dbp->pdqdb_command_requests));
581     PDQ_ADVANCE(ci->ci_response_completion, 1, PDQ_RING_MASK(dbp->pdqdb_command_responses));
582     ci->ci_command_active = 0;
583 
584     if (ci->ci_pending_commands != 0) {
585 	pdq_queue_commands(pdq);
586     } else {
587 	PDQ_CSR_WRITE(csrs, csr_cmd_response_producer,
588 		      ci->ci_response_producer | (ci->ci_response_completion << 8));
589 	PDQ_CSR_WRITE(csrs, csr_cmd_request_producer,
590 		      ci->ci_request_producer | (ci->ci_request_completion << 8));
591     }
592 }
593 
594 /*
595  * This following routine processes unsolicited events.
596  * In addition, it also fills the unsolicited queue with
597  * event buffers so it can be used to initialize the queue
598  * as well.
599  */
600 static void
pdq_process_unsolicited_events(pdq_t * pdq)601 pdq_process_unsolicited_events(
602     pdq_t *pdq)
603 {
604     const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
605     pdq_unsolicited_info_t *ui = &pdq->pdq_unsolicited_info;
606     volatile const pdq_consumer_block_t *cbp = pdq->pdq_cbp;
607     pdq_descriptor_block_t *dbp = pdq->pdq_dbp;
608     const pdq_unsolicited_event_t *event;
609     pdq_rxdesc_t *rxd;
610 
611     /*
612      * Process each unsolicited event (if any).
613      */
614 
615     while (cbp->pdqcb_unsolicited_event != ui->ui_completion) {
616 	rxd = &dbp->pdqdb_unsolicited_events[ui->ui_completion];
617 	event = &ui->ui_events[ui->ui_completion & (PDQ_NUM_UNSOLICITED_EVENTS-1)];
618 
619 	switch (event->event_type) {
620 	    case PDQ_UNSOLICITED_EVENT: {
621 		printf(PDQ_OS_PREFIX "Unsolicited Event: %s: %s",
622 		       PDQ_OS_PREFIX_ARGS,
623 		       pdq_entities[event->event_entity],
624 		       pdq_event_codes[event->event_entity][event->event_code.value]);
625 		if (event->event_entity == PDQ_ENTITY_PHY_PORT)
626 		    printf("[%d]", event->event_index);
627 		printf("\n");
628 		break;
629 	    }
630 	    case PDQ_UNSOLICITED_COUNTERS: {
631 		break;
632 	    }
633 	}
634 	PDQ_ADVANCE(ui->ui_completion, 1, PDQ_RING_MASK(dbp->pdqdb_unsolicited_events));
635 	ui->ui_free++;
636     }
637 
638     /*
639      * Now give back the event buffers back to the PDQ.
640      */
641     PDQ_ADVANCE(ui->ui_producer, ui->ui_free, PDQ_RING_MASK(dbp->pdqdb_unsolicited_events));
642     ui->ui_free = 0;
643 
644     PDQ_CSR_WRITE(csrs, csr_unsolicited_producer,
645 		  ui->ui_producer | (ui->ui_completion << 8));
646 }
647 
648 static void
pdq_process_received_data(pdq_t * pdq,pdq_rx_info_t * rx,pdq_rxdesc_t * receives,pdq_uint32_t completion_goal,pdq_uint32_t ring_mask)649 pdq_process_received_data(
650     pdq_t *pdq,
651     pdq_rx_info_t *rx,
652     pdq_rxdesc_t *receives,
653     pdq_uint32_t completion_goal,
654     pdq_uint32_t ring_mask)
655 {
656     pdq_uint32_t completion = rx->rx_completion;
657     pdq_uint32_t producer = rx->rx_producer;
658     PDQ_OS_DATABUF_T **buffers = (PDQ_OS_DATABUF_T **) rx->rx_buffers;
659     pdq_rxdesc_t *rxd;
660     pdq_uint32_t idx;
661 
662     while (completion != completion_goal) {
663 	PDQ_OS_DATABUF_T *fpdu, *lpdu, *npdu;
664 	pdq_uint8_t *dataptr;
665 	pdq_uint32_t fc, datalen, pdulen, segcnt;
666 	pdq_rxstatus_t status;
667 
668 	fpdu = lpdu = buffers[completion];
669 	PDQ_ASSERT(fpdu != NULL);
670 
671 	dataptr = PDQ_OS_DATABUF_PTR(fpdu);
672 	status = *(pdq_rxstatus_t *) dataptr;
673 	if ((status.rxs_status & 0x200000) == 0) {
674 	    datalen = status.rxs_status & 0x1FFF;
675 	    fc = dataptr[PDQ_RX_FC_OFFSET];
676 	    switch (fc & (PDQ_FDDIFC_C|PDQ_FDDIFC_L|PDQ_FDDIFC_F)) {
677 		case PDQ_FDDI_LLC_ASYNC:
678 		case PDQ_FDDI_LLC_SYNC:
679 		case PDQ_FDDI_IMP_ASYNC:
680 		case PDQ_FDDI_IMP_SYNC: {
681 		    if (datalen > PDQ_FDDI_MAX || datalen < PDQ_FDDI_LLC_MIN) {
682 			PDQ_PRINTF(("discard: bad length %d\n", datalen));
683 			goto discard_frame;
684 		    }
685 		    break;
686 		}
687 		case PDQ_FDDI_SMT: {
688 		    if (datalen > PDQ_FDDI_MAX || datalen < PDQ_FDDI_SMT_MIN)
689 			goto discard_frame;
690 		    break;
691 		}
692 		default: {
693 		    PDQ_PRINTF(("discard: bad fc 0x%x\n", fc));
694 		    goto discard_frame;
695 		}
696 	    }
697 	    /*
698 	     * Update the lengths of the data buffers now that we know
699 	     * the real length.
700 	     */
701 	    pdulen = datalen - 4 /* CRC */;
702 	    segcnt = (pdulen + PDQ_RX_FC_OFFSET + PDQ_OS_DATABUF_SIZE - 1) / PDQ_OS_DATABUF_SIZE;
703 	    PDQ_OS_DATABUF_ALLOC(npdu);
704 	    if (npdu == NULL) {
705 		PDQ_PRINTF(("discard: no databuf #0\n"));
706 		goto discard_frame;
707 	    }
708 	    buffers[completion] = npdu;
709 	    for (idx = 1; idx < segcnt; idx++) {
710 		PDQ_OS_DATABUF_ALLOC(npdu);
711 		if (npdu == NULL) {
712 		    PDQ_OS_DATABUF_NEXT_SET(lpdu, NULL);
713 		    PDQ_OS_DATABUF_FREE(fpdu);
714 		    goto discard_frame;
715 		}
716 		PDQ_OS_DATABUF_NEXT_SET(lpdu, buffers[(completion + idx) & ring_mask]);
717 		lpdu = PDQ_OS_DATABUF_NEXT(lpdu);
718 		buffers[(completion + idx) & ring_mask] = npdu;
719 	    }
720 	    PDQ_OS_DATABUF_NEXT_SET(lpdu, NULL);
721 	    for (idx = 0; idx < PDQ_RX_SEGCNT; idx++) {
722 		buffers[(producer + idx) & ring_mask] =
723 		    buffers[(completion + idx) & ring_mask];
724 		buffers[(completion + idx) & ring_mask] = NULL;
725 	    }
726 	    PDQ_OS_DATABUF_ADJ(fpdu, PDQ_RX_FC_OFFSET);
727 	    if (segcnt == 1) {
728 		PDQ_OS_DATABUF_LEN_SET(fpdu, pdulen);
729 	    } else {
730 		PDQ_OS_DATABUF_LEN_SET(lpdu, pdulen + PDQ_RX_FC_OFFSET - (segcnt - 1) * PDQ_OS_DATABUF_SIZE);
731 	    }
732 	    pdq_os_receive_pdu(pdq, fpdu, pdulen);
733 	    rx->rx_free += PDQ_RX_SEGCNT;
734 	    PDQ_ADVANCE(producer, PDQ_RX_SEGCNT, ring_mask);
735 	    PDQ_ADVANCE(completion, PDQ_RX_SEGCNT, ring_mask);
736 	    continue;
737 	} else {
738 	    PDQ_PRINTF(("discard: bad pdu 0x%x(%d.%d.%d.%d.%d)\n", status.rxs_status,
739 			status.rxs_rcc_badpdu, status.rxs_rcc_badcrc,
740 			status.rxs_rcc_reason, status.rxs_fsc, status.rxs_fsb_e));
741 	    if (status.rxs_rcc_reason == 7)
742 		goto discard_frame;
743 	    if (status.rxs_rcc_reason != 0) {
744 		/* hardware fault */
745 	    }
746 	    if (status.rxs_rcc_badcrc) {
747 		printf(PDQ_OS_PREFIX " MAC CRC error (source=%x-%x-%x-%x-%x-%x)\n",
748 		       PDQ_OS_PREFIX_ARGS,
749 		       dataptr[PDQ_RX_FC_OFFSET+1],
750 		       dataptr[PDQ_RX_FC_OFFSET+2],
751 		       dataptr[PDQ_RX_FC_OFFSET+3],
752 		       dataptr[PDQ_RX_FC_OFFSET+4],
753 		       dataptr[PDQ_RX_FC_OFFSET+5],
754 		       dataptr[PDQ_RX_FC_OFFSET+6]);
755 		/* rx->rx_badcrc++; */
756 	    } else if (status.rxs_fsc == 0 || status.rxs_fsb_e == 1) {
757 		/* rx->rx_frame_status_errors++; */
758 	    } else {
759 		/* hardware fault */
760 	    }
761 	}
762       discard_frame:
763 	/*
764 	 * Discarded frames go right back on the queue; therefore
765 	 * ring entries were freed.
766 	 */
767 	for (idx = 0; idx < PDQ_RX_SEGCNT; idx++) {
768 	    buffers[producer] = buffers[completion];
769 	    buffers[completion] = NULL;
770 	    rxd = &receives[rx->rx_producer];
771 	    if (idx == 0) {
772 		rxd->rxd_sop = 1; rxd->rxd_seg_cnt = PDQ_RX_SEGCNT - 1;
773 	    } else {
774 		rxd->rxd_sop = 0; rxd->rxd_seg_cnt = 0;
775 	    }
776 	    rxd->rxd_pa_hi = 0;
777 	    rxd->rxd_seg_len_hi = PDQ_OS_DATABUF_SIZE / 16;
778 	    rxd->rxd_pa_lo = PDQ_OS_VA_TO_PA(pdq, PDQ_OS_DATABUF_PTR(buffers[rx->rx_producer]));
779 	    PDQ_ADVANCE(rx->rx_producer, 1, ring_mask);
780 	    PDQ_ADVANCE(producer, 1, ring_mask);
781 	    PDQ_ADVANCE(completion, 1, ring_mask);
782 	}
783     }
784     rx->rx_completion = completion;
785 
786     while (rx->rx_free > PDQ_RX_SEGCNT && rx->rx_free > rx->rx_target) {
787 	PDQ_OS_DATABUF_T *pdu;
788 	/*
789 	 * Allocate the needed number of data buffers.
790 	 * Try to obtain them from our free queue before
791 	 * asking the system for more.
792 	 */
793 	for (idx = 0; idx < PDQ_RX_SEGCNT; idx++) {
794 	    if ((pdu = buffers[(rx->rx_producer + idx) & ring_mask]) == NULL) {
795 		PDQ_OS_DATABUF_ALLOC(pdu);
796 		if (pdu == NULL)
797 		    break;
798 		buffers[(rx->rx_producer + idx) & ring_mask] = pdu;
799 	    }
800 	    rxd = &receives[(rx->rx_producer + idx) & ring_mask];
801 	    if (idx == 0) {
802 		rxd->rxd_sop = 1; rxd->rxd_seg_cnt = PDQ_RX_SEGCNT - 1;
803 	    } else {
804 		rxd->rxd_sop = 0; rxd->rxd_seg_cnt = 0;
805 	    }
806 	    rxd->rxd_pa_hi = 0;
807 	    rxd->rxd_seg_len_hi = PDQ_OS_DATABUF_SIZE / 16;
808 	    rxd->rxd_pa_lo = PDQ_OS_VA_TO_PA(pdq, PDQ_OS_DATABUF_PTR(pdu));
809 	}
810 	if (idx < PDQ_RX_SEGCNT) {
811 	    /*
812 	     * We didn't get all databufs required to complete a new
813 	     * receive buffer.  Keep the ones we got and retry a bit
814 	     * later for the rest.
815 	     */
816 	    break;
817 	}
818 	PDQ_ADVANCE(rx->rx_producer, PDQ_RX_SEGCNT, ring_mask);
819 	rx->rx_free -= PDQ_RX_SEGCNT;
820     }
821 }
822 
823 pdq_boolean_t
pdq_queue_transmit_data(pdq_t * pdq,PDQ_OS_DATABUF_T * pdu)824 pdq_queue_transmit_data(
825     pdq_t *pdq,
826     PDQ_OS_DATABUF_T *pdu)
827 {
828     pdq_tx_info_t *tx = &pdq->pdq_tx_info;
829     pdq_descriptor_block_t *dbp = pdq->pdq_dbp;
830     pdq_uint32_t producer = tx->tx_producer;
831     pdq_txdesc_t *eop = NULL;
832     PDQ_OS_DATABUF_T *pdu0;
833     pdq_uint32_t freecnt;
834 
835     if (tx->tx_free < 1)
836 	return PDQ_FALSE;
837 
838     dbp->pdqdb_transmits[producer] = tx->tx_hdrdesc;
839     PDQ_ADVANCE(producer, 1, PDQ_RING_MASK(dbp->pdqdb_transmits));
840 
841     for (freecnt = tx->tx_free - 1, pdu0 = pdu; pdu0 != NULL && freecnt > 0;) {
842 	pdq_uint32_t fraglen, datalen = PDQ_OS_DATABUF_LEN(pdu0);
843 	const pdq_uint8_t *dataptr = PDQ_OS_DATABUF_PTR(pdu0);
844 
845 	/*
846 	 * The first segment is limited to the space remaining in
847 	 * page.  All segments after that can be up to a full page
848 	 * in size.
849 	 */
850 	fraglen = PDQ_OS_PAGESIZE - ((dataptr - (pdq_uint8_t *) NULL) & (PDQ_OS_PAGESIZE-1));
851 	while (datalen > 0 && freecnt > 0) {
852 	    pdq_uint32_t seglen = (fraglen < datalen ? fraglen : datalen);
853 
854 	    /*
855 	     * Initialize the transmit descriptor
856 	     */
857 	    eop = &dbp->pdqdb_transmits[producer];
858 	    eop->txd_seg_len = seglen;
859 	    eop->txd_pa_lo = PDQ_OS_VA_TO_PA(pdq, dataptr);
860 	    eop->txd_sop = eop->txd_eop = eop->txd_pa_hi = 0;
861 
862 	    datalen -= seglen;
863 	    dataptr += seglen;
864 	    fraglen = PDQ_OS_PAGESIZE;
865 	    freecnt--;
866 	    PDQ_ADVANCE(producer, 1, PDQ_RING_MASK(dbp->pdqdb_transmits));
867 	}
868 	pdu0 = PDQ_OS_DATABUF_NEXT(pdu0);
869     }
870     if (pdu0 != NULL) {
871 	PDQ_ASSERT(freecnt == 0);
872 	/*
873 	 * If we still have data to process then the ring was too full
874 	 * to store the PDU.  Return FALSE so the caller will requeue
875 	 * the PDU for later.
876 	 */
877 	return PDQ_FALSE;
878     }
879     /*
880      * Everything went fine.  Finish it up.
881      */
882     tx->tx_descriptor_count[tx->tx_producer] = tx->tx_free - freecnt;
883     eop->txd_eop = 1;
884     PDQ_OS_DATABUF_ENQUEUE(&tx->tx_txq, pdu);
885     tx->tx_producer = producer;
886     tx->tx_free = freecnt;
887     PDQ_DO_TYPE2_PRODUCER(pdq);
888     return PDQ_TRUE;
889 }
890 
891 static void
pdq_process_transmitted_data(pdq_t * pdq)892 pdq_process_transmitted_data(
893     pdq_t *pdq)
894 {
895     pdq_tx_info_t *tx = &pdq->pdq_tx_info;
896     volatile const pdq_consumer_block_t *cbp = pdq->pdq_cbp;
897     pdq_descriptor_block_t *dbp = pdq->pdq_dbp;
898     pdq_uint32_t completion = tx->tx_completion;
899 
900     while (completion != cbp->pdqcb_transmits) {
901 	PDQ_OS_DATABUF_T *pdu;
902 	pdq_uint32_t descriptor_count = tx->tx_descriptor_count[completion];
903 	PDQ_ASSERT(dbp->pdqdb_transmits[completion].txd_sop == 1);
904 	PDQ_ASSERT(dbp->pdqdb_transmits[(completion + descriptor_count - 1) & PDQ_RING_MASK(dbp->pdqdb_transmits)].txd_eop == 1);
905 	PDQ_OS_DATABUF_DEQUEUE(&tx->tx_txq, pdu);
906 	pdq_os_transmit_done(pdq, pdu);
907 	tx->tx_free += descriptor_count;
908 
909 	PDQ_ADVANCE(completion, descriptor_count, PDQ_RING_MASK(dbp->pdqdb_transmits));
910     }
911     if (tx->tx_completion != completion) {
912 	tx->tx_completion = completion;
913 	pdq_os_restart_transmitter(pdq);
914     }
915     PDQ_DO_TYPE2_PRODUCER(pdq);
916 }
917 
918 void
pdq_flush_transmitter(pdq_t * pdq)919 pdq_flush_transmitter(
920     pdq_t *pdq)
921 {
922     volatile pdq_consumer_block_t *cbp = pdq->pdq_cbp;
923     pdq_tx_info_t *tx = &pdq->pdq_tx_info;
924 
925     for (;;) {
926 	PDQ_OS_DATABUF_T *pdu;
927 	PDQ_OS_DATABUF_DEQUEUE(&tx->tx_txq, pdu);
928 	if (pdu == NULL)
929 	    break;
930 	/*
931 	 * Don't call transmit done since the packet never made it
932 	 * out on the wire.
933 	 */
934 	PDQ_OS_DATABUF_FREE(pdu);
935     }
936 
937     tx->tx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_transmits);
938     tx->tx_completion = cbp->pdqcb_transmits = tx->tx_producer;
939 
940     PDQ_DO_TYPE2_PRODUCER(pdq);
941 }
942 
943 void
pdq_hwreset(pdq_t * pdq)944 pdq_hwreset(
945     pdq_t *pdq)
946 {
947     const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
948     pdq_state_t state;
949     int cnt;
950 
951     state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
952     if (state == PDQS_DMA_UNAVAILABLE)
953 	return;
954     PDQ_CSR_WRITE(csrs, csr_port_data_a,
955 		  (state == PDQS_HALTED) ? 0 : PDQ_PRESET_SKIP_SELFTEST);
956     PDQ_CSR_WRITE(csrs, csr_port_reset, 1);
957     PDQ_OS_USEC_DELAY(100);
958     PDQ_CSR_WRITE(csrs, csr_port_reset, 0);
959     for (cnt = 45000;;cnt--) {
960 	PDQ_OS_USEC_DELAY(1000);
961 	state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
962 	if (state == PDQS_DMA_UNAVAILABLE || cnt == 0)
963 	    break;
964     }
965     PDQ_PRINTF(("PDQ Reset spun %d cycles\n", 45000 - cnt));
966     PDQ_OS_USEC_DELAY(10000);
967     state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
968     PDQ_ASSERT(state == PDQS_DMA_UNAVAILABLE);
969     PDQ_ASSERT(cnt > 0);
970 }
971 
972 /*
973  * The following routine brings the PDQ from whatever state it is
974  * in to DMA_UNAVAILABLE (ie. like a RESET but without doing a RESET).
975  */
976 pdq_state_t
pdq_stop(pdq_t * pdq)977 pdq_stop(
978     pdq_t *pdq)
979 {
980     pdq_state_t state;
981     const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
982     int cnt, pass = 0, idx;
983     PDQ_OS_DATABUF_T **buffers;
984 
985   restart:
986     state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
987     if (state != PDQS_DMA_UNAVAILABLE) {
988 	pdq_hwreset(pdq);
989 	state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
990 	PDQ_ASSERT(state == PDQS_DMA_UNAVAILABLE);
991     }
992 #if 0
993     switch (state) {
994 	case PDQS_RING_MEMBER:
995 	case PDQS_LINK_UNAVAILABLE:
996 	case PDQS_LINK_AVAILABLE: {
997 	    PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_SUB_CMD_LINK_UNINIT);
998 	    PDQ_CSR_WRITE(csrs, csr_port_data_b, 0);
999 	    pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD);
1000 	    state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
1001 	    PDQ_ASSERT(state == PDQS_DMA_AVAILABLE);
1002 	    /* FALL THROUGH */
1003 	}
1004 	case PDQS_DMA_AVAILABLE: {
1005 	    PDQ_CSR_WRITE(csrs, csr_port_data_a, 0);
1006 	    PDQ_CSR_WRITE(csrs, csr_port_data_b, 0);
1007 	    pdq_do_port_control(csrs, PDQ_PCTL_DMA_UNINIT);
1008 	    state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
1009 	    PDQ_ASSERT(state == PDQS_DMA_UNAVAILABLE);
1010 	    /* FALL THROUGH */
1011 	}
1012 	case PDQS_DMA_UNAVAILABLE: {
1013 	    break;
1014 	}
1015     }
1016 #endif
1017     /*
1018      * Now we should be in DMA_UNAVAILABLE.  So bring the PDQ into
1019      * DMA_AVAILABLE.
1020      */
1021 
1022     /*
1023      * Obtain the hardware address and firmware revisions
1024      * (MLA = my long address which is FDDI speak for hardware address)
1025      */
1026     pdq_read_mla(&pdq->pdq_csrs, &pdq->pdq_hwaddr);
1027     pdq_read_fwrev(&pdq->pdq_csrs, &pdq->pdq_fwrev);
1028     pdq->pdq_chip_rev = pdq_read_chiprev(&pdq->pdq_csrs);
1029 
1030     if (pdq->pdq_type == PDQ_DEFPA) {
1031 	/*
1032 	 * Disable interrupts and DMA.
1033 	 */
1034 	PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_mode_control, 0);
1035 	PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_status, 0x10);
1036     }
1037 
1038     /*
1039      * Flush all the databuf queues.
1040      */
1041     pdq_flush_databuf_queue(&pdq->pdq_tx_info.tx_txq);
1042     pdq->pdq_flags &= ~PDQ_TXOK;
1043     buffers = (PDQ_OS_DATABUF_T **) pdq->pdq_rx_info.rx_buffers;
1044     for (idx = 0; idx < PDQ_RING_SIZE(pdq->pdq_dbp->pdqdb_receives); idx++) {
1045 	if (buffers[idx] != NULL) {
1046 	    PDQ_OS_DATABUF_FREE(buffers[idx]);
1047 	    buffers[idx] = NULL;
1048 	}
1049     }
1050     pdq->pdq_rx_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_receives);
1051     buffers = (PDQ_OS_DATABUF_T **) pdq->pdq_host_smt_info.rx_buffers;
1052     for (idx = 0; idx < PDQ_RING_SIZE(pdq->pdq_dbp->pdqdb_host_smt); idx++) {
1053 	if (buffers[idx] != NULL) {
1054 	    PDQ_OS_DATABUF_FREE(buffers[idx]);
1055 	    buffers[idx] = NULL;
1056 	}
1057     }
1058     pdq->pdq_host_smt_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt);
1059 
1060     /*
1061      * Reset the consumer indexes to 0.
1062      */
1063     pdq->pdq_cbp->pdqcb_receives = 0;
1064     pdq->pdq_cbp->pdqcb_transmits = 0;
1065     pdq->pdq_cbp->pdqcb_host_smt = 0;
1066     pdq->pdq_cbp->pdqcb_unsolicited_event = 0;
1067     pdq->pdq_cbp->pdqcb_command_response = 0;
1068     pdq->pdq_cbp->pdqcb_command_request = 0;
1069 
1070     /*
1071      * Reset the producer and completion indexes to 0.
1072      */
1073     pdq->pdq_command_info.ci_request_producer = 0;
1074     pdq->pdq_command_info.ci_response_producer = 0;
1075     pdq->pdq_command_info.ci_request_completion = 0;
1076     pdq->pdq_command_info.ci_response_completion = 0;
1077     pdq->pdq_unsolicited_info.ui_producer = 0;
1078     pdq->pdq_unsolicited_info.ui_completion = 0;
1079     pdq->pdq_rx_info.rx_producer = 0;
1080     pdq->pdq_rx_info.rx_completion = 0;
1081     pdq->pdq_tx_info.tx_producer = 0;
1082     pdq->pdq_tx_info.tx_completion = 0;
1083     pdq->pdq_host_smt_info.rx_producer = 0;
1084     pdq->pdq_host_smt_info.rx_completion = 0;
1085 
1086     pdq->pdq_command_info.ci_command_active = 0;
1087     pdq->pdq_unsolicited_info.ui_free = PDQ_NUM_UNSOLICITED_EVENTS;
1088     pdq->pdq_tx_info.tx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_transmits);
1089 
1090     /*
1091      * Allow the DEFPA to do DMA.  Then program the physical
1092      * addresses of the consumer and descriptor blocks.
1093      */
1094     if (pdq->pdq_type == PDQ_DEFPA) {
1095 #ifdef PDQTEST
1096 	PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_mode_control,
1097 		      PDQ_PFI_MODE_DMA_ENABLE);
1098 #else
1099 	PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_mode_control,
1100 		      PDQ_PFI_MODE_DMA_ENABLE
1101 	    /*|PDQ_PFI_MODE_PFI_PCI_INTR*/|PDQ_PFI_MODE_PDQ_PCI_INTR);
1102 #endif
1103     }
1104 
1105     /*
1106      * Make sure the unsolicited queue has events ...
1107      */
1108     pdq_process_unsolicited_events(pdq);
1109 
1110     if (pdq->pdq_type == PDQ_DEFEA && pdq->pdq_chip_rev == PDQ_CHIP_REV_E)
1111 	PDQ_CSR_WRITE(csrs, csr_port_data_b, PDQ_DMA_BURST_16LW);
1112     else
1113 	PDQ_CSR_WRITE(csrs, csr_port_data_b, PDQ_DMA_BURST_8LW);
1114     PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_SUB_CMD_DMA_BURST_SIZE_SET);
1115     pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD);
1116 
1117     PDQ_CSR_WRITE(csrs, csr_port_data_b, 0);
1118     PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_OS_VA_TO_PA(pdq, pdq->pdq_cbp));
1119     pdq_do_port_control(csrs, PDQ_PCTL_CONSUMER_BLOCK);
1120 
1121     PDQ_CSR_WRITE(csrs, csr_port_data_b, 0);
1122     PDQ_CSR_WRITE(csrs, csr_port_data_a,
1123 		  PDQ_OS_VA_TO_PA(pdq, pdq->pdq_dbp) | PDQ_DMA_INIT_LW_BSWAP_DATA);
1124     pdq_do_port_control(csrs, PDQ_PCTL_DMA_INIT);
1125 
1126     for (cnt = 0; cnt < 1000; cnt++) {
1127 	state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
1128 	if (state == PDQS_HALTED) {
1129 	    if (pass > 0)
1130 		return PDQS_HALTED;
1131 	    pass = 1;
1132 	    goto restart;
1133 	}
1134 	if (state == PDQS_DMA_AVAILABLE) {
1135 	    PDQ_PRINTF(("Transition to DMA Available took %d spins\n", cnt));
1136 	    break;
1137 	}
1138 	PDQ_OS_USEC_DELAY(1000);
1139     }
1140     PDQ_ASSERT(state == PDQS_DMA_AVAILABLE);
1141 
1142     PDQ_CSR_WRITE(csrs, csr_host_int_type_0, 0xFF);
1143     PDQ_CSR_WRITE(csrs, csr_host_int_enable, 0) /* PDQ_HOST_INT_STATE_CHANGE
1144 	|PDQ_HOST_INT_FATAL_ERROR|PDQ_HOST_INT_CMD_RSP_ENABLE
1145 	|PDQ_HOST_INT_UNSOL_ENABLE */;
1146 
1147     /*
1148      * Any other command but START should be valid.
1149      */
1150     pdq->pdq_command_info.ci_pending_commands &= ~(PDQ_BITMASK(PDQC_START));
1151     if (pdq->pdq_flags & PDQ_PRINTCHARS)
1152 	pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_STATUS_CHARS_GET);
1153     pdq_queue_commands(pdq);
1154 
1155     if (pdq->pdq_flags & PDQ_PRINTCHARS) {
1156 	/*
1157 	 * Now wait (up to 100ms) for the command(s) to finish.
1158 	 */
1159 	for (cnt = 0; cnt < 1000; cnt++) {
1160 	    pdq_process_command_responses(pdq);
1161 	    if (pdq->pdq_command_info.ci_response_producer == pdq->pdq_command_info.ci_response_completion)
1162 		break;
1163 	    PDQ_OS_USEC_DELAY(1000);
1164 	}
1165 	state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
1166     }
1167 
1168     return state;
1169 }
1170 
1171 void
pdq_run(pdq_t * pdq)1172 pdq_run(
1173     pdq_t *pdq)
1174 {
1175     const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
1176     pdq_state_t state;
1177 
1178     state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
1179     PDQ_ASSERT(state != PDQS_DMA_UNAVAILABLE);
1180     PDQ_ASSERT(state != PDQS_RESET);
1181     PDQ_ASSERT(state != PDQS_HALTED);
1182     PDQ_ASSERT(state != PDQS_UPGRADE);
1183     PDQ_ASSERT(state != PDQS_RING_MEMBER);
1184     switch (state) {
1185 	case PDQS_DMA_AVAILABLE: {
1186 	    /*
1187 	     * The PDQ after being reset screws up some of its state.
1188 	     * So we need to clear all the errors/interrupts so the real
1189 	     * ones will get through.
1190 	     */
1191 	    PDQ_CSR_WRITE(csrs, csr_host_int_type_0, 0xFF);
1192 	    PDQ_CSR_WRITE(csrs, csr_host_int_enable, PDQ_HOST_INT_STATE_CHANGE|PDQ_HOST_INT_XMT_DATA_FLUSH
1193 		|PDQ_HOST_INT_FATAL_ERROR|PDQ_HOST_INT_CMD_RSP_ENABLE|PDQ_HOST_INT_UNSOL_ENABLE
1194 		|PDQ_HOST_INT_RX_ENABLE|PDQ_HOST_INT_TX_ENABLE|PDQ_HOST_INT_HOST_SMT_ENABLE);
1195 	    /*
1196 	     * Set the MAC and address filters and start up the PDQ.
1197 	     */
1198 	    pdq_process_unsolicited_events(pdq);
1199 	    pdq_process_received_data(pdq, &pdq->pdq_rx_info,
1200 				      pdq->pdq_dbp->pdqdb_receives,
1201 				      pdq->pdq_cbp->pdqcb_receives,
1202 				      PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_receives));
1203 	    PDQ_DO_TYPE2_PRODUCER(pdq);
1204 	    if (pdq->pdq_flags & PDQ_PASS_SMT) {
1205 		pdq_process_received_data(pdq, &pdq->pdq_host_smt_info,
1206 					  pdq->pdq_dbp->pdqdb_host_smt,
1207 					  pdq->pdq_cbp->pdqcb_host_smt,
1208 					  PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt));
1209 		PDQ_CSR_WRITE(csrs, csr_host_smt_producer,
1210 			      pdq->pdq_host_smt_info.rx_producer
1211 			          | (pdq->pdq_host_smt_info.rx_completion << 8));
1212 	    }
1213 	    pdq->pdq_command_info.ci_pending_commands = PDQ_BITMASK(PDQC_FILTER_SET)
1214 		| PDQ_BITMASK(PDQC_ADDR_FILTER_SET) | PDQ_BITMASK(PDQC_START);
1215 	    if (pdq->pdq_flags & PDQ_PRINTCHARS)
1216 		pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_STATUS_CHARS_GET);
1217 	    pdq_queue_commands(pdq);
1218 	    break;
1219 	}
1220 	case PDQS_LINK_UNAVAILABLE:
1221 	case PDQS_LINK_AVAILABLE: {
1222 	    pdq->pdq_command_info.ci_pending_commands = PDQ_BITMASK(PDQC_FILTER_SET)
1223 		| PDQ_BITMASK(PDQC_ADDR_FILTER_SET);
1224 	    if (pdq->pdq_flags & PDQ_PRINTCHARS)
1225 		pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_STATUS_CHARS_GET);
1226 	    if (pdq->pdq_flags & PDQ_PASS_SMT) {
1227 		pdq_process_received_data(pdq, &pdq->pdq_host_smt_info,
1228 					  pdq->pdq_dbp->pdqdb_host_smt,
1229 					  pdq->pdq_cbp->pdqcb_host_smt,
1230 					  PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt));
1231 		PDQ_CSR_WRITE(csrs, csr_host_smt_producer,
1232 			      pdq->pdq_host_smt_info.rx_producer
1233 			          | (pdq->pdq_host_smt_info.rx_completion << 8));
1234 	    }
1235 	    pdq_process_unsolicited_events(pdq);
1236 	    pdq_queue_commands(pdq);
1237 	    break;
1238 	}
1239 	case PDQS_RING_MEMBER: {
1240 	}
1241 	default:
1242 	    break;
1243     }
1244 }
1245 
1246 int
pdq_interrupt(pdq_t * pdq)1247 pdq_interrupt(
1248     pdq_t *pdq)
1249 {
1250     const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
1251     pdq_uint32_t data;
1252     int progress = 0;
1253 
1254     if (pdq->pdq_type == PDQ_DEFPA)
1255 	PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_status, 0x18);
1256 
1257     while ((data = PDQ_CSR_READ(csrs, csr_port_status)) & PDQ_PSTS_INTR_PENDING) {
1258 	progress = 1;
1259 	PDQ_PRINTF(("PDQ Interrupt: Status = 0x%08x\n", data));
1260 	if (data & PDQ_PSTS_RCV_DATA_PENDING) {
1261 	    pdq_process_received_data(pdq, &pdq->pdq_rx_info,
1262 				      pdq->pdq_dbp->pdqdb_receives,
1263 				      pdq->pdq_cbp->pdqcb_receives,
1264 				      PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_receives));
1265 	    PDQ_DO_TYPE2_PRODUCER(pdq);
1266 	}
1267 	if (data & PDQ_PSTS_HOST_SMT_PENDING) {
1268 	    pdq_process_received_data(pdq, &pdq->pdq_host_smt_info,
1269 				      pdq->pdq_dbp->pdqdb_host_smt,
1270 				      pdq->pdq_cbp->pdqcb_host_smt,
1271 				      PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt));
1272 	    PDQ_DO_HOST_SMT_PRODUCER(pdq);
1273 	}
1274 	if (data & PDQ_PSTS_XMT_DATA_PENDING)
1275 	    pdq_process_transmitted_data(pdq);
1276 	if (data & PDQ_PSTS_UNSOL_PENDING)
1277 	    pdq_process_unsolicited_events(pdq);
1278 	if (data & PDQ_PSTS_CMD_RSP_PENDING)
1279 	    pdq_process_command_responses(pdq);
1280 	if (data & PDQ_PSTS_TYPE_0_PENDING) {
1281 	    data = PDQ_CSR_READ(csrs, csr_host_int_type_0);
1282 	    if (data & PDQ_HOST_INT_STATE_CHANGE) {
1283 		pdq_state_t state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
1284 		printf(PDQ_OS_PREFIX "%s", PDQ_OS_PREFIX_ARGS, pdq_adapter_states[state]);
1285 		if (state == PDQS_LINK_UNAVAILABLE) {
1286 		    pdq->pdq_flags &= ~PDQ_TXOK;
1287 		} else if (state == PDQS_LINK_AVAILABLE) {
1288 		    pdq->pdq_flags |= PDQ_TXOK;
1289 		    pdq_os_restart_transmitter(pdq);
1290 		} else if (state == PDQS_HALTED) {
1291 		    pdq_response_error_log_get_t log_entry;
1292 		    pdq_halt_code_t halt_code = PDQ_PSTS_HALT_ID(PDQ_CSR_READ(csrs, csr_port_status));
1293 		    printf(": halt code = %d (%s)\n",
1294 			   halt_code, pdq_halt_codes[halt_code]);
1295 		    if (halt_code == PDQH_DMA_ERROR && pdq->pdq_type == PDQ_DEFPA) {
1296 			PDQ_PRINTF(("\tPFI status = 0x%x, Host 0 Fatal Interrupt = 0x%x\n",
1297 			       PDQ_CSR_READ(&pdq->pdq_pci_csrs, csr_pfi_status),
1298 			       data & PDQ_HOST_INT_FATAL_ERROR));
1299 		    }
1300 		    pdq_read_error_log(pdq, &log_entry);
1301 		    pdq_stop(pdq);
1302 		    if (pdq->pdq_flags & PDQ_RUNNING)
1303 			pdq_run(pdq);
1304 		    return 1;
1305 		}
1306 		printf("\n");
1307 		PDQ_CSR_WRITE(csrs, csr_host_int_type_0, PDQ_HOST_INT_STATE_CHANGE);
1308 	    }
1309 	    if (data & PDQ_HOST_INT_FATAL_ERROR) {
1310 		pdq_stop(pdq);
1311 		if (pdq->pdq_flags & PDQ_RUNNING)
1312 		    pdq_run(pdq);
1313 		return 1;
1314 	    }
1315 	    if (data & PDQ_HOST_INT_XMT_DATA_FLUSH) {
1316 		printf(PDQ_OS_PREFIX "Flushing transmit queue\n", PDQ_OS_PREFIX_ARGS);
1317 		pdq->pdq_flags &= ~PDQ_TXOK;
1318 		pdq_flush_transmitter(pdq);
1319 		pdq_do_port_control(csrs, PDQ_PCTL_XMT_DATA_FLUSH_DONE);
1320 		PDQ_CSR_WRITE(csrs, csr_host_int_type_0, PDQ_HOST_INT_XMT_DATA_FLUSH);
1321 	    }
1322 	}
1323 	if (pdq->pdq_type == PDQ_DEFPA)
1324 	    PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_status, 0x18);
1325     }
1326     return progress;
1327 }
1328 
1329 pdq_t *
pdq_initialize(pdq_bus_t bus,pdq_bus_memaddr_t csr_base,const char * name,int unit,void * ctx,pdq_type_t type)1330 pdq_initialize(
1331     pdq_bus_t bus,
1332     pdq_bus_memaddr_t csr_base,
1333     const char *name,
1334     int unit,
1335     void *ctx,
1336     pdq_type_t type)
1337 {
1338     pdq_t *pdq;
1339     pdq_state_t state;
1340     const pdq_uint32_t contig_bytes = (sizeof(pdq_descriptor_block_t) * 2) - PDQ_OS_PAGESIZE;
1341     pdq_uint8_t *p;
1342     int idx;
1343 
1344     PDQ_ASSERT(sizeof(pdq_descriptor_block_t) == 8192);
1345     PDQ_ASSERT(sizeof(pdq_consumer_block_t) == 64);
1346     PDQ_ASSERT(sizeof(pdq_response_filter_get_t) == PDQ_SIZE_RESPONSE_FILTER_GET);
1347     PDQ_ASSERT(sizeof(pdq_cmd_addr_filter_set_t) == PDQ_SIZE_CMD_ADDR_FILTER_SET);
1348     PDQ_ASSERT(sizeof(pdq_response_addr_filter_get_t) == PDQ_SIZE_RESPONSE_ADDR_FILTER_GET);
1349     PDQ_ASSERT(sizeof(pdq_response_status_chars_get_t) == PDQ_SIZE_RESPONSE_STATUS_CHARS_GET);
1350     PDQ_ASSERT(sizeof(pdq_response_fddi_mib_get_t) == PDQ_SIZE_RESPONSE_FDDI_MIB_GET);
1351     PDQ_ASSERT(sizeof(pdq_response_dec_ext_mib_get_t) == PDQ_SIZE_RESPONSE_DEC_EXT_MIB_GET);
1352     PDQ_ASSERT(sizeof(pdq_unsolicited_event_t) == 512);
1353 
1354     pdq = (pdq_t *) PDQ_OS_MEMALLOC(sizeof(pdq_t));
1355     if (pdq == NULL) {
1356 	PDQ_PRINTF(("malloc(%d) failed\n", sizeof(*pdq)));
1357 	return NULL;
1358     }
1359     PDQ_OS_MEMZERO(pdq, sizeof(pdq_t));
1360     pdq->pdq_type = type;
1361     pdq->pdq_unit = unit;
1362     pdq->pdq_os_ctx = (void *) ctx;
1363     pdq->pdq_os_name = name;
1364     pdq->pdq_flags = PDQ_PRINTCHARS;
1365     /*
1366      * Allocate the additional data structures required by
1367      * the PDQ driver.  Allocate a contiguous region of memory
1368      * for the descriptor block.  We need to allocated enough
1369      * to guarantee that we will a get 8KB block of memory aligned
1370      * on a 8KB boundary.  This turns to require that we allocate
1371      * (N*2 - 1 page) pages of memory.  On machine with less than
1372      * a 8KB page size, it mean we will allocate more memory than
1373      * we need.  The extra will be used for the unsolicited event
1374      * buffers (though on machines with 8KB pages we will to allocate
1375      * them separately since there will be nothing left overs.)
1376      */
1377     p = (pdq_uint8_t *) PDQ_OS_MEMALLOC_CONTIG(contig_bytes);
1378     if (p != NULL) {
1379 	pdq_physaddr_t physaddr = PDQ_OS_VA_TO_PA(pdq, p);
1380 	/*
1381 	 * Assert that we really got contiguous memory.  This isn't really
1382 	 * needed on systems that actually have physical contiguous allocation
1383 	 * routines, but on those systems that don't ...
1384 	 */
1385 	for (idx = PDQ_OS_PAGESIZE; idx < 0x2000; idx += PDQ_OS_PAGESIZE) {
1386 	    if (PDQ_OS_VA_TO_PA(pdq, p + idx) - physaddr != idx)
1387 		goto cleanup_and_return;
1388 	}
1389 	physaddr &= 0x1FFF;
1390 	if (physaddr) {
1391 	    pdq->pdq_unsolicited_info.ui_events = (pdq_unsolicited_event_t *) p;
1392 	    pdq->pdq_dbp = (pdq_descriptor_block_t *) &p[0x2000 - physaddr];
1393 	} else {
1394 	    pdq->pdq_dbp = (pdq_descriptor_block_t *) p;
1395 	    pdq->pdq_unsolicited_info.ui_events = (pdq_unsolicited_event_t *) &p[0x2000];
1396 	}
1397     }
1398     if (contig_bytes == sizeof(pdq_descriptor_block_t)) {
1399 	pdq->pdq_unsolicited_info.ui_events =
1400 	    (pdq_unsolicited_event_t *) PDQ_OS_MEMALLOC(
1401 		PDQ_NUM_UNSOLICITED_EVENTS * sizeof(pdq_unsolicited_event_t));
1402     }
1403 
1404     /*
1405      * Make sure everything got allocated.  If not, free what did
1406      * get allocated and return.
1407      */
1408     if (pdq->pdq_dbp == NULL || pdq->pdq_unsolicited_info.ui_events == NULL) {
1409       cleanup_and_return:
1410 	if (p /* pdq->pdq_dbp */ != NULL)
1411 	    PDQ_OS_MEMFREE_CONTIG(p /* pdq->pdq_dbp */, contig_bytes);
1412 	if (contig_bytes == sizeof(pdq_descriptor_block_t) && pdq->pdq_unsolicited_info.ui_events != NULL)
1413 	    PDQ_OS_MEMFREE(pdq->pdq_unsolicited_info.ui_events,
1414 			   PDQ_NUM_UNSOLICITED_EVENTS * sizeof(pdq_unsolicited_event_t));
1415 	PDQ_OS_MEMFREE(pdq, sizeof(pdq_t));
1416 	return NULL;
1417     }
1418 
1419     pdq->pdq_cbp = (volatile pdq_consumer_block_t *) &pdq->pdq_dbp->pdqdb_consumer;
1420     pdq->pdq_command_info.ci_bufstart = (pdq_uint8_t *) pdq->pdq_dbp->pdqdb_command_pool;
1421     pdq->pdq_rx_info.rx_buffers = (void *) pdq->pdq_dbp->pdqdb_receive_buffers;
1422 
1423     pdq->pdq_host_smt_info.rx_buffers = (void *) pdq->pdq_dbp->pdqdb_host_smt_buffers;
1424 
1425     PDQ_PRINTF(("\nPDQ Descriptor Block = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp));
1426     PDQ_PRINTF(("    Receive Queue          = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_receives));
1427     PDQ_PRINTF(("    Transmit Queue         = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_transmits));
1428     PDQ_PRINTF(("    Host SMT Queue         = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_host_smt));
1429     PDQ_PRINTF(("    Command Response Queue = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_command_responses));
1430     PDQ_PRINTF(("    Command Request Queue  = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_command_requests));
1431     PDQ_PRINTF(("PDQ Consumer Block = " PDQ_OS_PTR_FMT "\n", pdq->pdq_cbp));
1432 
1433     /*
1434      * Zero out the descriptor block.  Not really required but
1435      * it pays to be neat.  This will also zero out the consumer
1436      * block, command pool, and buffer pointers for the receive
1437      * host_smt rings.
1438      */
1439     PDQ_OS_MEMZERO(pdq->pdq_dbp, sizeof(*pdq->pdq_dbp));
1440 
1441     /*
1442      * Initialize the CSR references.
1443      * the DEFAA (FutureBus+) skips a longword between registers
1444      */
1445     pdq_init_csrs(&pdq->pdq_csrs, bus, csr_base, pdq->pdq_type == PDQ_DEFAA ? 2 : 1);
1446     if (pdq->pdq_type == PDQ_DEFPA)
1447 	pdq_init_pci_csrs(&pdq->pdq_pci_csrs, bus, csr_base, 1);
1448 
1449     PDQ_PRINTF(("PDQ CSRs: BASE = " PDQ_OS_PTR_FMT "\n", pdq->pdq_csrs.csr_base));
1450     PDQ_PRINTF(("    Port Reset                = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1451 	   pdq->pdq_csrs.csr_port_reset, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_reset)));
1452     PDQ_PRINTF(("    Host Data                 = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1453 	   pdq->pdq_csrs.csr_host_data, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_data)));
1454     PDQ_PRINTF(("    Port Control              = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1455 	   pdq->pdq_csrs.csr_port_control, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_control)));
1456     PDQ_PRINTF(("    Port Data A               = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1457 	   pdq->pdq_csrs.csr_port_data_a, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_data_a)));
1458     PDQ_PRINTF(("    Port Data B               = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1459 	   pdq->pdq_csrs.csr_port_data_b, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_data_b)));
1460     PDQ_PRINTF(("    Port Status               = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1461 	   pdq->pdq_csrs.csr_port_status, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_status)));
1462     PDQ_PRINTF(("    Host Int Type 0           = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1463 	   pdq->pdq_csrs.csr_host_int_type_0, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_int_type_0)));
1464     PDQ_PRINTF(("    Host Int Enable           = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1465 	   pdq->pdq_csrs.csr_host_int_enable, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_int_enable)));
1466     PDQ_PRINTF(("    Type 2 Producer           = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1467 	   pdq->pdq_csrs.csr_type_2_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_type_2_producer)));
1468     PDQ_PRINTF(("    Command Response Producer = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1469 	   pdq->pdq_csrs.csr_cmd_response_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_cmd_response_producer)));
1470     PDQ_PRINTF(("    Command Request Producer  = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1471 	   pdq->pdq_csrs.csr_cmd_request_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_cmd_request_producer)));
1472     PDQ_PRINTF(("    Host SMT Producer         = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1473 	   pdq->pdq_csrs.csr_host_smt_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_smt_producer)));
1474     PDQ_PRINTF(("    Unsolicited Producer      = " PDQ_OS_PTR_FMT " [0x%08x]\n",
1475 	   pdq->pdq_csrs.csr_unsolicited_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_unsolicited_producer)));
1476 
1477     /*
1478      * Initialize the command information block
1479      */
1480     pdq->pdq_command_info.ci_pa_bufstart = PDQ_OS_VA_TO_PA(pdq, pdq->pdq_command_info.ci_bufstart);
1481     for (idx = 0; idx < sizeof(pdq->pdq_dbp->pdqdb_command_requests)/sizeof(pdq->pdq_dbp->pdqdb_command_requests[0]); idx++) {
1482 	pdq_txdesc_t *txd = &pdq->pdq_dbp->pdqdb_command_requests[idx];
1483 
1484 	txd->txd_pa_lo = pdq->pdq_command_info.ci_pa_bufstart;
1485 	txd->txd_eop = txd->txd_sop = 1;
1486 	txd->txd_pa_hi = 0;
1487     }
1488     for (idx = 0; idx < sizeof(pdq->pdq_dbp->pdqdb_command_responses)/sizeof(pdq->pdq_dbp->pdqdb_command_responses[0]); idx++) {
1489 	pdq_rxdesc_t *rxd = &pdq->pdq_dbp->pdqdb_command_responses[idx];
1490 
1491 	rxd->rxd_pa_lo = pdq->pdq_command_info.ci_pa_bufstart;
1492 	rxd->rxd_sop = 1;
1493 	rxd->rxd_seg_cnt = 0;
1494 	rxd->rxd_seg_len_lo = 0;
1495     }
1496 
1497     /*
1498      * Initialize the unsolicited event information block
1499      */
1500     pdq->pdq_unsolicited_info.ui_free = PDQ_NUM_UNSOLICITED_EVENTS;
1501     pdq->pdq_unsolicited_info.ui_pa_bufstart = PDQ_OS_VA_TO_PA(pdq, pdq->pdq_unsolicited_info.ui_events);
1502     for (idx = 0; idx < sizeof(pdq->pdq_dbp->pdqdb_unsolicited_events)/sizeof(pdq->pdq_dbp->pdqdb_unsolicited_events[0]); idx++) {
1503 	pdq_rxdesc_t *rxd = &pdq->pdq_dbp->pdqdb_unsolicited_events[idx];
1504 	pdq_unsolicited_event_t *event = &pdq->pdq_unsolicited_info.ui_events[idx & (PDQ_NUM_UNSOLICITED_EVENTS-1)];
1505 
1506 	rxd->rxd_sop = 1;
1507 	rxd->rxd_seg_cnt = 0;
1508 	rxd->rxd_seg_len_hi = sizeof(pdq_unsolicited_event_t) / 16;
1509 	rxd->rxd_pa_lo = pdq->pdq_unsolicited_info.ui_pa_bufstart + (const pdq_uint8_t *) event
1510 	    - (const pdq_uint8_t *) pdq->pdq_unsolicited_info.ui_events;
1511 	rxd->rxd_pa_hi = 0;
1512     }
1513     /*
1514      * Initialize the receive information blocks (normal and SMT).
1515      */
1516     pdq->pdq_rx_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_receives);
1517     pdq->pdq_rx_info.rx_target = pdq->pdq_rx_info.rx_free - PDQ_RX_SEGCNT * 8;
1518 
1519     pdq->pdq_host_smt_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt);
1520     pdq->pdq_host_smt_info.rx_target = pdq->pdq_host_smt_info.rx_free - PDQ_RX_SEGCNT * 3;
1521 
1522     /*
1523      * Initialize the transmit information block.
1524      */
1525     pdq->pdq_tx_hdr[0] = PDQ_FDDI_PH0;
1526     pdq->pdq_tx_hdr[1] = PDQ_FDDI_PH1;
1527     pdq->pdq_tx_hdr[2] = PDQ_FDDI_PH2;
1528     pdq->pdq_tx_info.tx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_transmits);
1529     pdq->pdq_tx_info.tx_hdrdesc.txd_seg_len = sizeof(pdq->pdq_tx_hdr);
1530     pdq->pdq_tx_info.tx_hdrdesc.txd_sop = 1;
1531     pdq->pdq_tx_info.tx_hdrdesc.txd_pa_lo = PDQ_OS_VA_TO_PA(pdq, pdq->pdq_tx_hdr);
1532 
1533     state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_status));
1534     PDQ_PRINTF(("PDQ Adapter State = %s\n", pdq_adapter_states[state]));
1535 
1536     /*
1537      * Stop the PDQ if it is running and put it into a known state.
1538      */
1539     state = pdq_stop(pdq);
1540 
1541     PDQ_PRINTF(("PDQ Adapter State = %s\n", pdq_adapter_states[state]));
1542     PDQ_ASSERT(state == PDQS_DMA_AVAILABLE);
1543     /*
1544      * If the adapter is not the state we expect, then the initialization
1545      * failed.  Cleanup and exit.
1546      */
1547 #if defined(PDQVERBOSE)
1548     if (state == PDQS_HALTED) {
1549 	pdq_halt_code_t halt_code = PDQ_PSTS_HALT_ID(PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_status));
1550 	printf("Halt code = %d (%s)\n", halt_code, pdq_halt_codes[halt_code]);
1551 	if (halt_code == PDQH_DMA_ERROR && pdq->pdq_type == PDQ_DEFPA)
1552 	    PDQ_PRINTF(("PFI status = 0x%x, Host 0 Fatal Interrupt = 0x%x\n",
1553 		       PDQ_CSR_READ(&pdq->pdq_pci_csrs, csr_pfi_status),
1554 		       PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_int_type_0) & PDQ_HOST_INT_FATAL_ERROR));
1555     }
1556 #endif
1557     if (state == PDQS_RESET || state == PDQS_HALTED || state == PDQS_UPGRADE)
1558 	goto cleanup_and_return;
1559 
1560     PDQ_PRINTF(("PDQ Hardware Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
1561 	   pdq->pdq_hwaddr.lanaddr_bytes[0], pdq->pdq_hwaddr.lanaddr_bytes[1],
1562 	   pdq->pdq_hwaddr.lanaddr_bytes[2], pdq->pdq_hwaddr.lanaddr_bytes[3],
1563 	   pdq->pdq_hwaddr.lanaddr_bytes[4], pdq->pdq_hwaddr.lanaddr_bytes[5]));
1564     PDQ_PRINTF(("PDQ Firmware Revision = %c%c%c%c\n",
1565 	   pdq->pdq_fwrev.fwrev_bytes[0], pdq->pdq_fwrev.fwrev_bytes[1],
1566 	   pdq->pdq_fwrev.fwrev_bytes[2], pdq->pdq_fwrev.fwrev_bytes[3]));
1567     PDQ_PRINTF(("PDQ Chip Revision = "));
1568     switch (pdq->pdq_chip_rev) {
1569 	case PDQ_CHIP_REV_A_B_OR_C: PDQ_PRINTF(("Rev C or below")); break;
1570 	case PDQ_CHIP_REV_D: PDQ_PRINTF(("Rev D")); break;
1571 	case PDQ_CHIP_REV_E: PDQ_PRINTF(("Rev E")); break;
1572 	default: PDQ_PRINTF(("Unknown Rev %d", (int) pdq->pdq_chip_rev));
1573     }
1574     PDQ_PRINTF(("\n"));
1575 
1576     return pdq;
1577 }
1578