1 // SPDX-License-Identifier: GPL-2.0+
3 * NC-SI protocol configuration
5 * Copyright (C) 2019, IBM Corporation.
14 #include <net/ncsi-pkt.h>
15 #include <asm/unaligned.h>
17 #define NCSI_PACKAGE_MAX 8
18 #define NCSI_CHANNEL_MAX 31
20 #define NCSI_PACKAGE_SHIFT 5
21 #define NCSI_PACKAGE_INDEX(c) (((c) >> NCSI_PACKAGE_SHIFT) & 0x7)
22 #define NCSI_RESERVED_CHANNEL 0x1f
23 #define NCSI_CHANNEL_INDEX(c) ((c) & ((1 << NCSI_PACKAGE_SHIFT) - 1))
24 #define NCSI_TO_CHANNEL(p, c) (((p) << NCSI_PACKAGE_SHIFT) | (c))
26 #define NCSI_PKT_REVISION 0x01
28 #define NCSI_CAP_GENERIC_MASK 0x7f
29 #define NCSI_CAP_BC_MASK 0x0f
30 #define NCSI_CAP_MC_MASK 0x3f
31 #define NCSI_CAP_AEN_MASK 0x07
32 #define NCSI_CAP_VLAN_MASK 0x07
34 static void ncsi_send_ebf(unsigned int np, unsigned int nc);
35 static void ncsi_send_ae(unsigned int np, unsigned int nc);
36 static void ncsi_send_gls(unsigned int np, unsigned int nc);
37 static int ncsi_send_command(unsigned int np, unsigned int nc, unsigned int cmd,
38 uchar *payload, int len, bool wait);
52 /* version information */
54 u32 version; /* Supported BCD encoded NCSI version */
55 u32 alpha2; /* Supported BCD encoded NCSI version */
56 u8 fw_name[12]; /* Firmware name string */
57 u32 fw_version; /* Firmware version */
58 u16 pci_ids[4]; /* PCI identification */
59 u32 mf_id; /* Manufacture ID */
66 unsigned int n_channels;
67 struct ncsi_channel *channels;
72 NCSI_PROBE_PACKAGE_SP,
73 NCSI_PROBE_PACKAGE_DP,
74 NCSI_PROBE_CHANNEL_SP,
79 unsigned int pending_requests;
80 unsigned int requests[256];
81 unsigned int last_request;
83 unsigned int current_package;
84 unsigned int current_channel;
86 unsigned int n_packages;
87 struct ncsi_package *packages;
90 struct ncsi *ncsi_priv;
92 bool ncsi_active(void)
99 np = ncsi_priv->current_package;
100 nc = ncsi_priv->current_channel;
102 if (ncsi_priv->state != NCSI_CONFIG)
105 return np < NCSI_PACKAGE_MAX && nc < NCSI_CHANNEL_MAX &&
106 ncsi_priv->packages[np].channels[nc].has_link;
109 static unsigned int cmd_payload(int cmd)
112 case NCSI_PKT_CMD_CIS:
114 case NCSI_PKT_CMD_SP:
116 case NCSI_PKT_CMD_DP:
118 case NCSI_PKT_CMD_EC:
120 case NCSI_PKT_CMD_DC:
122 case NCSI_PKT_CMD_RC:
124 case NCSI_PKT_CMD_ECNT:
126 case NCSI_PKT_CMD_DCNT:
128 case NCSI_PKT_CMD_AE:
130 case NCSI_PKT_CMD_SL:
132 case NCSI_PKT_CMD_GLS:
134 case NCSI_PKT_CMD_SVF:
136 case NCSI_PKT_CMD_EV:
138 case NCSI_PKT_CMD_DV:
140 case NCSI_PKT_CMD_SMA:
142 case NCSI_PKT_CMD_EBF:
144 case NCSI_PKT_CMD_DBF:
146 case NCSI_PKT_CMD_EGMF:
148 case NCSI_PKT_CMD_DGMF:
150 case NCSI_PKT_CMD_SNFC:
152 case NCSI_PKT_CMD_GVI:
154 case NCSI_PKT_CMD_GC:
156 case NCSI_PKT_CMD_GP:
158 case NCSI_PKT_CMD_GCPS:
160 case NCSI_PKT_CMD_GNS:
162 case NCSI_PKT_CMD_GNPTS:
164 case NCSI_PKT_CMD_GPS:
167 printf("NCSI: Unknown command 0x%02x\n", cmd);
172 static u32 ncsi_calculate_checksum(unsigned char *data, int len)
177 for (i = 0; i < len; i += 2)
178 checksum += (((u32)data[i] << 8) | data[i + 1]);
180 checksum = (~checksum + 1);
184 static int ncsi_validate_rsp(struct ncsi_rsp_pkt *pkt, int payload)
186 struct ncsi_rsp_pkt_hdr *hdr = &pkt->rsp;
187 u32 checksum, c_offset;
190 if (hdr->common.revision != 1) {
191 printf("NCSI: 0x%02x response has unsupported revision 0x%x\n",
192 hdr->common.type, hdr->common.revision);
196 if (hdr->code != 0) {
197 printf("NCSI: 0x%02x response returns error %d\n",
198 hdr->common.type, __be16_to_cpu(hdr->code));
199 if (ntohs(hdr->reason) == 0x05)
200 printf("(Invalid command length)\n");
204 if (ntohs(hdr->common.length) != payload) {
205 printf("NCSI: 0x%02x response has incorrect length %d\n",
206 hdr->common.type, hdr->common.length);
210 c_offset = sizeof(struct ncsi_rsp_pkt_hdr) + payload - sizeof(checksum);
211 pchecksum = get_unaligned_be32((void *)hdr + c_offset);
212 if (pchecksum != 0) {
213 checksum = ncsi_calculate_checksum((unsigned char *)hdr,
215 if (pchecksum != checksum) {
216 printf("NCSI: 0x%02x response has invalid checksum\n",
225 static void ncsi_rsp_ec(struct ncsi_rsp_pkt *pkt)
227 struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&pkt->rsp;
230 np = NCSI_PACKAGE_INDEX(rsp->common.channel);
231 nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
233 if (ncsi_priv->packages[np].channels[nc].cap_aen != 0)
234 ncsi_send_ae(np, nc);
238 static void ncsi_rsp_ecnt(struct ncsi_rsp_pkt *pkt)
240 struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&pkt->rsp;
243 np = NCSI_PACKAGE_INDEX(rsp->common.channel);
244 nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
246 ncsi_send_command(np, nc, NCSI_PKT_CMD_EC, NULL, 0, true);
249 static void ncsi_rsp_ebf(struct ncsi_rsp_pkt *pkt)
251 struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&pkt->rsp;
254 np = NCSI_PACKAGE_INDEX(rsp->common.channel);
255 nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
257 ncsi_send_command(np, nc, NCSI_PKT_CMD_ECNT, NULL, 0, true);
260 static void ncsi_rsp_sma(struct ncsi_rsp_pkt *pkt)
262 struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&pkt->rsp;
265 np = NCSI_PACKAGE_INDEX(rsp->common.channel);
266 nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
268 ncsi_send_ebf(np, nc);
271 static void ncsi_rsp_gc(struct ncsi_rsp_pkt *pkt)
273 struct ncsi_rsp_gc_pkt *gc = (struct ncsi_rsp_gc_pkt *)pkt;
274 struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&gc->rsp;
275 struct ncsi_channel *c;
278 np = NCSI_PACKAGE_INDEX(rsp->common.channel);
279 nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
281 if (np >= ncsi_priv->n_packages ||
282 nc >= ncsi_priv->packages[np].n_channels) {
283 printf("NCSI: Invalid package / channel (0x%02x, 0x%02x)\n",
288 c = &ncsi_priv->packages[np].channels[nc];
289 c->cap_generic = get_unaligned_be32(&gc->cap) & NCSI_CAP_GENERIC_MASK;
290 c->cap_bc = get_unaligned_be32(&gc->bc_cap) & NCSI_CAP_BC_MASK;
291 c->cap_mc = get_unaligned_be32(&gc->mc_cap) & NCSI_CAP_MC_MASK;
292 c->cap_aen = get_unaligned_be32(&gc->aen_cap) & NCSI_CAP_AEN_MASK;
293 c->cap_vlan = gc->vlan_mode & NCSI_CAP_VLAN_MASK;
295 /* End of probe for this channel */
298 static void ncsi_rsp_gvi(struct ncsi_rsp_pkt *pkt)
300 struct ncsi_rsp_gvi_pkt *gvi = (struct ncsi_rsp_gvi_pkt *)pkt;
301 struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&gvi->rsp;
302 struct ncsi_channel *c;
303 unsigned int np, nc, i;
305 np = NCSI_PACKAGE_INDEX(rsp->common.channel);
306 nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
308 if (np >= ncsi_priv->n_packages ||
309 nc >= ncsi_priv->packages[np].n_channels) {
310 printf("NCSI: Invalid package / channel (0x%02x, 0x%02x)\n",
315 c = &ncsi_priv->packages[np].channels[nc];
316 c->version.version = get_unaligned_be32(&gvi->ncsi_version);
317 c->version.alpha2 = gvi->alpha2;
318 memcpy(c->version.fw_name, gvi->fw_name, sizeof(c->version.fw_name));
319 c->version.fw_version = get_unaligned_be32(&gvi->fw_version);
320 for (i = 0; i < ARRAY_SIZE(c->version.pci_ids); i++)
321 c->version.pci_ids[i] = get_unaligned_be16(gvi->pci_ids + i);
322 c->version.mf_id = get_unaligned_be32(&gvi->mf_id);
324 if (ncsi_priv->state == NCSI_PROBE_CHANNEL)
325 ncsi_send_command(np, nc, NCSI_PKT_CMD_GC, NULL, 0, true);
328 static void ncsi_rsp_gls(struct ncsi_rsp_pkt *pkt)
330 struct ncsi_rsp_gls_pkt *gls = (struct ncsi_rsp_gls_pkt *)pkt;
331 struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&gls->rsp;
334 np = NCSI_PACKAGE_INDEX(rsp->common.channel);
335 nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
337 if (np >= ncsi_priv->n_packages ||
338 nc >= ncsi_priv->packages[np].n_channels) {
339 printf("NCSI: Invalid package / channel (0x%02x, 0x%02x)\n",
344 ncsi_priv->packages[np].channels[nc].has_link =
345 !!(get_unaligned_be32(&gls->status));
347 if (ncsi_priv->state == NCSI_PROBE_CHANNEL)
348 ncsi_send_command(np, nc, NCSI_PKT_CMD_GVI, NULL, 0, true);
351 static void ncsi_rsp_cis(struct ncsi_rsp_pkt *pkt)
353 struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)pkt;
354 struct ncsi_package *package;
357 np = NCSI_PACKAGE_INDEX(rsp->common.channel);
358 nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
360 if (np >= ncsi_priv->n_packages) {
361 printf("NCSI: Mystery package 0x%02x from CIS\n", np);
365 package = &ncsi_priv->packages[np];
367 if (nc < package->n_channels) {
369 * This is fine in general but in the current design we
370 * don't send CIS commands to known channels.
372 debug("NCSI: Duplicate channel 0x%02x\n", nc);
376 package->channels = realloc(package->channels,
377 sizeof(struct ncsi_channel) *
378 (package->n_channels + 1));
379 if (!package->channels) {
380 printf("NCSI: Could not allocate memory for new channel\n");
384 debug("NCSI: New channel 0x%02x\n", nc);
386 package->channels[nc].id = nc;
387 package->channels[nc].has_link = false;
388 package->n_channels++;
390 ncsi_send_gls(np, nc);
393 static void ncsi_rsp_dp(struct ncsi_rsp_pkt *pkt)
395 struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)pkt;
398 /* No action needed */
400 np = NCSI_PACKAGE_INDEX(rsp->common.channel);
401 if (np >= ncsi_priv->n_packages)
402 debug("NCSI: DP response from unknown package %d\n", np);
405 static void ncsi_rsp_sp(struct ncsi_rsp_pkt *pkt)
407 struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)pkt;
410 np = NCSI_PACKAGE_INDEX(rsp->common.channel);
412 if (np < ncsi_priv->n_packages) {
413 /* Already know about this package */
414 debug("NCSI: package 0x%02x selected\n", np);
418 debug("NCSI: adding new package %d\n", np);
420 ncsi_priv->packages = realloc(ncsi_priv->packages,
421 sizeof(struct ncsi_package) *
422 (ncsi_priv->n_packages + 1));
423 if (!ncsi_priv->packages) {
424 printf("NCSI: could not allocate memory for new package\n");
428 ncsi_priv->packages[np].id = np;
429 ncsi_priv->packages[np].n_channels = 0;
430 ncsi_priv->packages[np].channels = NULL;
431 ncsi_priv->n_packages++;
434 static void ncsi_update_state(struct ncsi_rsp_pkt_hdr *nh)
439 switch (ncsi_priv->state) {
440 case NCSI_PROBE_PACKAGE_SP:
442 ncsi_priv->current_package + 1 < NCSI_PACKAGE_MAX) {
443 ncsi_priv->current_package++;
445 ncsi_priv->state = NCSI_PROBE_PACKAGE_DP;
446 ncsi_priv->current_package = 0;
448 return ncsi_probe_packages();
449 case NCSI_PROBE_PACKAGE_DP:
450 if (ncsi_priv->current_package + 1 < ncsi_priv->n_packages &&
452 ncsi_priv->current_package++;
454 if (!ncsi_priv->n_packages) {
455 printf("NCSI: no packages found\n");
456 net_set_state(NETLOOP_FAIL);
459 printf("NCSI: probing channels\n");
460 ncsi_priv->state = NCSI_PROBE_CHANNEL_SP;
461 ncsi_priv->current_package = 0;
462 ncsi_priv->current_channel = 0;
464 return ncsi_probe_packages();
465 case NCSI_PROBE_CHANNEL_SP:
466 if (!timeout && nh->common.type == NCSI_PKT_RSP_SP) {
467 ncsi_priv->state = NCSI_PROBE_CHANNEL;
468 return ncsi_probe_packages();
470 printf("NCSI: failed to select package 0x%0x2 or timeout\n",
471 ncsi_priv->current_package);
472 net_set_state(NETLOOP_FAIL);
474 case NCSI_PROBE_CHANNEL:
475 // TODO only does package 0 for now
476 if (ncsi_priv->pending_requests == 0) {
477 np = ncsi_priv->current_package;
478 nc = ncsi_priv->current_channel;
480 /* Configure first channel that has link */
481 if (ncsi_priv->packages[np].channels[nc].has_link) {
482 ncsi_priv->state = NCSI_CONFIG;
483 } else if (ncsi_priv->current_channel + 1 <
485 ncsi_priv->current_channel++;
487 // XXX As above only package 0
488 printf("NCSI: no channel found with link\n");
489 net_set_state(NETLOOP_FAIL);
492 return ncsi_probe_packages();
496 if (ncsi_priv->pending_requests == 0) {
497 printf("NCSI: configuration done!\n");
498 net_set_state(NETLOOP_SUCCESS);
499 } else if (timeout) {
500 printf("NCSI: timeout during configure\n");
501 net_set_state(NETLOOP_FAIL);
505 printf("NCSI: something went very wrong, nevermind\n");
506 net_set_state(NETLOOP_FAIL);
511 static void ncsi_timeout_handler(void)
513 if (ncsi_priv->pending_requests)
514 ncsi_priv->pending_requests--;
516 ncsi_update_state(NULL);
519 static int ncsi_send_command(unsigned int np, unsigned int nc, unsigned int cmd,
520 uchar *payload, int len, bool wait)
522 struct ncsi_pkt_hdr *hdr;
529 pkt = calloc(1, PKTSIZE_ALIGN + PKTALIGN);
534 eth_hdr_size = net_set_ether(pkt, net_bcast_ethaddr, PROT_NCSI);
537 /* Set NCSI command header fields */
538 hdr = (struct ncsi_pkt_hdr *)pkt;
540 hdr->revision = NCSI_PKT_REVISION;
541 hdr->id = ++ncsi_priv->last_request;
542 ncsi_priv->requests[ncsi_priv->last_request] = 1;
544 hdr->channel = NCSI_TO_CHANNEL(np, nc);
545 hdr->length = htons(len);
548 memcpy(pkt + sizeof(struct ncsi_pkt_hdr), payload, len);
550 /* Calculate checksum */
551 checksum = ncsi_calculate_checksum((unsigned char *)hdr,
553 pchecksum = (__be32 *)((void *)(hdr + 1) + len);
554 put_unaligned_be32(checksum, pchecksum);
557 net_set_timeout_handler(1000UL, ncsi_timeout_handler);
558 ncsi_priv->pending_requests++;
563 /* frame header, packet header, payload, checksum */
564 final_len = eth_hdr_size + sizeof(struct ncsi_cmd_pkt_hdr) + len + 4;
566 net_send_packet(start, final_len);
571 static void ncsi_handle_aen(struct ip_udp_hdr *ip, unsigned int len)
573 struct ncsi_aen_pkt_hdr *hdr = (struct ncsi_aen_pkt_hdr *)ip;
579 case NCSI_PKT_AEN_LSC:
580 printf("NCSI: link state changed\n");
583 case NCSI_PKT_AEN_CR:
584 printf("NCSI: re-configuration required\n");
587 case NCSI_PKT_AEN_HNCDSC:
588 /* Host notifcation - N/A but weird */
589 debug("NCSI: HNCDSC AEN received\n");
592 printf("%s: Invalid type 0x%02x\n", __func__, hdr->type);
596 /* Validate packet */
597 if (hdr->common.revision != 1) {
598 printf("NCSI: 0x%02x response has unsupported revision 0x%x\n",
599 hdr->common.type, hdr->common.revision);
603 if (ntohs(hdr->common.length) != payload) {
604 printf("NCSI: 0x%02x response has incorrect length %d\n",
605 hdr->common.type, hdr->common.length);
609 pchecksum = get_unaligned_be32((void *)(hdr + 1) + payload - 4);
610 if (pchecksum != 0) {
611 checksum = ncsi_calculate_checksum((unsigned char *)hdr,
612 sizeof(*hdr) + payload - 4);
613 if (pchecksum != checksum) {
614 printf("NCSI: 0x%02x response has invalid checksum\n",
620 /* Link or configuration lost - just redo the discovery process */
621 ncsi_priv->state = NCSI_PROBE_PACKAGE_SP;
622 for (i = 0; i < ncsi_priv->n_packages; i++) {
623 free(ncsi_priv->packages[i].channels);
624 ncsi_priv->packages[i].channels = NULL;
626 free(ncsi_priv->packages);
627 ncsi_priv->packages = NULL;
628 ncsi_priv->n_packages = 0;
630 ncsi_priv->current_package = NCSI_PACKAGE_MAX;
631 ncsi_priv->current_channel = NCSI_CHANNEL_MAX;
633 ncsi_probe_packages();
636 void ncsi_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip,
639 struct ncsi_rsp_pkt *pkt = (struct ncsi_rsp_pkt *)ip;
640 struct ncsi_rsp_pkt_hdr *nh = (struct ncsi_rsp_pkt_hdr *)&pkt->rsp;
641 void (*handler)(struct ncsi_rsp_pkt *pkt) = NULL;
642 unsigned short payload;
644 if (ncsi_priv->pending_requests)
645 ncsi_priv->pending_requests--;
647 if (len < sizeof(struct ncsi_rsp_pkt_hdr)) {
648 printf("NCSI: undersized packet: %u bytes\n", len);
652 if (nh->common.type == NCSI_PKT_AEN)
653 return ncsi_handle_aen(ip, len);
655 switch (nh->common.type) {
656 case NCSI_PKT_RSP_SP:
658 handler = ncsi_rsp_sp;
660 case NCSI_PKT_RSP_DP:
662 handler = ncsi_rsp_dp;
664 case NCSI_PKT_RSP_CIS:
666 handler = ncsi_rsp_cis;
668 case NCSI_PKT_RSP_GLS:
670 handler = ncsi_rsp_gls;
672 case NCSI_PKT_RSP_GVI:
674 handler = ncsi_rsp_gvi;
676 case NCSI_PKT_RSP_GC:
678 handler = ncsi_rsp_gc;
680 case NCSI_PKT_RSP_SMA:
682 handler = ncsi_rsp_sma;
684 case NCSI_PKT_RSP_EBF:
686 handler = ncsi_rsp_ebf;
688 case NCSI_PKT_RSP_ECNT:
690 handler = ncsi_rsp_ecnt;
692 case NCSI_PKT_RSP_EC:
694 handler = ncsi_rsp_ec;
696 case NCSI_PKT_RSP_AE:
701 printf("NCSI: unsupported packet type 0x%02x\n",
706 if (ncsi_validate_rsp(pkt, payload) != 0) {
707 printf("NCSI: discarding invalid packet of type 0x%02x\n",
715 ncsi_update_state(nh);
718 static void ncsi_send_sp(unsigned int np)
720 uchar payload[4] = {0};
722 ncsi_send_command(np, NCSI_RESERVED_CHANNEL, NCSI_PKT_CMD_SP,
723 (unsigned char *)&payload,
724 cmd_payload(NCSI_PKT_CMD_SP), true);
727 static void ncsi_send_dp(unsigned int np)
729 ncsi_send_command(np, NCSI_RESERVED_CHANNEL, NCSI_PKT_CMD_DP, NULL, 0,
733 static void ncsi_send_gls(unsigned int np, unsigned int nc)
735 ncsi_send_command(np, nc, NCSI_PKT_CMD_GLS, NULL, 0, true);
738 static void ncsi_send_cis(unsigned int np, unsigned int nc)
740 ncsi_send_command(np, nc, NCSI_PKT_CMD_CIS, NULL, 0, true);
743 static void ncsi_send_ae(unsigned int np, unsigned int nc)
745 struct ncsi_cmd_ae_pkt cmd;
747 memset(&cmd, 0, sizeof(cmd));
748 cmd.mode = htonl(ncsi_priv->packages[np].channels[nc].cap_aen);
750 ncsi_send_command(np, nc, NCSI_PKT_CMD_AE,
751 ((unsigned char *)&cmd)
752 + sizeof(struct ncsi_cmd_pkt_hdr),
753 cmd_payload(NCSI_PKT_CMD_AE), true);
756 static void ncsi_send_ebf(unsigned int np, unsigned int nc)
758 struct ncsi_cmd_ebf_pkt cmd;
760 memset(&cmd, 0, sizeof(cmd));
761 cmd.mode = htonl(ncsi_priv->packages[np].channels[nc].cap_bc);
763 ncsi_send_command(np, nc, NCSI_PKT_CMD_EBF,
764 ((unsigned char *)&cmd)
765 + sizeof(struct ncsi_cmd_pkt_hdr),
766 cmd_payload(NCSI_PKT_CMD_EBF), true);
769 static void ncsi_send_sma(unsigned int np, unsigned int nc)
771 struct ncsi_cmd_sma_pkt cmd;
772 unsigned char *addr, i;
774 addr = eth_get_ethaddr();
776 printf("NCSI: no MAC address configured\n");
780 memset(&cmd, 0, sizeof(cmd));
781 for (i = 0; i < ARP_HLEN; i++)
782 cmd.mac[i] = addr[i];
786 ncsi_send_command(np, nc, NCSI_PKT_CMD_SMA,
787 ((unsigned char *)&cmd)
788 + sizeof(struct ncsi_cmd_pkt_hdr),
789 cmd_payload(NCSI_PKT_CMD_SMA), true);
792 void ncsi_probe_packages(void)
794 struct ncsi_package *package;
797 switch (ncsi_priv->state) {
798 case NCSI_PROBE_PACKAGE_SP:
799 if (ncsi_priv->current_package == NCSI_PACKAGE_MAX)
800 ncsi_priv->current_package = 0;
801 ncsi_send_sp(ncsi_priv->current_package);
803 case NCSI_PROBE_PACKAGE_DP:
804 ncsi_send_dp(ncsi_priv->current_package);
806 case NCSI_PROBE_CHANNEL_SP:
807 if (ncsi_priv->n_packages > 0)
808 ncsi_send_sp(ncsi_priv->current_package);
810 printf("NCSI: no packages discovered, configuration not possible\n");
812 case NCSI_PROBE_CHANNEL:
813 /* Kicks off chain of channel discovery */
814 ncsi_send_cis(ncsi_priv->current_package,
815 ncsi_priv->current_channel);
818 for (np = 0; np < ncsi_priv->n_packages; np++) {
819 package = &ncsi_priv->packages[np];
820 for (nc = 0; nc < package->n_channels; nc++)
821 if (package->channels[nc].has_link)
823 if (nc < package->n_channels)
826 if (np == ncsi_priv->n_packages) {
827 printf("NCSI: no link available\n");
831 printf("NCSI: configuring channel %d\n", nc);
832 ncsi_priv->current_package = np;
833 ncsi_priv->current_channel = nc;
834 /* Kicks off rest of configure chain */
835 ncsi_send_sma(np, nc);
838 printf("NCSI: unknown state 0x%x\n", ncsi_priv->state);
842 int ncsi_probe(struct phy_device *phydev)
845 phydev->priv = malloc(sizeof(struct ncsi));
848 memset(phydev->priv, 0, sizeof(struct ncsi));
851 ncsi_priv = phydev->priv;
856 int ncsi_startup(struct phy_device *phydev)
858 /* Set phydev parameters */
859 phydev->speed = SPEED_100;
860 phydev->duplex = DUPLEX_FULL;
861 /* Normal phy reset is N/A */
862 phydev->flags |= PHY_FLAG_BROKEN_RESET;
864 /* Set initial probe state */
865 ncsi_priv->state = NCSI_PROBE_PACKAGE_SP;
867 /* No active package/channel yet */
868 ncsi_priv->current_package = NCSI_PACKAGE_MAX;
869 ncsi_priv->current_channel = NCSI_CHANNEL_MAX;
871 /* Pretend link works so the MAC driver sets final bits up */
874 /* Set ncsi_priv so we can use it when called from net_loop() */
875 ncsi_priv = phydev->priv;
880 int ncsi_shutdown(struct phy_device *phydev)
882 printf("NCSI: Disabling package %d\n", ncsi_priv->current_package);
883 ncsi_send_dp(ncsi_priv->current_package);
887 U_BOOT_PHY_DRIVER(ncsi) = {
891 .features = PHY_100BT_FEATURES | PHY_DEFAULT_FEATURES |
892 SUPPORTED_100baseT_Full | SUPPORTED_MII,
894 .startup = ncsi_startup,
895 .shutdown = ncsi_shutdown,