1 /* $NetBSD: pdq.c,v 1.36.2.2 2005/11/10 14:04:15 skrll Exp $ */
4 * Copyright (c) 1995,1996 Matt Thomas <matt@3am-software.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * Id: pdq.c,v 1.32 1997/06/05 01:56:35 thomas Exp
31 * DEC PDQ FDDI Controller O/S independent code
33 * This module should work any on PDQ based board. Note that changes for
34 * MIPS and Alpha architectures (or any other architecture which requires
35 * a flushing of memory or write buffers and/or has incoherent caches)
36 * have yet to be made.
38 * However, it is expected that the PDQ_CSR_WRITE macro will cause a
39 * flushing of the write buffers.
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: pdq.c,v 1.36.2.2 2005/11/10 14:04:15 skrll Exp $");
45 #define PDQ_HWSUPPORT /* for pdq.h */
47 #if defined(__FreeBSD__)
49 * What a botch having to specific includes for FreeBSD!
51 #include <dev/pdq/pdqvar.h>
52 #include <dev/pdq/pdqreg.h>
58 #define PDQ_ROUNDUP(n, x) (((n) + ((x) - 1)) & ~((x) - 1))
59 #define PDQ_CMD_RX_ALIGNMENT 16
61 #if (defined(PDQTEST) && !defined(PDQ_NOPRINTF)) || defined(PDQVERBOSE)
62 #define PDQ_PRINTF(x) printf x
64 #define PDQ_PRINTF(x) do { } while (0)
67 static const char * const pdq_halt_codes
[] = {
68 "Selftest Timeout", "Host Bus Parity Error", "Host Directed Fault",
69 "Software Fault", "Hardware Fault", "PC Trace Path Test",
70 "DMA Error", "Image CRC Error", "Adapter Processer Error"
73 static const char * const pdq_adapter_states
[] = {
74 "Reset", "Upgrade", "DMA Unavailable", "DMA Available",
75 "Link Available", "Link Unavailable", "Halted", "Ring Member"
79 * The following are used in conjunction with
82 static const char * const pdq_entities
[] = {
83 "Station", "Link", "Phy Port"
86 static const char * const pdq_station_events
[] = {
91 static const char * const pdq_link_events
[] = {
94 "Block Check Error (CRC)",
99 "Receive Data Overrun",
102 "Ring Initialization Initiated",
103 "Ring Initialization Received",
104 "Ring Beacon Initiated",
105 "Duplicate Address Failure",
106 "Duplicate Token Detected",
110 "Directed Beacon Received",
114 static const char * const pdq_station_arguments
[] = {
118 static const char * const pdq_link_arguments
[] = {
125 static const char * const pdq_phy_arguments
[] = {
129 static const char * const * const pdq_event_arguments
[] = {
130 pdq_station_arguments
,
138 static const char * const pdq_phy_events
[] = {
139 "LEM Error Monitor Reject",
140 "Elasticy Buffer Error",
141 "Link Confidence Test Reject"
144 static const char * const * const pdq_event_codes
[] = {
150 static const char * const pdq_station_types
[] = {
151 "SAS", "DAC", "SAC", "NAC", "DAS"
154 static const char * const pdq_smt_versions
[] = { "", "V6.2", "V7.2", "V7.3" };
156 static const char pdq_phy_types
[] = "ABSM";
158 static const char * const pdq_pmd_types0
[] = {
159 "ANSI Multi-Mode", "ANSI Single-Mode Type 1", "ANSI Single-Mode Type 2",
163 static const char * const pdq_pmd_types100
[] = {
164 "Low Power", "Thin Wire", "Shielded Twisted Pair",
165 "Unshielded Twisted Pair"
168 static const char * const * const pdq_pmd_types
[] = {
169 pdq_pmd_types0
, pdq_pmd_types100
172 static const char * const pdq_descriptions
[] = {
181 pdq_print_fddi_chars(
183 const pdq_response_status_chars_get_t
*rsp
)
185 pdq_uint32_t phy_type
;
186 pdq_uint32_t pmd_type
;
187 pdq_uint32_t smt_version_id
;
188 pdq_station_type_t station_type
;
191 #if !defined(__bsdi__) && !defined(__NetBSD__)
196 "DEC %s FDDI %s Controller\n",
197 #if !defined(__bsdi__) && !defined(__NetBSD__)
200 pdq_descriptions
[pdq
->pdq_type
],
201 pdq_station_types
[le32toh(rsp
->status_chars_get
.station_type
)]);
203 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",
205 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[0] >> 4],
206 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[0] & 0x0F],
207 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[1] >> 4],
208 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[1] & 0x0F],
209 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[2] >> 4],
210 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[2] & 0x0F],
211 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[3] >> 4],
212 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[3] & 0x0F],
213 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[4] >> 4],
214 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[4] & 0x0F],
215 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[5] >> 4],
216 hexdigits
[pdq
->pdq_hwaddr
.lanaddr_bytes
[5] & 0x0F],
217 pdq
->pdq_fwrev
.fwrev_bytes
[0], pdq
->pdq_fwrev
.fwrev_bytes
[1],
218 pdq
->pdq_fwrev
.fwrev_bytes
[2], pdq
->pdq_fwrev
.fwrev_bytes
[3],
219 rsp
->status_chars_get
.module_rev
.fwrev_bytes
[0]);
221 phy_type
= le32toh(rsp
->status_chars_get
.phy_type
[0]);
222 pmd_type
= le32toh(rsp
->status_chars_get
.pmd_type
[0]);
223 station_type
= le32toh(rsp
->status_chars_get
.station_type
);
224 smt_version_id
= le32toh(rsp
->status_chars_get
.smt_version_id
);
226 if (smt_version_id
< PDQ_ARRAY_SIZE(pdq_smt_versions
))
227 printf(", SMT %s\n", pdq_smt_versions
[smt_version_id
]);
229 printf(PDQ_OS_PREFIX
"FDDI Port%s = %c (PMD = %s)",
231 le32toh(station_type
) == PDQ_STATION_TYPE_DAS
? "[A]" : "",
232 pdq_phy_types
[phy_type
],
233 pdq_pmd_types
[pmd_type
/ 100][pmd_type
% 100]);
235 if (station_type
== PDQ_STATION_TYPE_DAS
) {
236 phy_type
= le32toh(rsp
->status_chars_get
.phy_type
[1]);
237 pmd_type
= le32toh(rsp
->status_chars_get
.pmd_type
[1]);
238 printf(", FDDI Port[B] = %c (PMD = %s)",
239 pdq_phy_types
[phy_type
],
240 pdq_pmd_types
[pmd_type
/ 100][pmd_type
% 100]);
245 pdq_os_update_status(pdq
, rsp
);
252 pdq_bus_memaddr_t csr_base
,
256 csrs
->csr_base
= csr_base
;
257 csrs
->csr_port_reset
= PDQ_CSR_OFFSET(csr_base
, 0 * csrsize
);
258 csrs
->csr_host_data
= PDQ_CSR_OFFSET(csr_base
, 1 * csrsize
);
259 csrs
->csr_port_control
= PDQ_CSR_OFFSET(csr_base
, 2 * csrsize
);
260 csrs
->csr_port_data_a
= PDQ_CSR_OFFSET(csr_base
, 3 * csrsize
);
261 csrs
->csr_port_data_b
= PDQ_CSR_OFFSET(csr_base
, 4 * csrsize
);
262 csrs
->csr_port_status
= PDQ_CSR_OFFSET(csr_base
, 5 * csrsize
);
263 csrs
->csr_host_int_type_0
= PDQ_CSR_OFFSET(csr_base
, 6 * csrsize
);
264 csrs
->csr_host_int_enable
= PDQ_CSR_OFFSET(csr_base
, 7 * csrsize
);
265 csrs
->csr_type_2_producer
= PDQ_CSR_OFFSET(csr_base
, 8 * csrsize
);
266 csrs
->csr_cmd_response_producer
= PDQ_CSR_OFFSET(csr_base
, 10 * csrsize
);
267 csrs
->csr_cmd_request_producer
= PDQ_CSR_OFFSET(csr_base
, 11 * csrsize
);
268 csrs
->csr_host_smt_producer
= PDQ_CSR_OFFSET(csr_base
, 12 * csrsize
);
269 csrs
->csr_unsolicited_producer
= PDQ_CSR_OFFSET(csr_base
, 13 * csrsize
);
274 pdq_pci_csrs_t
*csrs
,
276 pdq_bus_memaddr_t csr_base
,
280 csrs
->csr_base
= csr_base
;
281 csrs
->csr_pfi_mode_control
= PDQ_CSR_OFFSET(csr_base
, 16 * csrsize
);
282 csrs
->csr_pfi_status
= PDQ_CSR_OFFSET(csr_base
, 17 * csrsize
);
283 csrs
->csr_fifo_write
= PDQ_CSR_OFFSET(csr_base
, 18 * csrsize
);
284 csrs
->csr_fifo_read
= PDQ_CSR_OFFSET(csr_base
, 19 * csrsize
);
288 pdq_flush_databuf_queue(
290 pdq_databuf_queue_t
*q
)
292 PDQ_OS_DATABUF_T
*pdu
;
294 PDQ_OS_DATABUF_DEQUEUE(q
, pdu
);
297 PDQ_OS_DATABUF_FREE(pdq
, pdu
);
303 const pdq_csrs_t
* const csrs
,
307 PDQ_CSR_WRITE(csrs
, csr_host_int_type_0
, PDQ_HOST_INT_CSR_CMD_DONE
);
308 PDQ_CSR_WRITE(csrs
, csr_port_control
, PDQ_PCTL_CMD_ERROR
| cmd
);
309 while ((PDQ_CSR_READ(csrs
, csr_host_int_type_0
) & PDQ_HOST_INT_CSR_CMD_DONE
) == 0 && cnt
< 33000000)
311 PDQ_PRINTF(("CSR cmd spun %d times\n", cnt
));
312 if (PDQ_CSR_READ(csrs
, csr_host_int_type_0
) & PDQ_HOST_INT_CSR_CMD_DONE
) {
313 PDQ_CSR_WRITE(csrs
, csr_host_int_type_0
, PDQ_HOST_INT_CSR_CMD_DONE
);
314 return (PDQ_CSR_READ(csrs
, csr_port_control
) & PDQ_PCTL_CMD_ERROR
) ? PDQ_FALSE
: PDQ_TRUE
;
316 /* adapter failure */
323 const pdq_csrs_t
* const csrs
,
324 pdq_lanaddr_t
*hwaddr
)
328 PDQ_CSR_WRITE(csrs
, csr_port_data_a
, 0);
329 pdq_do_port_control(csrs
, PDQ_PCTL_MLA_READ
);
330 data
= PDQ_CSR_READ(csrs
, csr_host_data
);
332 hwaddr
->lanaddr_bytes
[0] = (data
>> 0) & 0xFF;
333 hwaddr
->lanaddr_bytes
[1] = (data
>> 8) & 0xFF;
334 hwaddr
->lanaddr_bytes
[2] = (data
>> 16) & 0xFF;
335 hwaddr
->lanaddr_bytes
[3] = (data
>> 24) & 0xFF;
337 PDQ_CSR_WRITE(csrs
, csr_port_data_a
, 1);
338 pdq_do_port_control(csrs
, PDQ_PCTL_MLA_READ
);
339 data
= PDQ_CSR_READ(csrs
, csr_host_data
);
341 hwaddr
->lanaddr_bytes
[4] = (data
>> 0) & 0xFF;
342 hwaddr
->lanaddr_bytes
[5] = (data
>> 8) & 0xFF;
347 const pdq_csrs_t
* const csrs
,
352 pdq_do_port_control(csrs
, PDQ_PCTL_FW_REV_READ
);
353 data
= PDQ_CSR_READ(csrs
, csr_host_data
);
355 fwrev
->fwrev_bytes
[3] = (data
>> 0) & 0xFF;
356 fwrev
->fwrev_bytes
[2] = (data
>> 8) & 0xFF;
357 fwrev
->fwrev_bytes
[1] = (data
>> 16) & 0xFF;
358 fwrev
->fwrev_bytes
[0] = (data
>> 24) & 0xFF;
364 pdq_response_error_log_get_t
*log_entry
)
366 const pdq_csrs_t
* const csrs
= &pdq
->pdq_csrs
;
367 pdq_uint32_t
*ptr
= (pdq_uint32_t
*) log_entry
;
369 pdq_do_port_control(csrs
, PDQ_PCTL_ERROR_LOG_START
);
371 while (pdq_do_port_control(csrs
, PDQ_PCTL_FW_REV_READ
) == PDQ_TRUE
) {
372 *ptr
++ = PDQ_CSR_READ(csrs
, csr_host_data
);
373 if ((pdq_uint8_t
*) ptr
- (pdq_uint8_t
*) log_entry
== sizeof(*log_entry
))
376 return (ptr
== (pdq_uint32_t
*) log_entry
) ? PDQ_FALSE
: PDQ_TRUE
;
379 static pdq_chip_rev_t
381 const pdq_csrs_t
* const csrs
)
385 PDQ_CSR_WRITE(csrs
, csr_port_data_a
, PDQ_SUB_CMD_PDQ_REV_GET
);
386 pdq_do_port_control(csrs
, PDQ_PCTL_SUB_CMD
);
387 data
= PDQ_CSR_READ(csrs
, csr_host_data
);
389 return (pdq_chip_rev_t
) data
;
392 static const struct {
395 const char *cmd_name
;
397 { sizeof(pdq_cmd_generic_t
), /* 0 - PDQC_START */
398 sizeof(pdq_response_generic_t
),
401 { sizeof(pdq_cmd_filter_set_t
), /* 1 - PDQC_FILTER_SET */
402 sizeof(pdq_response_generic_t
),
405 { sizeof(pdq_cmd_generic_t
), /* 2 - PDQC_FILTER_GET */
406 sizeof(pdq_response_filter_get_t
),
409 { sizeof(pdq_cmd_chars_set_t
), /* 3 - PDQC_CHARS_SET */
410 sizeof(pdq_response_generic_t
),
413 { sizeof(pdq_cmd_generic_t
), /* 4 - PDQC_STATUS_CHARS_GET */
414 sizeof(pdq_response_status_chars_get_t
),
418 { sizeof(pdq_cmd_generic_t
), /* 5 - PDQC_COUNTERS_GET */
419 sizeof(pdq_response_counters_get_t
),
422 { sizeof(pdq_cmd_counters_set_t
), /* 6 - PDQC_COUNTERS_SET */
423 sizeof(pdq_response_generic_t
),
427 { 0, 0, "Counters Get" },
428 { 0, 0, "Counters Set" },
430 { sizeof(pdq_cmd_addr_filter_set_t
), /* 7 - PDQC_ADDR_FILTER_SET */
431 sizeof(pdq_response_generic_t
),
434 { sizeof(pdq_cmd_generic_t
), /* 8 - PDQC_ADDR_FILTER_GET */
435 sizeof(pdq_response_addr_filter_get_t
),
438 { sizeof(pdq_cmd_generic_t
), /* 9 - PDQC_ERROR_LOG_CLEAR */
439 sizeof(pdq_response_generic_t
),
442 { sizeof(pdq_cmd_generic_t
), /* 10 - PDQC_ERROR_LOG_SET */
443 sizeof(pdq_response_generic_t
),
446 { sizeof(pdq_cmd_generic_t
), /* 11 - PDQC_FDDI_MIB_GET */
447 sizeof(pdq_response_generic_t
),
450 { sizeof(pdq_cmd_generic_t
), /* 12 - PDQC_DEC_EXT_MIB_GET */
451 sizeof(pdq_response_generic_t
),
454 { sizeof(pdq_cmd_generic_t
), /* 13 - PDQC_DEC_SPECIFIC_GET */
455 sizeof(pdq_response_generic_t
),
458 { sizeof(pdq_cmd_generic_t
), /* 14 - PDQC_SNMP_SET */
459 sizeof(pdq_response_generic_t
),
463 { sizeof(pdq_cmd_generic_t
), /* 16 - PDQC_SMT_MIB_GET */
464 sizeof(pdq_response_generic_t
),
467 { sizeof(pdq_cmd_generic_t
), /* 17 - PDQC_SMT_MIB_SET */
468 sizeof(pdq_response_generic_t
),
471 { 0, 0, "Bogus CMD" },
478 const pdq_csrs_t
* const csrs
= &pdq
->pdq_csrs
;
479 pdq_command_info_t
* const ci
= &pdq
->pdq_command_info
;
480 pdq_descriptor_block_t
* const dbp
= pdq
->pdq_dbp
;
481 pdq_txdesc_t
* const txd
= &dbp
->pdqdb_command_requests
[ci
->ci_request_producer
];
483 pdq_uint32_t cmdlen
, rsplen
, mask
;
486 * If there are commands or responses active or there aren't
487 * any pending commands, then don't queue any more.
489 if (ci
->ci_command_active
|| ci
->ci_pending_commands
== 0)
493 * Determine which command needs to be queued.
495 op
= PDQC_SMT_MIB_SET
;
496 for (mask
= 1 << ((int) op
); (mask
& ci
->ci_pending_commands
) == 0; mask
>>= 1)
497 op
= (pdq_cmd_code_t
) ((int) op
- 1);
499 * Obtain the sizes needed for the command and response.
500 * Round up to PDQ_CMD_RX_ALIGNMENT so the receive buffer is
501 * always properly aligned.
503 cmdlen
= PDQ_ROUNDUP(pdq_cmd_info
[op
].cmd_len
, PDQ_CMD_RX_ALIGNMENT
);
504 rsplen
= PDQ_ROUNDUP(pdq_cmd_info
[op
].rsp_len
, PDQ_CMD_RX_ALIGNMENT
);
508 * Since only one command at a time will be queued, there will always
513 * Obtain and fill in the descriptor for the command (descriptor is
517 htole32(PDQ_TXDESC_SEG_LEN(cmdlen
)|PDQ_TXDESC_EOP
|PDQ_TXDESC_SOP
);
520 * Clear the command area, set the opcode, and the command from the pending
524 ci
->ci_queued_commands
[ci
->ci_request_producer
] = op
;
525 #if defined(PDQVERBOSE)
526 ((pdq_response_generic_t
*) ci
->ci_response_bufstart
)->generic_op
=
527 htole32(PDQC_BOGUS_CMD
);
529 PDQ_OS_MEMZERO(ci
->ci_request_bufstart
, cmdlen
);
530 *(pdq_uint32_t
*) ci
->ci_request_bufstart
= htole32(op
);
531 ci
->ci_pending_commands
&= ~mask
;
534 * Fill in the command area, if needed.
537 case PDQC_FILTER_SET
: {
538 pdq_cmd_filter_set_t
*filter_set
= (pdq_cmd_filter_set_t
*) ci
->ci_request_bufstart
;
540 filter_set
->filter_set_items
[idx
].item_code
=
541 htole32(PDQI_IND_GROUP_PROM
);
542 filter_set
->filter_set_items
[idx
].filter_state
=
543 htole32(pdq
->pdq_flags
& PDQ_PROMISC
? PDQ_FILTER_PASS
: PDQ_FILTER_BLOCK
);
545 filter_set
->filter_set_items
[idx
].item_code
=
546 htole32(PDQI_GROUP_PROM
);
547 filter_set
->filter_set_items
[idx
].filter_state
=
548 htole32(pdq
->pdq_flags
& PDQ_ALLMULTI
? PDQ_FILTER_PASS
: PDQ_FILTER_BLOCK
);
550 filter_set
->filter_set_items
[idx
].item_code
=
551 htole32(PDQI_SMT_PROM
);
552 filter_set
->filter_set_items
[idx
].filter_state
=
553 htole32((pdq
->pdq_flags
& (PDQ_PROMISC
|PDQ_PASS_SMT
)) == (PDQ_PROMISC
|PDQ_PASS_SMT
) ? PDQ_FILTER_PASS
: PDQ_FILTER_BLOCK
);
555 filter_set
->filter_set_items
[idx
].item_code
=
556 htole32(PDQI_SMT_USER
);
557 filter_set
->filter_set_items
[idx
].filter_state
=
558 htole32((pdq
->pdq_flags
& PDQ_PASS_SMT
) ? PDQ_FILTER_PASS
: PDQ_FILTER_BLOCK
);
560 filter_set
->filter_set_items
[idx
].item_code
=
564 case PDQC_ADDR_FILTER_SET
: {
565 pdq_cmd_addr_filter_set_t
*addr_filter_set
= (pdq_cmd_addr_filter_set_t
*) ci
->ci_request_bufstart
;
566 pdq_lanaddr_t
*addr
= addr_filter_set
->addr_filter_set_addresses
;
567 addr
->lanaddr_bytes
[0] = 0xFF;
568 addr
->lanaddr_bytes
[1] = 0xFF;
569 addr
->lanaddr_bytes
[2] = 0xFF;
570 addr
->lanaddr_bytes
[3] = 0xFF;
571 addr
->lanaddr_bytes
[4] = 0xFF;
572 addr
->lanaddr_bytes
[5] = 0xFF;
574 pdq_os_addr_fill(pdq
, addr
, 61);
577 case PDQC_SNMP_SET
: {
578 pdq_cmd_snmp_set_t
*snmp_set
= (pdq_cmd_snmp_set_t
*) ci
->ci_request_bufstart
;
580 snmp_set
->snmp_set_items
[idx
].item_code
= htole32(PDQSNMP_FULL_DUPLEX_ENABLE
);
581 snmp_set
->snmp_set_items
[idx
].item_value
= htole32(pdq
->pdq_flags
& PDQ_WANT_FDX
? 1 : 2);
582 snmp_set
->snmp_set_items
[idx
].item_port
= 0;
584 snmp_set
->snmp_set_items
[idx
].item_code
= htole32(PDQSNMP_EOL
);
587 default: { /* to make gcc happy */
594 * Sync the command request buffer and descriptor, then advance
595 * the request producer index.
597 PDQ_OS_CMDRQST_PRESYNC(pdq
, cmdlen
);
598 PDQ_OS_DESC_PRESYNC(pdq
, txd
, sizeof(pdq_txdesc_t
));
599 PDQ_ADVANCE(ci
->ci_request_producer
, 1, PDQ_RING_MASK(dbp
->pdqdb_command_requests
));
602 * Sync the command response buffer and advance the response
603 * producer index (descriptor is already pre-initialized)
605 PDQ_OS_CMDRSP_PRESYNC(pdq
, PDQ_SIZE_COMMAND_RESPONSE
);
606 PDQ_ADVANCE(ci
->ci_response_producer
, 1, PDQ_RING_MASK(dbp
->pdqdb_command_responses
));
608 * At this point the command is done. All that needs to be done is to
609 * produce it to the PDQ.
611 PDQ_PRINTF(("PDQ Queue Command Request: %s queued\n",
612 pdq_cmd_info
[op
].cmd_name
));
614 ci
->ci_command_active
++;
615 PDQ_CSR_WRITE(csrs
, csr_cmd_response_producer
, ci
->ci_response_producer
| (ci
->ci_response_completion
<< 8));
616 PDQ_CSR_WRITE(csrs
, csr_cmd_request_producer
, ci
->ci_request_producer
| (ci
->ci_request_completion
<< 8));
620 pdq_process_command_responses(
623 const pdq_csrs_t
* const csrs
= &pdq
->pdq_csrs
;
624 pdq_command_info_t
* const ci
= &pdq
->pdq_command_info
;
625 volatile const pdq_consumer_block_t
* const cbp
= pdq
->pdq_cbp
;
626 pdq_descriptor_block_t
* const dbp
= pdq
->pdq_dbp
;
627 const pdq_response_generic_t
*rspgen
;
629 pdq_response_code_t status
;
632 * We have to process the command and response in tandem so
633 * just wait for the response to be consumed. If it has been
634 * consumed then the command must have been as well.
637 if (le32toh(cbp
->pdqcb_command_response
) == ci
->ci_response_completion
)
640 PDQ_ASSERT(le32toh(cbp
->pdqcb_command_request
) != ci
->ci_request_completion
);
642 PDQ_OS_CMDRSP_POSTSYNC(pdq
, PDQ_SIZE_COMMAND_RESPONSE
);
643 rspgen
= (const pdq_response_generic_t
*) ci
->ci_response_bufstart
;
644 op
= le32toh(rspgen
->generic_op
);
645 status
= le32toh(rspgen
->generic_status
);
646 PDQ_ASSERT(op
== ci
->ci_queued_commands
[ci
->ci_request_completion
]);
647 PDQ_ASSERT(status
== PDQR_SUCCESS
);
648 PDQ_PRINTF(("PDQ Process Command Response: %s completed (status=%d [0x%x])\n",
649 pdq_cmd_info
[op
].cmd_name
,
653 if (op
== PDQC_STATUS_CHARS_GET
&& (pdq
->pdq_flags
& PDQ_PRINTCHARS
)) {
654 pdq
->pdq_flags
&= ~PDQ_PRINTCHARS
;
655 pdq_print_fddi_chars(pdq
, (const pdq_response_status_chars_get_t
*) rspgen
);
656 } else if (op
== PDQC_DEC_EXT_MIB_GET
) {
657 pdq
->pdq_flags
&= ~PDQ_IS_FDX
;
658 if (le32toh(((const pdq_response_dec_ext_mib_get_t
*)rspgen
)->dec_ext_mib_get
.fdx_operational
))
659 pdq
->pdq_flags
|= PDQ_IS_FDX
;
662 PDQ_ADVANCE(ci
->ci_request_completion
, 1, PDQ_RING_MASK(dbp
->pdqdb_command_requests
));
663 PDQ_ADVANCE(ci
->ci_response_completion
, 1, PDQ_RING_MASK(dbp
->pdqdb_command_responses
));
664 ci
->ci_command_active
= 0;
666 if (ci
->ci_pending_commands
!= 0) {
667 pdq_queue_commands(pdq
);
669 PDQ_CSR_WRITE(csrs
, csr_cmd_response_producer
,
670 ci
->ci_response_producer
| (ci
->ci_response_completion
<< 8));
671 PDQ_CSR_WRITE(csrs
, csr_cmd_request_producer
,
672 ci
->ci_request_producer
| (ci
->ci_request_completion
<< 8));
677 * This following routine processes unsolicited events.
678 * In addition, it also fills the unsolicited queue with
679 * event buffers so it can be used to initialize the queue
683 pdq_process_unsolicited_events(
686 const pdq_csrs_t
* const csrs
= &pdq
->pdq_csrs
;
687 pdq_unsolicited_info_t
*ui
= &pdq
->pdq_unsolicited_info
;
688 volatile const pdq_consumer_block_t
*cbp
= pdq
->pdq_cbp
;
689 pdq_descriptor_block_t
*dbp
= pdq
->pdq_dbp
;
692 * Process each unsolicited event (if any).
695 while (le32toh(cbp
->pdqcb_unsolicited_event
) != ui
->ui_completion
) {
696 const pdq_unsolicited_event_t
*event
;
699 event
= &ui
->ui_events
[ui
->ui_completion
& (PDQ_NUM_UNSOLICITED_EVENTS
-1)];
700 PDQ_OS_UNSOL_EVENT_POSTSYNC(pdq
, event
);
702 switch (event
->event_type
) {
703 case PDQ_UNSOLICITED_EVENT
: {
705 entity
= le32toh(event
->event_entity
);
706 value
= le32toh(event
->event_code
.value
);
708 case PDQ_ENTITY_STATION
: {
709 bad_event
= value
>= PDQ_STATION_EVENT_MAX
;
712 case PDQ_ENTITY_LINK
: {
713 bad_event
= value
>= PDQ_LINK_EVENT_MAX
;
716 case PDQ_ENTITY_PHY_PORT
: {
717 bad_event
= value
>= PDQ_PHY_EVENT_MAX
;
728 printf(PDQ_OS_PREFIX
"Unsolicited Event: %s: %s",
730 pdq_entities
[entity
],
731 pdq_event_codes
[entity
][value
]);
732 if (event
->event_entity
== PDQ_ENTITY_PHY_PORT
)
733 printf("[%d]", le32toh(event
->event_index
));
737 case PDQ_UNSOLICITED_COUNTERS
: {
741 PDQ_OS_UNSOL_EVENT_PRESYNC(pdq
, event
);
742 PDQ_ADVANCE(ui
->ui_completion
, 1, PDQ_RING_MASK(dbp
->pdqdb_unsolicited_events
));
747 * Now give back the event buffers back to the PDQ.
749 PDQ_ADVANCE(ui
->ui_producer
, ui
->ui_free
, PDQ_RING_MASK(dbp
->pdqdb_unsolicited_events
));
752 PDQ_CSR_WRITE(csrs
, csr_unsolicited_producer
,
753 ui
->ui_producer
| (ui
->ui_completion
<< 8));
757 pdq_process_received_data(
760 pdq_rxdesc_t
*receives
,
761 pdq_uint32_t completion_goal
,
762 pdq_uint32_t ring_mask
)
764 pdq_uint32_t completion
= rx
->rx_completion
;
765 pdq_uint32_t producer
= rx
->rx_producer
;
766 PDQ_OS_DATABUF_T
**buffers
= (PDQ_OS_DATABUF_T
**) rx
->rx_buffers
;
770 while (completion
!= completion_goal
) {
771 PDQ_OS_DATABUF_T
*fpdu
, *lpdu
, *npdu
;
772 pdq_uint8_t
*dataptr
;
773 pdq_uint32_t fc
, datalen
, pdulen
, segcnt
;
776 fpdu
= lpdu
= buffers
[completion
];
777 PDQ_ASSERT(fpdu
!= NULL
);
778 PDQ_OS_RXPDU_POSTSYNC(pdq
, fpdu
, 0, sizeof(u_int32_t
));
779 dataptr
= PDQ_OS_DATABUF_PTR(fpdu
);
780 status
= le32toh(*(pdq_uint32_t
*) dataptr
);
781 if (PDQ_RXS_RCC_BADPDU(status
) == 0) {
782 datalen
= PDQ_RXS_LEN(status
);
783 PDQ_OS_RXPDU_POSTSYNC(pdq
, fpdu
, sizeof(u_int32_t
),
784 PDQ_RX_FC_OFFSET
+ 1 - sizeof(u_int32_t
));
785 fc
= dataptr
[PDQ_RX_FC_OFFSET
];
786 switch (fc
& (PDQ_FDDIFC_C
|PDQ_FDDIFC_L
|PDQ_FDDIFC_F
)) {
787 case PDQ_FDDI_LLC_ASYNC
:
788 case PDQ_FDDI_LLC_SYNC
:
789 case PDQ_FDDI_IMP_ASYNC
:
790 case PDQ_FDDI_IMP_SYNC
: {
791 if (datalen
> PDQ_FDDI_MAX
|| datalen
< PDQ_FDDI_LLC_MIN
) {
792 PDQ_PRINTF(("discard: bad length %d\n", datalen
));
798 if (datalen
> PDQ_FDDI_MAX
|| datalen
< PDQ_FDDI_SMT_MIN
)
803 PDQ_PRINTF(("discard: bad fc 0x%x\n", fc
));
808 * Update the lengths of the data buffers now that we know
811 pdulen
= datalen
+ (PDQ_RX_FC_OFFSET
- PDQ_OS_HDR_OFFSET
) - 4 /* CRC */;
812 segcnt
= (pdulen
+ PDQ_OS_HDR_OFFSET
+ PDQ_OS_DATABUF_SIZE
- 1) / PDQ_OS_DATABUF_SIZE
;
813 PDQ_OS_DATABUF_ALLOC(pdq
, npdu
);
815 PDQ_PRINTF(("discard: no databuf #0\n"));
818 buffers
[completion
] = npdu
;
819 for (idx
= 1; idx
< segcnt
; idx
++) {
820 PDQ_OS_DATABUF_ALLOC(pdq
, npdu
);
822 PDQ_OS_DATABUF_NEXT_SET(lpdu
, NULL
);
823 PDQ_OS_DATABUF_FREE(pdq
, fpdu
);
826 PDQ_OS_DATABUF_NEXT_SET(lpdu
, buffers
[(completion
+ idx
) & ring_mask
]);
827 lpdu
= PDQ_OS_DATABUF_NEXT(lpdu
);
828 buffers
[(completion
+ idx
) & ring_mask
] = npdu
;
830 PDQ_OS_DATABUF_NEXT_SET(lpdu
, NULL
);
831 for (idx
= 0; idx
< PDQ_RX_SEGCNT
; idx
++) {
832 buffers
[(producer
+ idx
) & ring_mask
] =
833 buffers
[(completion
+ idx
) & ring_mask
];
834 buffers
[(completion
+ idx
) & ring_mask
] = NULL
;
836 PDQ_OS_DATABUF_ADJ(fpdu
, PDQ_OS_HDR_OFFSET
);
838 PDQ_OS_DATABUF_LEN_SET(fpdu
, pdulen
);
840 PDQ_OS_DATABUF_LEN_SET(lpdu
, pdulen
+ PDQ_OS_HDR_OFFSET
- (segcnt
- 1) * PDQ_OS_DATABUF_SIZE
);
843 * Do not pass to protocol if packet was received promiscuously
845 pdq_os_receive_pdu(pdq
, fpdu
, pdulen
,
846 PDQ_RXS_RCC_DD(status
) < PDQ_RXS_RCC_DD_CAM_MATCH
);
847 rx
->rx_free
+= PDQ_RX_SEGCNT
;
848 PDQ_ADVANCE(producer
, PDQ_RX_SEGCNT
, ring_mask
);
849 PDQ_ADVANCE(completion
, PDQ_RX_SEGCNT
, ring_mask
);
852 PDQ_PRINTF(("discard: bad pdu 0x%x(%d.%d.%d.%d.%d)\n", status
.rxs_status
,
853 PDQ_RXS_RCC_BADPDU(status
), PDQ_RXS_RCC_BADCRC(status
),
854 PDQ_RXS_RCC_REASON(status
), PDQ_RXS_FSC(status
),
855 PDQ_RXS_FSB_E(status
)));
856 if (PDQ_RXS_RCC_REASON(status
) == 7)
858 if (PDQ_RXS_RCC_REASON(status
) != 0) {
860 if (PDQ_RXS_RCC_BADCRC(status
)) {
861 printf(PDQ_OS_PREFIX
" MAC CRC error (source=%x-%x-%x-%x-%x-%x)\n",
863 dataptr
[PDQ_RX_FC_OFFSET
+1],
864 dataptr
[PDQ_RX_FC_OFFSET
+2],
865 dataptr
[PDQ_RX_FC_OFFSET
+3],
866 dataptr
[PDQ_RX_FC_OFFSET
+4],
867 dataptr
[PDQ_RX_FC_OFFSET
+5],
868 dataptr
[PDQ_RX_FC_OFFSET
+6]);
869 /* rx->rx_badcrc++; */
870 } else if (PDQ_RXS_FSC(status
) == 0 || PDQ_RXS_FSB_E(status
) == 1) {
871 /* rx->rx_frame_status_errors++; */
879 * Discarded frames go right back on the queue; therefore
880 * ring entries were freed.
882 for (idx
= 0; idx
< PDQ_RX_SEGCNT
; idx
++) {
883 buffers
[producer
] = buffers
[completion
];
884 buffers
[completion
] = NULL
;
885 rxd
= &receives
[rx
->rx_producer
];
887 rxd
->rxd_pa_hi
= htole32(
889 PDQ_RXDESC_SEG_CNT(PDQ_RX_SEGCNT
- 1) |
890 PDQ_RXDESC_SEG_LEN(PDQ_OS_DATABUF_SIZE
));
893 htole32(PDQ_RXDESC_SEG_LEN(PDQ_OS_DATABUF_SIZE
));
895 rxd
->rxd_pa_lo
= htole32(PDQ_OS_DATABUF_BUSPA(pdq
, buffers
[rx
->rx_producer
]));
896 PDQ_OS_RXPDU_PRESYNC(pdq
, buffers
[rx
->rx_producer
], 0, PDQ_OS_DATABUF_SIZE
);
897 PDQ_OS_DESC_PRESYNC(pdq
, rxd
, sizeof(*rxd
));
898 PDQ_ADVANCE(rx
->rx_producer
, 1, ring_mask
);
899 PDQ_ADVANCE(producer
, 1, ring_mask
);
900 PDQ_ADVANCE(completion
, 1, ring_mask
);
903 rx
->rx_completion
= completion
;
905 while (rx
->rx_free
> PDQ_RX_SEGCNT
&& rx
->rx_free
> rx
->rx_target
) {
906 PDQ_OS_DATABUF_T
*pdu
;
908 * Allocate the needed number of data buffers.
909 * Try to obtain them from our free queue before
910 * asking the system for more.
912 for (idx
= 0; idx
< PDQ_RX_SEGCNT
; idx
++) {
913 if ((pdu
= buffers
[(rx
->rx_producer
+ idx
) & ring_mask
]) == NULL
) {
914 PDQ_OS_DATABUF_ALLOC(pdq
, pdu
);
917 buffers
[(rx
->rx_producer
+ idx
) & ring_mask
] = pdu
;
919 rxd
= &receives
[(rx
->rx_producer
+ idx
) & ring_mask
];
921 rxd
->rxd_pa_hi
= htole32(
923 PDQ_RXDESC_SEG_CNT(PDQ_RX_SEGCNT
- 1)|
924 PDQ_RXDESC_SEG_LEN(PDQ_OS_DATABUF_SIZE
));
927 htole32(PDQ_RXDESC_SEG_LEN(PDQ_OS_DATABUF_SIZE
));
929 rxd
->rxd_pa_lo
= htole32(PDQ_OS_DATABUF_BUSPA(pdq
, pdu
));
930 PDQ_OS_RXPDU_PRESYNC(pdq
, pdu
, 0, PDQ_OS_DATABUF_SIZE
);
931 PDQ_OS_DESC_PRESYNC(pdq
, rxd
, sizeof(*rxd
));
933 if (idx
< PDQ_RX_SEGCNT
) {
935 * We didn't get all databufs required to complete a new
936 * receive buffer. Keep the ones we got and retry a bit
937 * later for the rest.
941 PDQ_ADVANCE(rx
->rx_producer
, PDQ_RX_SEGCNT
, ring_mask
);
942 rx
->rx_free
-= PDQ_RX_SEGCNT
;
946 static void pdq_process_transmitted_data(pdq_t
*pdq
);
949 pdq_queue_transmit_data(
951 PDQ_OS_DATABUF_T
*pdu
)
953 pdq_tx_info_t
* const tx
= &pdq
->pdq_tx_info
;
954 pdq_descriptor_block_t
* const dbp
= pdq
->pdq_dbp
;
955 pdq_uint32_t producer
= tx
->tx_producer
;
956 pdq_txdesc_t
*eop
= NULL
;
957 PDQ_OS_DATABUF_T
*pdu0
;
958 pdq_uint32_t freecnt
;
959 #if defined(PDQ_BUS_DMA)
964 if (PDQ_RX_FC_OFFSET
== PDQ_OS_HDR_OFFSET
) {
965 freecnt
= tx
->tx_free
- 1;
967 freecnt
= tx
->tx_free
;
970 * Need 2 or more descriptors to be able to send.
973 pdq
->pdq_intrmask
|= PDQ_HOST_INT_TX_ENABLE
;
974 PDQ_CSR_WRITE(&pdq
->pdq_csrs
, csr_host_int_enable
, pdq
->pdq_intrmask
);
978 if (PDQ_RX_FC_OFFSET
== PDQ_OS_HDR_OFFSET
) {
979 dbp
->pdqdb_transmits
[producer
] = tx
->tx_hdrdesc
;
980 PDQ_OS_DESC_PRESYNC(pdq
, &dbp
->pdqdb_transmits
[producer
], sizeof(pdq_txdesc_t
));
981 PDQ_ADVANCE(producer
, 1, PDQ_RING_MASK(dbp
->pdqdb_transmits
));
984 #if defined(PDQ_BUS_DMA)
985 map
= M_GETCTX(pdu
, bus_dmamap_t
);
986 if (freecnt
>= map
->dm_nsegs
) {
988 for (idx
= 0; idx
< map
->dm_nsegs
; idx
++) {
990 * Initialize the transmit descriptor
992 eop
= &dbp
->pdqdb_transmits
[producer
];
994 htole32(PDQ_TXDESC_SEG_LEN(map
->dm_segs
[idx
].ds_len
));
995 eop
->txd_pa_lo
= htole32(map
->dm_segs
[idx
].ds_addr
);
996 PDQ_OS_DESC_PRESYNC(pdq
, eop
, sizeof(pdq_txdesc_t
));
998 PDQ_ADVANCE(producer
, 1, PDQ_RING_MASK(dbp
->pdqdb_transmits
));
1005 for (freecnt
= tx
->tx_free
- 1, pdu0
= pdu
; pdu0
!= NULL
&& freecnt
> 0;) {
1006 pdq_uint32_t fraglen
, datalen
= PDQ_OS_DATABUF_LEN(pdu0
);
1007 const pdq_uint8_t
*dataptr
= PDQ_OS_DATABUF_PTR(pdu0
);
1010 * The first segment is limited to the space remaining in
1011 * page. All segments after that can be up to a full page
1014 fraglen
= PDQ_OS_PAGESIZE
- ((dataptr
- (pdq_uint8_t
*) NULL
) & (PDQ_OS_PAGESIZE
-1));
1015 while (datalen
> 0 && freecnt
> 0) {
1016 pdq_uint32_t seglen
= (fraglen
< datalen
? fraglen
: datalen
);
1019 * Initialize the transmit descriptor
1021 eop
= &dbp
->pdqdb_transmits
[producer
];
1022 eop
->txd_pa_hi
= htole32(PDQ_TXDESC_SEG_LEN(seglen
));
1023 eop
->txd_pa_lo
= htole32(PDQ_OS_VA_TO_BUSPA(pdq
, dataptr
));
1024 PDQ_OS_DESC_PRESYNC(pdq
, eop
, sizeof(pdq_txdesc_t
));
1027 fraglen
= PDQ_OS_PAGESIZE
;
1029 PDQ_ADVANCE(producer
, 1, PDQ_RING_MASK(dbp
->pdqdb_transmits
));
1031 pdu0
= PDQ_OS_DATABUF_NEXT(pdu0
);
1033 #endif /* defined(PDQ_BUS_DMA) */
1035 unsigned completion
= tx
->tx_completion
;
1036 PDQ_ASSERT(freecnt
== 0);
1037 PDQ_OS_CONSUMER_POSTSYNC(pdq
);
1038 pdq_process_transmitted_data(pdq
);
1039 if (completion
!= tx
->tx_completion
) {
1040 producer
= tx
->tx_producer
;
1045 * If we still have data to process then the ring was too full
1046 * to store the PDU. Return FALSE so the caller will requeue
1047 * the PDU for later.
1049 pdq
->pdq_intrmask
|= PDQ_HOST_INT_TX_ENABLE
;
1050 PDQ_CSR_WRITE(&pdq
->pdq_csrs
, csr_host_int_enable
, pdq
->pdq_intrmask
);
1054 * Everything went fine. Finish it up.
1056 tx
->tx_descriptor_count
[tx
->tx_producer
] = tx
->tx_free
- freecnt
;
1057 if (PDQ_RX_FC_OFFSET
!= PDQ_OS_HDR_OFFSET
) {
1058 dbp
->pdqdb_transmits
[tx
->tx_producer
].txd_pa_hi
|=
1059 htole32(PDQ_TXDESC_SOP
);
1060 PDQ_OS_DESC_PRESYNC(pdq
, &dbp
->pdqdb_transmits
[tx
->tx_producer
],
1061 sizeof(pdq_txdesc_t
));
1063 eop
->txd_pa_hi
|= htole32(PDQ_TXDESC_EOP
);
1064 PDQ_OS_DESC_PRESYNC(pdq
, eop
, sizeof(pdq_txdesc_t
));
1065 PDQ_OS_DATABUF_ENQUEUE(&tx
->tx_txq
, pdu
);
1066 tx
->tx_producer
= producer
;
1067 tx
->tx_free
= freecnt
;
1068 PDQ_DO_TYPE2_PRODUCER(pdq
);
1073 pdq_process_transmitted_data(
1076 pdq_tx_info_t
*tx
= &pdq
->pdq_tx_info
;
1077 volatile const pdq_consumer_block_t
*cbp
= pdq
->pdq_cbp
;
1078 pdq_descriptor_block_t
*dbp
= pdq
->pdq_dbp
;
1079 pdq_uint32_t completion
= tx
->tx_completion
;
1082 while (completion
!= le16toh(cbp
->pdqcb_transmits
)) {
1083 PDQ_OS_DATABUF_T
*pdu
;
1084 pdq_uint32_t descriptor_count
= tx
->tx_descriptor_count
[completion
];
1085 PDQ_ASSERT(dbp
->pdqdb_transmits
[completion
].txd_sop
== 1);
1086 PDQ_ASSERT(dbp
->pdqdb_transmits
[(completion
+ descriptor_count
- 1) & PDQ_RING_MASK(dbp
->pdqdb_transmits
)].txd_eop
== 1);
1087 PDQ_OS_DATABUF_DEQUEUE(&tx
->tx_txq
, pdu
);
1088 pdq_os_transmit_done(pdq
, pdu
);
1089 tx
->tx_free
+= descriptor_count
;
1091 PDQ_ADVANCE(completion
, descriptor_count
, PDQ_RING_MASK(dbp
->pdqdb_transmits
));
1093 if (tx
->tx_completion
!= completion
) {
1094 tx
->tx_completion
= completion
;
1095 pdq
->pdq_intrmask
&= ~PDQ_HOST_INT_TX_ENABLE
;
1096 PDQ_CSR_WRITE(&pdq
->pdq_csrs
, csr_host_int_enable
, pdq
->pdq_intrmask
);
1097 pdq_os_restart_transmitter(pdq
);
1100 PDQ_DO_TYPE2_PRODUCER(pdq
);
1104 pdq_flush_transmitter(
1107 volatile pdq_consumer_block_t
*cbp
= pdq
->pdq_cbp
;
1108 pdq_tx_info_t
*tx
= &pdq
->pdq_tx_info
;
1111 PDQ_OS_DATABUF_T
*pdu
;
1112 PDQ_OS_DATABUF_DEQUEUE(&tx
->tx_txq
, pdu
);
1116 * Don't call transmit done since the packet never made it
1119 PDQ_OS_DATABUF_FREE(pdq
, pdu
);
1122 tx
->tx_free
= PDQ_RING_MASK(pdq
->pdq_dbp
->pdqdb_transmits
);
1123 tx
->tx_completion
= tx
->tx_producer
;
1124 cbp
->pdqcb_transmits
= htole16(tx
->tx_completion
);
1125 PDQ_OS_CONSUMER_PRESYNC(pdq
);
1127 PDQ_DO_TYPE2_PRODUCER(pdq
);
1134 const pdq_csrs_t
* const csrs
= &pdq
->pdq_csrs
;
1138 state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs
, csr_port_status
));
1139 if (state
== PDQS_DMA_UNAVAILABLE
)
1141 PDQ_CSR_WRITE(csrs
, csr_port_data_a
,
1142 (state
== PDQS_HALTED
&& pdq
->pdq_type
!= PDQ_DEFTA
) ? 0 : PDQ_PRESET_SKIP_SELFTEST
);
1143 PDQ_CSR_WRITE(csrs
, csr_port_reset
, 1);
1144 PDQ_OS_USEC_DELAY(100);
1145 PDQ_CSR_WRITE(csrs
, csr_port_reset
, 0);
1146 for (cnt
= 100000;;cnt
--) {
1147 PDQ_OS_USEC_DELAY(1000);
1148 state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs
, csr_port_status
));
1149 if (state
== PDQS_DMA_UNAVAILABLE
|| cnt
== 0)
1152 PDQ_PRINTF(("PDQ Reset spun %d cycles\n", 100000 - cnt
));
1153 PDQ_OS_USEC_DELAY(10000);
1154 state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs
, csr_port_status
));
1155 PDQ_ASSERT(state
== PDQS_DMA_UNAVAILABLE
);
1156 PDQ_ASSERT(cnt
> 0);
1160 * The following routine brings the PDQ from whatever state it is
1161 * in to DMA_UNAVAILABLE (ie. like a RESET but without doing a RESET).
1168 const pdq_csrs_t
* const csrs
= &pdq
->pdq_csrs
;
1169 int cnt
, pass
= 0, idx
;
1170 PDQ_OS_DATABUF_T
**buffers
;
1173 state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs
, csr_port_status
));
1174 if (state
!= PDQS_DMA_UNAVAILABLE
) {
1176 state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs
, csr_port_status
));
1177 PDQ_ASSERT(state
== PDQS_DMA_UNAVAILABLE
);
1181 case PDQS_RING_MEMBER
:
1182 case PDQS_LINK_UNAVAILABLE
:
1183 case PDQS_LINK_AVAILABLE
: {
1184 PDQ_CSR_WRITE(csrs
, csr_port_data_a
, PDQ_SUB_CMD_LINK_UNINIT
);
1185 PDQ_CSR_WRITE(csrs
, csr_port_data_b
, 0);
1186 pdq_do_port_control(csrs
, PDQ_PCTL_SUB_CMD
);
1187 state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs
, csr_port_status
));
1188 PDQ_ASSERT(state
== PDQS_DMA_AVAILABLE
);
1191 case PDQS_DMA_AVAILABLE
: {
1192 PDQ_CSR_WRITE(csrs
, csr_port_data_a
, 0);
1193 PDQ_CSR_WRITE(csrs
, csr_port_data_b
, 0);
1194 pdq_do_port_control(csrs
, PDQ_PCTL_DMA_UNINIT
);
1195 state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs
, csr_port_status
));
1196 PDQ_ASSERT(state
== PDQS_DMA_UNAVAILABLE
);
1199 case PDQS_DMA_UNAVAILABLE
: {
1205 * Now we should be in DMA_UNAVAILABLE. So bring the PDQ into
1210 * Obtain the hardware address and firmware revisions
1211 * (MLA = my long address which is FDDI speak for hardware address)
1213 pdq_read_mla(&pdq
->pdq_csrs
, &pdq
->pdq_hwaddr
);
1214 pdq_read_fwrev(&pdq
->pdq_csrs
, &pdq
->pdq_fwrev
);
1215 pdq
->pdq_chip_rev
= pdq_read_chiprev(&pdq
->pdq_csrs
);
1217 if (pdq
->pdq_type
== PDQ_DEFPA
) {
1219 * Disable interrupts and DMA.
1221 PDQ_CSR_WRITE(&pdq
->pdq_pci_csrs
, csr_pfi_mode_control
, 0);
1222 PDQ_CSR_WRITE(&pdq
->pdq_pci_csrs
, csr_pfi_status
, 0x10);
1226 * Flush all the databuf queues.
1228 pdq_flush_databuf_queue(pdq
, &pdq
->pdq_tx_info
.tx_txq
);
1229 pdq
->pdq_flags
&= ~(PDQ_TXOK
|PDQ_IS_ONRING
|PDQ_IS_FDX
);
1230 buffers
= (PDQ_OS_DATABUF_T
**) pdq
->pdq_rx_info
.rx_buffers
;
1231 for (idx
= 0; idx
< PDQ_RING_SIZE(pdq
->pdq_dbp
->pdqdb_receives
); idx
++) {
1232 if (buffers
[idx
] != NULL
) {
1233 PDQ_OS_DATABUF_FREE(pdq
, buffers
[idx
]);
1234 buffers
[idx
] = NULL
;
1237 pdq
->pdq_rx_info
.rx_free
= PDQ_RING_MASK(pdq
->pdq_dbp
->pdqdb_receives
);
1238 buffers
= (PDQ_OS_DATABUF_T
**) pdq
->pdq_host_smt_info
.rx_buffers
;
1239 for (idx
= 0; idx
< PDQ_RING_SIZE(pdq
->pdq_dbp
->pdqdb_host_smt
); idx
++) {
1240 if (buffers
[idx
] != NULL
) {
1241 PDQ_OS_DATABUF_FREE(pdq
, buffers
[idx
]);
1242 buffers
[idx
] = NULL
;
1245 pdq
->pdq_host_smt_info
.rx_free
= PDQ_RING_MASK(pdq
->pdq_dbp
->pdqdb_host_smt
);
1248 * Reset the consumer indexes to 0.
1250 pdq
->pdq_cbp
->pdqcb_receives
= 0;
1251 pdq
->pdq_cbp
->pdqcb_transmits
= 0;
1252 pdq
->pdq_cbp
->pdqcb_host_smt
= 0;
1253 pdq
->pdq_cbp
->pdqcb_unsolicited_event
= 0;
1254 pdq
->pdq_cbp
->pdqcb_command_response
= 0;
1255 pdq
->pdq_cbp
->pdqcb_command_request
= 0;
1256 PDQ_OS_CONSUMER_PRESYNC(pdq
);
1259 * Reset the producer and completion indexes to 0.
1261 pdq
->pdq_command_info
.ci_request_producer
= 0;
1262 pdq
->pdq_command_info
.ci_response_producer
= 0;
1263 pdq
->pdq_command_info
.ci_request_completion
= 0;
1264 pdq
->pdq_command_info
.ci_response_completion
= 0;
1265 pdq
->pdq_unsolicited_info
.ui_producer
= 0;
1266 pdq
->pdq_unsolicited_info
.ui_completion
= 0;
1267 pdq
->pdq_rx_info
.rx_producer
= 0;
1268 pdq
->pdq_rx_info
.rx_completion
= 0;
1269 pdq
->pdq_tx_info
.tx_producer
= 0;
1270 pdq
->pdq_tx_info
.tx_completion
= 0;
1271 pdq
->pdq_host_smt_info
.rx_producer
= 0;
1272 pdq
->pdq_host_smt_info
.rx_completion
= 0;
1274 pdq
->pdq_command_info
.ci_command_active
= 0;
1275 pdq
->pdq_unsolicited_info
.ui_free
= PDQ_NUM_UNSOLICITED_EVENTS
;
1276 pdq
->pdq_tx_info
.tx_free
= PDQ_RING_MASK(pdq
->pdq_dbp
->pdqdb_transmits
);
1279 * Allow the DEFPA to do DMA. Then program the physical
1280 * addresses of the consumer and descriptor blocks.
1282 if (pdq
->pdq_type
== PDQ_DEFPA
) {
1284 PDQ_CSR_WRITE(&pdq
->pdq_pci_csrs
, csr_pfi_mode_control
,
1285 PDQ_PFI_MODE_DMA_ENABLE
);
1287 PDQ_CSR_WRITE(&pdq
->pdq_pci_csrs
, csr_pfi_mode_control
,
1288 PDQ_PFI_MODE_DMA_ENABLE
1289 /*|PDQ_PFI_MODE_PFI_PCI_INTR*/|PDQ_PFI_MODE_PDQ_PCI_INTR
);
1294 * Make sure the unsolicited queue has events ...
1296 pdq_process_unsolicited_events(pdq
);
1298 if ((pdq
->pdq_type
== PDQ_DEFEA
&& pdq
->pdq_chip_rev
== PDQ_CHIP_REV_E
)
1299 || pdq
->pdq_type
== PDQ_DEFTA
)
1300 PDQ_CSR_WRITE(csrs
, csr_port_data_b
, PDQ_DMA_BURST_16LW
);
1302 PDQ_CSR_WRITE(csrs
, csr_port_data_b
, PDQ_DMA_BURST_8LW
);
1303 PDQ_CSR_WRITE(csrs
, csr_port_data_a
, PDQ_SUB_CMD_DMA_BURST_SIZE_SET
);
1304 pdq_do_port_control(csrs
, PDQ_PCTL_SUB_CMD
);
1307 * Make sure there isn't stale information in the caches before
1308 * tell the adapter about the blocks it's going to use.
1310 PDQ_OS_CONSUMER_PRESYNC(pdq
);
1312 PDQ_CSR_WRITE(csrs
, csr_port_data_b
, 0);
1313 PDQ_CSR_WRITE(csrs
, csr_port_data_a
, pdq
->pdq_pa_consumer_block
);
1314 pdq_do_port_control(csrs
, PDQ_PCTL_CONSUMER_BLOCK
);
1316 PDQ_CSR_WRITE(csrs
, csr_port_data_b
, 0);
1317 PDQ_CSR_WRITE(csrs
, csr_port_data_a
, pdq
->pdq_pa_descriptor_block
| PDQ_DMA_INIT_LW_BSWAP_DATA
);
1318 pdq_do_port_control(csrs
, PDQ_PCTL_DMA_INIT
);
1320 for (cnt
= 0; cnt
< 1000; cnt
++) {
1321 state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs
, csr_port_status
));
1322 if (state
== PDQS_HALTED
) {
1328 if (state
== PDQS_DMA_AVAILABLE
) {
1329 PDQ_PRINTF(("Transition to DMA Available took %d spins\n", cnt
));
1332 PDQ_OS_USEC_DELAY(1000);
1334 PDQ_ASSERT(state
== PDQS_DMA_AVAILABLE
);
1336 PDQ_CSR_WRITE(csrs
, csr_host_int_type_0
, 0xFF);
1337 pdq
->pdq_intrmask
= 0;
1338 /* PDQ_HOST_INT_STATE_CHANGE
1339 |PDQ_HOST_INT_FATAL_ERROR|PDQ_HOST_INT_CMD_RSP_ENABLE
1340 |PDQ_HOST_INT_UNSOL_ENABLE */;
1341 PDQ_CSR_WRITE(csrs
, csr_host_int_enable
, pdq
->pdq_intrmask
);
1344 * Any other command but START should be valid.
1346 pdq
->pdq_command_info
.ci_pending_commands
&= ~(PDQ_BITMASK(PDQC_START
));
1347 if (pdq
->pdq_flags
& PDQ_PRINTCHARS
)
1348 pdq
->pdq_command_info
.ci_pending_commands
|= PDQ_BITMASK(PDQC_STATUS_CHARS_GET
);
1349 pdq_queue_commands(pdq
);
1351 if (pdq
->pdq_flags
& PDQ_PRINTCHARS
) {
1353 * Now wait (up to 100ms) for the command(s) to finish.
1355 for (cnt
= 0; cnt
< 1000; cnt
++) {
1356 PDQ_OS_CONSUMER_POSTSYNC(pdq
);
1357 pdq_process_command_responses(pdq
);
1358 if (pdq
->pdq_command_info
.ci_response_producer
== pdq
->pdq_command_info
.ci_response_completion
)
1360 PDQ_OS_USEC_DELAY(1000);
1362 state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs
, csr_port_status
));
1372 const pdq_csrs_t
* const csrs
= &pdq
->pdq_csrs
;
1375 state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs
, csr_port_status
));
1376 PDQ_ASSERT(state
!= PDQS_DMA_UNAVAILABLE
);
1377 PDQ_ASSERT(state
!= PDQS_RESET
);
1378 PDQ_ASSERT(state
!= PDQS_HALTED
);
1379 PDQ_ASSERT(state
!= PDQS_UPGRADE
);
1380 PDQ_ASSERT(state
!= PDQS_RING_MEMBER
);
1382 case PDQS_DMA_AVAILABLE
: {
1384 * The PDQ after being reset screws up some of its state.
1385 * So we need to clear all the errors/interrupts so the real
1386 * ones will get through.
1388 PDQ_CSR_WRITE(csrs
, csr_host_int_type_0
, 0xFF);
1389 pdq
->pdq_intrmask
= PDQ_HOST_INT_STATE_CHANGE
1390 |PDQ_HOST_INT_XMT_DATA_FLUSH
|PDQ_HOST_INT_FATAL_ERROR
1391 |PDQ_HOST_INT_CMD_RSP_ENABLE
|PDQ_HOST_INT_UNSOL_ENABLE
1392 |PDQ_HOST_INT_RX_ENABLE
|PDQ_HOST_INT_HOST_SMT_ENABLE
;
1393 PDQ_CSR_WRITE(csrs
, csr_host_int_enable
, pdq
->pdq_intrmask
);
1395 * Set the MAC and address filters and start up the PDQ.
1397 pdq_process_unsolicited_events(pdq
);
1398 pdq_process_received_data(pdq
, &pdq
->pdq_rx_info
,
1399 pdq
->pdq_dbp
->pdqdb_receives
,
1400 le16toh(pdq
->pdq_cbp
->pdqcb_receives
),
1401 PDQ_RING_MASK(pdq
->pdq_dbp
->pdqdb_receives
));
1402 PDQ_DO_TYPE2_PRODUCER(pdq
);
1403 if (pdq
->pdq_flags
& PDQ_PASS_SMT
) {
1404 pdq_process_received_data(pdq
, &pdq
->pdq_host_smt_info
,
1405 pdq
->pdq_dbp
->pdqdb_host_smt
,
1406 le32toh(pdq
->pdq_cbp
->pdqcb_host_smt
),
1407 PDQ_RING_MASK(pdq
->pdq_dbp
->pdqdb_host_smt
));
1408 PDQ_CSR_WRITE(csrs
, csr_host_smt_producer
,
1409 pdq
->pdq_host_smt_info
.rx_producer
1410 | (pdq
->pdq_host_smt_info
.rx_completion
<< 8));
1412 pdq
->pdq_command_info
.ci_pending_commands
= PDQ_BITMASK(PDQC_FILTER_SET
)
1413 | PDQ_BITMASK(PDQC_ADDR_FILTER_SET
)
1414 | PDQ_BITMASK(PDQC_SNMP_SET
)
1415 | PDQ_BITMASK(PDQC_START
);
1416 if (pdq
->pdq_flags
& PDQ_PRINTCHARS
)
1417 pdq
->pdq_command_info
.ci_pending_commands
|= PDQ_BITMASK(PDQC_STATUS_CHARS_GET
);
1418 pdq_queue_commands(pdq
);
1421 case PDQS_LINK_UNAVAILABLE
:
1422 case PDQS_LINK_AVAILABLE
: {
1423 pdq
->pdq_command_info
.ci_pending_commands
= PDQ_BITMASK(PDQC_FILTER_SET
)
1424 | PDQ_BITMASK(PDQC_ADDR_FILTER_SET
)
1425 | PDQ_BITMASK(PDQC_SNMP_SET
);
1426 if (pdq
->pdq_flags
& PDQ_PRINTCHARS
)
1427 pdq
->pdq_command_info
.ci_pending_commands
|= PDQ_BITMASK(PDQC_STATUS_CHARS_GET
);
1428 if (pdq
->pdq_flags
& PDQ_PASS_SMT
) {
1429 pdq_process_received_data(pdq
, &pdq
->pdq_host_smt_info
,
1430 pdq
->pdq_dbp
->pdqdb_host_smt
,
1431 le32toh(pdq
->pdq_cbp
->pdqcb_host_smt
),
1432 PDQ_RING_MASK(pdq
->pdq_dbp
->pdqdb_host_smt
));
1433 PDQ_CSR_WRITE(csrs
, csr_host_smt_producer
,
1434 pdq
->pdq_host_smt_info
.rx_producer
1435 | (pdq
->pdq_host_smt_info
.rx_completion
<< 8));
1437 pdq_process_unsolicited_events(pdq
);
1438 pdq_queue_commands(pdq
);
1441 case PDQS_RING_MEMBER
: {
1443 default: { /* to make gcc happy */
1453 const pdq_csrs_t
* const csrs
= &pdq
->pdq_csrs
;
1457 if (pdq
->pdq_type
== PDQ_DEFPA
)
1458 PDQ_CSR_WRITE(&pdq
->pdq_pci_csrs
, csr_pfi_status
, 0x18);
1460 while ((data
= PDQ_CSR_READ(csrs
, csr_port_status
)) & PDQ_PSTS_INTR_PENDING
) {
1462 PDQ_PRINTF(("PDQ Interrupt: Status = 0x%08x\n", data
));
1463 PDQ_OS_CONSUMER_POSTSYNC(pdq
);
1464 if (data
& PDQ_PSTS_RCV_DATA_PENDING
) {
1465 pdq_process_received_data(pdq
, &pdq
->pdq_rx_info
,
1466 pdq
->pdq_dbp
->pdqdb_receives
,
1467 le16toh(pdq
->pdq_cbp
->pdqcb_receives
),
1468 PDQ_RING_MASK(pdq
->pdq_dbp
->pdqdb_receives
));
1469 PDQ_DO_TYPE2_PRODUCER(pdq
);
1471 if (data
& PDQ_PSTS_HOST_SMT_PENDING
) {
1472 pdq_process_received_data(pdq
, &pdq
->pdq_host_smt_info
,
1473 pdq
->pdq_dbp
->pdqdb_host_smt
,
1474 le32toh(pdq
->pdq_cbp
->pdqcb_host_smt
),
1475 PDQ_RING_MASK(pdq
->pdq_dbp
->pdqdb_host_smt
));
1476 PDQ_DO_HOST_SMT_PRODUCER(pdq
);
1478 /* if (data & PDQ_PSTS_XMT_DATA_PENDING) */
1479 pdq_process_transmitted_data(pdq
);
1480 if (data
& PDQ_PSTS_UNSOL_PENDING
)
1481 pdq_process_unsolicited_events(pdq
);
1482 if (data
& PDQ_PSTS_CMD_RSP_PENDING
)
1483 pdq_process_command_responses(pdq
);
1484 if (data
& PDQ_PSTS_TYPE_0_PENDING
) {
1485 data
= PDQ_CSR_READ(csrs
, csr_host_int_type_0
);
1486 if (data
& PDQ_HOST_INT_STATE_CHANGE
) {
1487 pdq_state_t state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs
, csr_port_status
));
1488 printf(PDQ_OS_PREFIX
"%s", PDQ_OS_PREFIX_ARGS
, pdq_adapter_states
[state
]);
1489 if (state
== PDQS_LINK_UNAVAILABLE
) {
1490 pdq
->pdq_flags
&= ~(PDQ_TXOK
|PDQ_IS_ONRING
|PDQ_IS_FDX
);
1491 } else if (state
== PDQS_LINK_AVAILABLE
) {
1492 if (pdq
->pdq_flags
& PDQ_WANT_FDX
) {
1493 pdq
->pdq_command_info
.ci_pending_commands
|= PDQ_BITMASK(PDQC_DEC_EXT_MIB_GET
);
1494 pdq_queue_commands(pdq
);
1496 pdq
->pdq_flags
|= PDQ_TXOK
|PDQ_IS_ONRING
;
1497 pdq_os_restart_transmitter(pdq
);
1498 } else if (state
== PDQS_HALTED
) {
1499 pdq_response_error_log_get_t log_entry
;
1500 pdq_halt_code_t halt_code
= PDQ_PSTS_HALT_ID(PDQ_CSR_READ(csrs
, csr_port_status
));
1501 printf(": halt code = %d (%s)\n",
1502 halt_code
, pdq_halt_codes
[halt_code
]);
1503 if (halt_code
== PDQH_DMA_ERROR
&& pdq
->pdq_type
== PDQ_DEFPA
) {
1504 PDQ_PRINTF(("\tPFI status = 0x%x, Host 0 Fatal Interrupt = 0x%x\n",
1505 PDQ_CSR_READ(&pdq
->pdq_pci_csrs
, csr_pfi_status
),
1506 data
& PDQ_HOST_INT_FATAL_ERROR
));
1508 PDQ_OS_MEMZERO(&log_entry
, sizeof(log_entry
));
1509 if (pdq_read_error_log(pdq
, &log_entry
)) {
1510 PDQ_PRINTF((" Error log Entry:\n"));
1511 PDQ_PRINTF((" CMD Status = %d (0x%x)\n",
1512 log_entry
.error_log_get_status
,
1513 log_entry
.error_log_get_status
));
1514 PDQ_PRINTF((" Event Status = %d (0x%x)\n",
1515 log_entry
.error_log_get_event_status
,
1516 log_entry
.error_log_get_event_status
));
1517 PDQ_PRINTF((" Caller Id = %d (0x%x)\n",
1518 log_entry
.error_log_get_caller_id
,
1519 log_entry
.error_log_get_caller_id
));
1520 PDQ_PRINTF((" Write Count = %d (0x%x)\n",
1521 log_entry
.error_log_get_write_count
,
1522 log_entry
.error_log_get_write_count
));
1523 PDQ_PRINTF((" FRU Implication Mask = %d (0x%x)\n",
1524 log_entry
.error_log_get_fru_implication_mask
,
1525 log_entry
.error_log_get_fru_implication_mask
));
1526 PDQ_PRINTF((" Test ID = %d (0x%x)\n",
1527 log_entry
.error_log_get_test_id
,
1528 log_entry
.error_log_get_test_id
));
1531 if (pdq
->pdq_flags
& PDQ_RUNNING
)
1536 PDQ_CSR_WRITE(csrs
, csr_host_int_type_0
, PDQ_HOST_INT_STATE_CHANGE
);
1538 if (data
& PDQ_HOST_INT_FATAL_ERROR
) {
1540 if (pdq
->pdq_flags
& PDQ_RUNNING
)
1544 if (data
& PDQ_HOST_INT_XMT_DATA_FLUSH
) {
1545 printf(PDQ_OS_PREFIX
"Flushing transmit queue\n", PDQ_OS_PREFIX_ARGS
);
1546 pdq
->pdq_flags
&= ~PDQ_TXOK
;
1547 pdq_flush_transmitter(pdq
);
1548 pdq_do_port_control(csrs
, PDQ_PCTL_XMT_DATA_FLUSH_DONE
);
1549 PDQ_CSR_WRITE(csrs
, csr_host_int_type_0
, PDQ_HOST_INT_XMT_DATA_FLUSH
);
1552 if (pdq
->pdq_type
== PDQ_DEFPA
)
1553 PDQ_CSR_WRITE(&pdq
->pdq_pci_csrs
, csr_pfi_status
, 0x18);
1561 pdq_bus_memaddr_t csr_base
,
1569 pdq_descriptor_block_t
*dbp
;
1570 #if !defined(PDQ_BUS_DMA)
1571 const pdq_uint32_t contig_bytes
= (sizeof(pdq_descriptor_block_t
) * 2) - PDQ_OS_PAGESIZE
;
1576 PDQ_ASSERT(sizeof(pdq_descriptor_block_t
) == 8192);
1577 PDQ_ASSERT(sizeof(pdq_consumer_block_t
) == 64);
1578 PDQ_ASSERT(sizeof(pdq_response_filter_get_t
) == PDQ_SIZE_RESPONSE_FILTER_GET
);
1579 PDQ_ASSERT(sizeof(pdq_cmd_addr_filter_set_t
) == PDQ_SIZE_CMD_ADDR_FILTER_SET
);
1580 PDQ_ASSERT(sizeof(pdq_response_addr_filter_get_t
) == PDQ_SIZE_RESPONSE_ADDR_FILTER_GET
);
1581 PDQ_ASSERT(sizeof(pdq_response_status_chars_get_t
) == PDQ_SIZE_RESPONSE_STATUS_CHARS_GET
);
1582 PDQ_ASSERT(sizeof(pdq_response_fddi_mib_get_t
) == PDQ_SIZE_RESPONSE_FDDI_MIB_GET
);
1583 PDQ_ASSERT(sizeof(pdq_response_dec_ext_mib_get_t
) == PDQ_SIZE_RESPONSE_DEC_EXT_MIB_GET
);
1584 PDQ_ASSERT(sizeof(pdq_unsolicited_event_t
) == 512);
1586 pdq
= (pdq_t
*) PDQ_OS_MEMALLOC(sizeof(pdq_t
));
1588 PDQ_PRINTF(("malloc(%d) failed\n", sizeof(*pdq
)));
1591 PDQ_OS_MEMZERO(pdq
, sizeof(pdq_t
));
1592 pdq
->pdq_type
= type
;
1593 pdq
->pdq_unit
= unit
;
1594 pdq
->pdq_os_ctx
= (void *) ctx
;
1595 pdq
->pdq_os_name
= name
;
1596 pdq
->pdq_flags
= PDQ_PRINTCHARS
;
1598 * Allocate the additional data structures required by
1599 * the PDQ driver. Allocate a contiguous region of memory
1600 * for the descriptor block. We need to allocated enough
1601 * to guarantee that we will a get 8KB block of memory aligned
1602 * on a 8KB boundary. This turns to require that we allocate
1603 * (N*2 - 1 page) pages of memory. On machine with less than
1604 * a 8KB page size, it mean we will allocate more memory than
1605 * we need. The extra will be used for the unsolicited event
1606 * buffers (though on machines with 8KB pages we will to allocate
1607 * them separately since there will be nothing left overs.)
1609 #if defined(PDQ_OS_MEMALLOC_CONTIG)
1610 p
= (pdq_uint8_t
*) PDQ_OS_MEMALLOC_CONTIG(contig_bytes
);
1612 pdq_physaddr_t physaddr
= PDQ_OS_VA_TO_BUSPA(pdq
, p
);
1614 * Assert that we really got contiguous memory. This isn't really
1615 * needed on systems that actually have physical contiguous allocation
1616 * routines, but on those systems that don't ...
1618 for (idx
= PDQ_OS_PAGESIZE
; idx
< 0x2000; idx
+= PDQ_OS_PAGESIZE
) {
1619 if (PDQ_OS_VA_TO_BUSPA(pdq
, p
+ idx
) - physaddr
!= idx
)
1620 goto cleanup_and_return
;
1622 if (physaddr
& 0x1FFF) {
1623 pdq
->pdq_unsolicited_info
.ui_events
= (pdq_unsolicited_event_t
*) p
;
1624 pdq
->pdq_unsolicited_info
.ui_pa_bufstart
= physaddr
;
1625 pdq
->pdq_dbp
= (pdq_descriptor_block_t
*) &p
[0x2000 - (physaddr
& 0x1FFF)];
1626 pdq
->pdq_pa_descriptor_block
= physaddr
& ~0x1FFFUL
;
1628 pdq
->pdq_dbp
= (pdq_descriptor_block_t
*) p
;
1629 pdq
->pdq_pa_descriptor_block
= physaddr
;
1630 pdq
->pdq_unsolicited_info
.ui_events
= (pdq_unsolicited_event_t
*) &p
[0x2000];
1631 pdq
->pdq_unsolicited_info
.ui_pa_bufstart
= physaddr
+ 0x2000;
1634 pdq
->pdq_cbp
= (volatile pdq_consumer_block_t
*) &pdq
->pdq_dbp
->pdqdb_consumer
;
1635 pdq
->pdq_pa_consumer_block
= PDQ_DB_BUSPA(pdq
, pdq
->pdq_cbp
);
1636 if (contig_bytes
== sizeof(pdq_descriptor_block_t
)) {
1637 pdq
->pdq_unsolicited_info
.ui_events
=
1638 (pdq_unsolicited_event_t
*) PDQ_OS_MEMALLOC(
1639 PDQ_NUM_UNSOLICITED_EVENTS
* sizeof(pdq_unsolicited_event_t
));
1642 if (pdq_os_memalloc_contig(pdq
))
1643 goto cleanup_and_return
;
1647 * Make sure everything got allocated. If not, free what did
1648 * get allocated and return.
1650 if (pdq
->pdq_dbp
== NULL
|| pdq
->pdq_unsolicited_info
.ui_events
== NULL
) {
1652 #ifdef PDQ_OS_MEMFREE_CONTIG
1653 if (p
/* pdq->pdq_dbp */ != NULL
)
1654 PDQ_OS_MEMFREE_CONTIG(p
/* pdq->pdq_dbp */, contig_bytes
);
1655 if (contig_bytes
== sizeof(pdq_descriptor_block_t
) && pdq
->pdq_unsolicited_info
.ui_events
!= NULL
)
1656 PDQ_OS_MEMFREE(pdq
->pdq_unsolicited_info
.ui_events
,
1657 PDQ_NUM_UNSOLICITED_EVENTS
* sizeof(pdq_unsolicited_event_t
));
1659 PDQ_OS_MEMFREE(pdq
, sizeof(pdq_t
));
1664 PDQ_PRINTF(("\nPDQ Descriptor Block = " PDQ_OS_PTR_FMT
" (PA = 0x%x)\n", dbp
, pdq
->pdq_pa_descriptor_block
));
1665 PDQ_PRINTF((" Receive Queue = " PDQ_OS_PTR_FMT
"\n", dbp
->pdqdb_receives
));
1666 PDQ_PRINTF((" Transmit Queue = " PDQ_OS_PTR_FMT
"\n", dbp
->pdqdb_transmits
));
1667 PDQ_PRINTF((" Host SMT Queue = " PDQ_OS_PTR_FMT
"\n", dbp
->pdqdb_host_smt
));
1668 PDQ_PRINTF((" Command Response Queue = " PDQ_OS_PTR_FMT
"\n", dbp
->pdqdb_command_responses
));
1669 PDQ_PRINTF((" Command Request Queue = " PDQ_OS_PTR_FMT
"\n", dbp
->pdqdb_command_requests
));
1670 PDQ_PRINTF(("PDQ Consumer Block = " PDQ_OS_PTR_FMT
"\n", pdq
->pdq_cbp
));
1673 * Zero out the descriptor block. Not really required but
1674 * it pays to be neat. This will also zero out the consumer
1675 * block, command pool, and buffer pointers for the receive
1678 PDQ_OS_MEMZERO(dbp
, sizeof(*dbp
));
1681 * Initialize the CSR references.
1682 * the DEFAA (FutureBus+) skips a longword between registers
1684 pdq_init_csrs(&pdq
->pdq_csrs
, bus
, csr_base
, pdq
->pdq_type
== PDQ_DEFAA
? 2 : 1);
1685 if (pdq
->pdq_type
== PDQ_DEFPA
)
1686 pdq_init_pci_csrs(&pdq
->pdq_pci_csrs
, bus
, csr_base
, 1);
1688 PDQ_PRINTF(("PDQ CSRs: BASE = " PDQ_OS_CSR_FMT
"\n", pdq
->pdq_csrs
.csr_base
));
1689 PDQ_PRINTF((" Port Reset = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1690 pdq
->pdq_csrs
.csr_port_reset
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_port_reset
)));
1691 PDQ_PRINTF((" Host Data = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1692 pdq
->pdq_csrs
.csr_host_data
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_host_data
)));
1693 PDQ_PRINTF((" Port Control = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1694 pdq
->pdq_csrs
.csr_port_control
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_port_control
)));
1695 PDQ_PRINTF((" Port Data A = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1696 pdq
->pdq_csrs
.csr_port_data_a
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_port_data_a
)));
1697 PDQ_PRINTF((" Port Data B = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1698 pdq
->pdq_csrs
.csr_port_data_b
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_port_data_b
)));
1699 PDQ_PRINTF((" Port Status = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1700 pdq
->pdq_csrs
.csr_port_status
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_port_status
)));
1701 PDQ_PRINTF((" Host Int Type 0 = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1702 pdq
->pdq_csrs
.csr_host_int_type_0
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_host_int_type_0
)));
1703 PDQ_PRINTF((" Host Int Enable = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1704 pdq
->pdq_csrs
.csr_host_int_enable
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_host_int_enable
)));
1705 PDQ_PRINTF((" Type 2 Producer = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1706 pdq
->pdq_csrs
.csr_type_2_producer
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_type_2_producer
)));
1707 PDQ_PRINTF((" Command Response Producer = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1708 pdq
->pdq_csrs
.csr_cmd_response_producer
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_cmd_response_producer
)));
1709 PDQ_PRINTF((" Command Request Producer = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1710 pdq
->pdq_csrs
.csr_cmd_request_producer
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_cmd_request_producer
)));
1711 PDQ_PRINTF((" Host SMT Producer = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1712 pdq
->pdq_csrs
.csr_host_smt_producer
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_host_smt_producer
)));
1713 PDQ_PRINTF((" Unsolicited Producer = " PDQ_OS_CSR_FMT
" [0x%08x]\n",
1714 pdq
->pdq_csrs
.csr_unsolicited_producer
, PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_unsolicited_producer
)));
1717 * Initialize the command information block
1719 pdq
->pdq_command_info
.ci_request_bufstart
= dbp
->pdqdb_cmd_request_buf
;
1720 pdq
->pdq_command_info
.ci_pa_request_bufstart
= PDQ_DB_BUSPA(pdq
, pdq
->pdq_command_info
.ci_request_bufstart
);
1721 pdq
->pdq_command_info
.ci_pa_request_descriptors
= PDQ_DB_BUSPA(pdq
, dbp
->pdqdb_command_requests
);
1722 PDQ_PRINTF(("PDQ Command Request Buffer = " PDQ_OS_PTR_FMT
" (PA=0x%x)\n",
1723 pdq
->pdq_command_info
.ci_request_bufstart
,
1724 pdq
->pdq_command_info
.ci_pa_request_bufstart
));
1725 for (idx
= 0; idx
< sizeof(dbp
->pdqdb_command_requests
)/sizeof(dbp
->pdqdb_command_requests
[0]); idx
++) {
1726 pdq_txdesc_t
*txd
= &dbp
->pdqdb_command_requests
[idx
];
1728 txd
->txd_pa_lo
= htole32(pdq
->pdq_command_info
.ci_pa_request_bufstart
);
1729 txd
->txd_pa_hi
= htole32(PDQ_TXDESC_SOP
| PDQ_TXDESC_EOP
);
1731 PDQ_OS_DESC_PRESYNC(pdq
, dbp
->pdqdb_command_requests
,
1732 sizeof(dbp
->pdqdb_command_requests
));
1734 pdq
->pdq_command_info
.ci_response_bufstart
= dbp
->pdqdb_cmd_response_buf
;
1735 pdq
->pdq_command_info
.ci_pa_response_bufstart
= PDQ_DB_BUSPA(pdq
, pdq
->pdq_command_info
.ci_response_bufstart
);
1736 pdq
->pdq_command_info
.ci_pa_response_descriptors
= PDQ_DB_BUSPA(pdq
, dbp
->pdqdb_command_responses
);
1737 PDQ_PRINTF(("PDQ Command Response Buffer = " PDQ_OS_PTR_FMT
" (PA=0x%x)\n",
1738 pdq
->pdq_command_info
.ci_response_bufstart
,
1739 pdq
->pdq_command_info
.ci_pa_response_bufstart
));
1740 for (idx
= 0; idx
< sizeof(dbp
->pdqdb_command_responses
)/sizeof(dbp
->pdqdb_command_responses
[0]); idx
++) {
1741 pdq_rxdesc_t
*rxd
= &dbp
->pdqdb_command_responses
[idx
];
1743 rxd
->rxd_pa_hi
= htole32(PDQ_RXDESC_SOP
|
1744 PDQ_RXDESC_SEG_LEN(PDQ_SIZE_COMMAND_RESPONSE
));
1745 rxd
->rxd_pa_lo
= htole32(pdq
->pdq_command_info
.ci_pa_response_bufstart
);
1747 PDQ_OS_DESC_PRESYNC(pdq
, dbp
->pdqdb_command_responses
,
1748 sizeof(dbp
->pdqdb_command_responses
));
1751 * Initialize the unsolicited event information block
1753 pdq
->pdq_unsolicited_info
.ui_free
= PDQ_NUM_UNSOLICITED_EVENTS
;
1754 pdq
->pdq_unsolicited_info
.ui_pa_descriptors
= PDQ_DB_BUSPA(pdq
, dbp
->pdqdb_unsolicited_events
);
1755 PDQ_PRINTF(("PDQ Unsolicit Event Buffer = " PDQ_OS_PTR_FMT
" (PA=0x%x)\n",
1756 pdq
->pdq_unsolicited_info
.ui_events
,
1757 pdq
->pdq_unsolicited_info
.ui_pa_bufstart
));
1758 for (idx
= 0; idx
< sizeof(dbp
->pdqdb_unsolicited_events
)/sizeof(dbp
->pdqdb_unsolicited_events
[0]); idx
++) {
1759 pdq_rxdesc_t
*rxd
= &dbp
->pdqdb_unsolicited_events
[idx
];
1760 pdq_unsolicited_event_t
*event
= &pdq
->pdq_unsolicited_info
.ui_events
[idx
& (PDQ_NUM_UNSOLICITED_EVENTS
-1)];
1762 rxd
->rxd_pa_hi
= htole32(PDQ_RXDESC_SOP
|
1763 PDQ_RXDESC_SEG_LEN(sizeof(pdq_unsolicited_event_t
)));
1764 rxd
->rxd_pa_lo
= htole32(pdq
->pdq_unsolicited_info
.ui_pa_bufstart
+ (const pdq_uint8_t
*) event
1765 - (const pdq_uint8_t
*) pdq
->pdq_unsolicited_info
.ui_events
);
1766 PDQ_OS_UNSOL_EVENT_PRESYNC(pdq
, event
);
1768 PDQ_OS_DESC_PRESYNC(pdq
, dbp
->pdqdb_unsolicited_events
,
1769 sizeof(dbp
->pdqdb_unsolicited_events
));
1772 * Initialize the receive information blocks (normal and SMT).
1774 pdq
->pdq_rx_info
.rx_buffers
= pdq
->pdq_receive_buffers
;
1775 pdq
->pdq_rx_info
.rx_free
= PDQ_RING_MASK(dbp
->pdqdb_receives
);
1776 pdq
->pdq_rx_info
.rx_target
= pdq
->pdq_rx_info
.rx_free
- PDQ_RX_SEGCNT
* 8;
1777 pdq
->pdq_rx_info
.rx_pa_descriptors
= PDQ_DB_BUSPA(pdq
, dbp
->pdqdb_receives
);
1779 pdq
->pdq_host_smt_info
.rx_buffers
= pdq
->pdq_host_smt_buffers
;
1780 pdq
->pdq_host_smt_info
.rx_free
= PDQ_RING_MASK(dbp
->pdqdb_host_smt
);
1781 pdq
->pdq_host_smt_info
.rx_target
= pdq
->pdq_host_smt_info
.rx_free
- PDQ_RX_SEGCNT
* 3;
1782 pdq
->pdq_host_smt_info
.rx_pa_descriptors
= PDQ_DB_BUSPA(pdq
, dbp
->pdqdb_host_smt
);
1785 * Initialize the transmit information block.
1787 dbp
->pdqdb_tx_hdr
[0] = PDQ_FDDI_PH0
;
1788 dbp
->pdqdb_tx_hdr
[1] = PDQ_FDDI_PH1
;
1789 dbp
->pdqdb_tx_hdr
[2] = PDQ_FDDI_PH2
;
1790 pdq
->pdq_tx_info
.tx_free
= PDQ_RING_MASK(dbp
->pdqdb_transmits
);
1791 pdq
->pdq_tx_info
.tx_hdrdesc
.txd_pa_hi
= htole32(PDQ_TXDESC_SOP
|PDQ_TXDESC_SEG_LEN(3));
1792 pdq
->pdq_tx_info
.tx_hdrdesc
.txd_pa_lo
= htole32(PDQ_DB_BUSPA(pdq
, dbp
->pdqdb_tx_hdr
));
1793 pdq
->pdq_tx_info
.tx_pa_descriptors
= PDQ_DB_BUSPA(pdq
, dbp
->pdqdb_transmits
);
1795 state
= PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_port_status
));
1796 PDQ_PRINTF(("PDQ Adapter State = %s\n", pdq_adapter_states
[state
]));
1799 * Stop the PDQ if it is running and put it into a known state.
1801 state
= pdq_stop(pdq
);
1803 PDQ_PRINTF(("PDQ Adapter State = %s\n", pdq_adapter_states
[state
]));
1804 PDQ_ASSERT(state
== PDQS_DMA_AVAILABLE
);
1806 * If the adapter is not the state we expect, then the initialization
1807 * failed. Cleanup and exit.
1809 #if defined(PDQVERBOSE)
1810 if (state
== PDQS_HALTED
) {
1811 pdq_halt_code_t halt_code
= PDQ_PSTS_HALT_ID(PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_port_status
));
1812 printf("Halt code = %d (%s)\n", halt_code
, pdq_halt_codes
[halt_code
]);
1813 if (halt_code
== PDQH_DMA_ERROR
&& pdq
->pdq_type
== PDQ_DEFPA
)
1814 PDQ_PRINTF(("PFI status = 0x%x, Host 0 Fatal Interrupt = 0x%x\n",
1815 PDQ_CSR_READ(&pdq
->pdq_pci_csrs
, csr_pfi_status
),
1816 PDQ_CSR_READ(&pdq
->pdq_csrs
, csr_host_int_type_0
) & PDQ_HOST_INT_FATAL_ERROR
));
1819 if (state
== PDQS_RESET
|| state
== PDQS_HALTED
|| state
== PDQS_UPGRADE
)
1820 goto cleanup_and_return
;
1822 PDQ_PRINTF(("PDQ Hardware Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
1823 pdq
->pdq_hwaddr
.lanaddr_bytes
[0], pdq
->pdq_hwaddr
.lanaddr_bytes
[1],
1824 pdq
->pdq_hwaddr
.lanaddr_bytes
[2], pdq
->pdq_hwaddr
.lanaddr_bytes
[3],
1825 pdq
->pdq_hwaddr
.lanaddr_bytes
[4], pdq
->pdq_hwaddr
.lanaddr_bytes
[5]));
1826 PDQ_PRINTF(("PDQ Firmware Revision = %c%c%c%c\n",
1827 pdq
->pdq_fwrev
.fwrev_bytes
[0], pdq
->pdq_fwrev
.fwrev_bytes
[1],
1828 pdq
->pdq_fwrev
.fwrev_bytes
[2], pdq
->pdq_fwrev
.fwrev_bytes
[3]));
1829 PDQ_PRINTF(("PDQ Chip Revision = "));
1830 switch (pdq
->pdq_chip_rev
) {
1831 case PDQ_CHIP_REV_A_B_OR_C
: PDQ_PRINTF(("Rev C or below")); break;
1832 case PDQ_CHIP_REV_D
: PDQ_PRINTF(("Rev D")); break;
1833 case PDQ_CHIP_REV_E
: PDQ_PRINTF(("Rev E")); break;
1834 default: PDQ_PRINTF(("Unknown Rev %d", (int) pdq
->pdq_chip_rev
));