This source file includes following definitions.
- pdq_print_fddi_chars
- pdq_init_csrs
- pdq_init_pci_csrs
- pdq_flush_databuf_queue
- pdq_do_port_control
- pdq_read_mla
- pdq_read_fwrev
- pdq_read_error_log
- pdq_read_chiprev
- pdq_queue_commands
- pdq_process_command_responses
- pdq_process_unsolicited_events
- pdq_process_received_data
- pdq_queue_transmit_data
- pdq_process_transmitted_data
- pdq_flush_transmitter
- pdq_hwreset
- pdq_stop
- pdq_run
- pdq_interrupt
- pdq_initialize
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #define PDQ_HWSUPPORT
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
70
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
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
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
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
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
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
280 PDQ_ASSERT(0);
281 return PDQ_FALSE;
282 }
283
284 static void
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
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
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
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),
361 sizeof(pdq_response_generic_t),
362 "Start"
363 },
364 { sizeof(pdq_cmd_filter_set_t),
365 sizeof(pdq_response_generic_t),
366 "Filter Set"
367 },
368 { sizeof(pdq_cmd_generic_t),
369 sizeof(pdq_response_filter_get_t),
370 "Filter Get"
371 },
372 { sizeof(pdq_cmd_chars_set_t),
373 sizeof(pdq_response_generic_t),
374 "Chars Set"
375 },
376 { sizeof(pdq_cmd_generic_t),
377 sizeof(pdq_response_status_chars_get_t),
378 "Status Chars Get"
379 },
380 #if 0
381 { sizeof(pdq_cmd_generic_t),
382 sizeof(pdq_response_counters_get_t),
383 "Counters Get"
384 },
385 { sizeof(pdq_cmd_counters_set_t),
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),
394 sizeof(pdq_response_generic_t),
395 "Addr Filter Set"
396 },
397 { sizeof(pdq_cmd_generic_t),
398 sizeof(pdq_response_addr_filter_get_t),
399 "Addr Filter Get"
400 },
401 #if 0
402 { sizeof(pdq_cmd_generic_t),
403 sizeof(pdq_response_generic_t),
404 "Error Log Clear"
405 },
406 { sizeof(pdq_cmd_generic_t),
407 sizeof(pdq_response_generic_t),
408 "Error Log Set"
409 },
410 { sizeof(pdq_cmd_generic_t),
411 sizeof(pdq_response_generic_t),
412 "FDDI MIB Get"
413 },
414 { sizeof(pdq_cmd_generic_t),
415 sizeof(pdq_response_generic_t),
416 "DEC Ext MIB Get"
417 },
418 { sizeof(pdq_cmd_generic_t),
419 sizeof(pdq_response_generic_t),
420 "DEC Specific Get"
421 },
422 { sizeof(pdq_cmd_generic_t),
423 sizeof(pdq_response_generic_t),
424 "SNMP Set"
425 },
426 { 0, 0, "N/A" },
427 { sizeof(pdq_cmd_generic_t),
428 sizeof(pdq_response_generic_t),
429 "SMT MIB Get"
430 },
431 { sizeof(pdq_cmd_generic_t),
432 sizeof(pdq_response_generic_t),
433 "SMT MIB Set",
434 },
435 #endif
436 };
437
438 static void
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
450
451
452 if (ci->ci_command_active || ci->ci_pending_commands == 0)
453 return;
454
455
456
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
463
464
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
472
473
474
475
476
477
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
484
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
491
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
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
538
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
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
560
561
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
596
597
598
599
600 static void
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
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
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
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
699
700
701 pdulen = datalen - 4 ;
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
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
756 } else if (status.rxs_fsc == 0 || status.rxs_fsb_e == 1) {
757
758 } else {
759
760 }
761 }
762 discard_frame:
763
764
765
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
790
791
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
813
814
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
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
847
848
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
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
874
875
876
877 return PDQ_FALSE;
878 }
879
880
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
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
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
932
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
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
974
975
976 pdq_state_t
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
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
1011 }
1012 case PDQS_DMA_UNAVAILABLE: {
1013 break;
1014 }
1015 }
1016 #endif
1017
1018
1019
1020
1021
1022
1023
1024
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
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
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
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
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
1092
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_PDQ_PCI_INTR);
1102 #endif
1103 }
1104
1105
1106
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)
1144
1145 ;
1146
1147
1148
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
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
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
1188
1189
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
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
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 *
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
1367
1368
1369
1370
1371
1372
1373
1374
1375
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
1382
1383
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
1406
1407
1408 if (pdq->pdq_dbp == NULL || pdq->pdq_unsolicited_info.ui_events == NULL) {
1409 cleanup_and_return:
1410 if (p != NULL)
1411 PDQ_OS_MEMFREE_CONTIG(p , 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
1435
1436
1437
1438
1439 PDQ_OS_MEMZERO(pdq->pdq_dbp, sizeof(*pdq->pdq_dbp));
1440
1441
1442
1443
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
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
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
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
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
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
1545
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 }