xref: /openbmc/u-boot/drivers/net/phy/ncsi.c (revision c16019f2)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * NC-SI protocol configuration
4  *
5  * Copyright (C) 2019, IBM Corporation.
6  */
7 
8 #include <common.h>
9 #include <malloc.h>
10 #include <phy.h>
11 #include <net/ncsi.h>
12 #include <net/ncsi-pkt.h>
13 #include <asm/unaligned.h>
14 
15 #define NCSI_PACKAGE_MAX 8
16 #define NCSI_CHANNEL_MAX 31
17 
18 #define NCSI_PACKAGE_SHIFT      5
19 #define NCSI_PACKAGE_INDEX(c)   (((c) >> NCSI_PACKAGE_SHIFT) & 0x7)
20 #define NCSI_RESERVED_CHANNEL   0x1f
21 #define NCSI_CHANNEL_INDEX(c)   ((c) & ((1 << NCSI_PACKAGE_SHIFT) - 1))
22 #define NCSI_TO_CHANNEL(p, c)   (((p) << NCSI_PACKAGE_SHIFT) | (c))
23 
24 #define NCSI_PKT_REVISION       0x01
25 
26 #define NCSI_CAP_GENERIC_MASK	0x7f
27 #define NCSI_CAP_BC_MASK	0x0f
28 #define NCSI_CAP_MC_MASK	0x3f
29 #define NCSI_CAP_AEN_MASK	0x07
30 #define NCSI_CAP_VLAN_MASK	0x07
31 
32 static void ncsi_send_ebf(unsigned int np, unsigned int nc);
33 static void ncsi_send_ae(unsigned int np, unsigned int nc);
34 static void ncsi_send_gls(unsigned int np, unsigned int nc);
35 static int ncsi_send_command(unsigned int np, unsigned int nc, unsigned int cmd,
36 			     uchar *payload, int len, bool wait);
37 
38 struct ncsi_channel {
39 	unsigned int	id;
40 	bool		has_link;
41 
42 	/* capabilities */
43 	u32 cap_generic;
44 	u32 cap_bc;
45 	u32 cap_mc;
46 	u32 cap_buffer;
47 	u32 cap_aen;
48 	u32 cap_vlan;
49 
50 	/* version information */
51 	struct {
52 		u32 version;            /* Supported BCD encoded NCSI version */
53 		u32 alpha2;             /* Supported BCD encoded NCSI version */
54 		u8  fw_name[12];        /* Firmware name string               */
55 		u32 fw_version;         /* Firmware version                   */
56 		u16 pci_ids[4];         /* PCI identification                 */
57 		u32 mf_id;              /* Manufacture ID                     */
58 	} version;
59 
60 };
61 
62 struct ncsi_package {
63 	unsigned int		id;
64 	unsigned int		n_channels;
65 	struct ncsi_channel	*channels;
66 };
67 
68 struct ncsi {
69 	enum {
70 		NCSI_PROBE_PACKAGE_SP,
71 		NCSI_PROBE_PACKAGE_DP,
72 		NCSI_PROBE_CHANNEL_SP,
73 		NCSI_PROBE_CHANNEL,
74 		NCSI_CONFIG,
75 	} state;
76 
77 	unsigned int	pending_requests;
78 	unsigned int	requests[256];
79 	unsigned int	last_request;
80 
81 	unsigned int	current_package;
82 	unsigned int	current_channel;
83 
84 	unsigned int		n_packages;
85 	struct ncsi_package	*packages;
86 };
87 
88 struct ncsi *ncsi_priv;
89 
90 bool ncsi_active(void)
91 {
92 	unsigned int np, nc;
93 
94 	if (!ncsi_priv)
95 		return false;
96 
97 	np = ncsi_priv->current_package;
98 	nc = ncsi_priv->current_channel;
99 
100 	if (ncsi_priv->state != NCSI_CONFIG)
101 		return false;
102 
103 	return np < NCSI_PACKAGE_MAX && nc < NCSI_CHANNEL_MAX &&
104 		ncsi_priv->packages[np].channels[nc].has_link;
105 }
106 
107 static unsigned int cmd_payload(int cmd)
108 {
109 	switch (cmd) {
110 	case NCSI_PKT_CMD_CIS:
111 		return 0;
112 	case NCSI_PKT_CMD_SP:
113 		return 4;
114 	case NCSI_PKT_CMD_DP:
115 		return 0;
116 	case NCSI_PKT_CMD_EC:
117 		return 0;
118 	case NCSI_PKT_CMD_DC:
119 		return 4;
120 	case NCSI_PKT_CMD_RC:
121 		return 4;
122 	case NCSI_PKT_CMD_ECNT:
123 		return 0;
124 	case NCSI_PKT_CMD_DCNT:
125 		return 0;
126 	case NCSI_PKT_CMD_AE:
127 		return 8;
128 	case NCSI_PKT_CMD_SL:
129 		return 8;
130 	case NCSI_PKT_CMD_GLS:
131 		return 0;
132 	case NCSI_PKT_CMD_SVF:
133 		return 8;
134 	case NCSI_PKT_CMD_EV:
135 		return 4;
136 	case NCSI_PKT_CMD_DV:
137 		return 0;
138 	case NCSI_PKT_CMD_SMA:
139 		return 8;
140 	case NCSI_PKT_CMD_EBF:
141 		return 4;
142 	case NCSI_PKT_CMD_DBF:
143 		return 0;
144 	case NCSI_PKT_CMD_EGMF:
145 		return 4;
146 	case NCSI_PKT_CMD_DGMF:
147 		return 0;
148 	case NCSI_PKT_CMD_SNFC:
149 		return 4;
150 	case NCSI_PKT_CMD_GVI:
151 		return 0;
152 	case NCSI_PKT_CMD_GC:
153 		return 0;
154 	case NCSI_PKT_CMD_GP:
155 		return 0;
156 	case NCSI_PKT_CMD_GCPS:
157 		return 0;
158 	case NCSI_PKT_CMD_GNS:
159 		return 0;
160 	case NCSI_PKT_CMD_GNPTS:
161 		return 0;
162 	case NCSI_PKT_CMD_GPS:
163 		return 0;
164 	default:
165 		printf("NCSI: Unknown command 0x%02x\n", cmd);
166 		return 0;
167 	}
168 }
169 
170 static u32 ncsi_calculate_checksum(unsigned char *data, int len)
171 {
172 	u32 checksum = 0;
173 	int i;
174 
175 	for (i = 0; i < len; i += 2)
176 		checksum += (((u32)data[i] << 8) | data[i + 1]);
177 
178 	checksum = (~checksum + 1);
179 	return checksum;
180 }
181 
182 static int ncsi_validate_rsp(struct ncsi_rsp_pkt *pkt, int payload)
183 {
184 	struct ncsi_rsp_pkt_hdr *hdr = &pkt->rsp;
185 	u32 checksum, c_offset;
186 	__be32 pchecksum;
187 
188 	if (hdr->common.revision != 1) {
189 		printf("NCSI: 0x%02x response has unsupported revision 0x%x\n",
190 		       hdr->common.type, hdr->common.revision);
191 		return -1;
192 	}
193 
194 	if (hdr->code != 0) {
195 		printf("NCSI: 0x%02x response returns error %d\n",
196 		       hdr->common.type, __be16_to_cpu(hdr->code));
197 		if (ntohs(hdr->reason) == 0x05)
198 			printf("(Invalid command length)\n");
199 		return -1;
200 	}
201 
202 	if (ntohs(hdr->common.length) != payload) {
203 		printf("NCSI: 0x%02x response has incorrect length %d\n",
204 		       hdr->common.type, hdr->common.length);
205 		return -1;
206 	}
207 
208 	c_offset = sizeof(struct ncsi_rsp_pkt_hdr) + payload - sizeof(checksum);
209 	pchecksum = get_unaligned_be32((void *)hdr + c_offset);
210 	if (pchecksum != 0) {
211 		checksum = ncsi_calculate_checksum((unsigned char *)hdr,
212 						   c_offset);
213 		if (pchecksum != checksum) {
214 			printf("NCSI: 0x%02x response has invalid checksum\n",
215 			       hdr->common.type);
216 			return -1;
217 		}
218 	}
219 
220 	return 0;
221 }
222 
223 static void ncsi_rsp_ec(struct ncsi_rsp_pkt *pkt)
224 {
225 	struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&pkt->rsp;
226 	unsigned int np, nc;
227 
228 	np = NCSI_PACKAGE_INDEX(rsp->common.channel);
229 	nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
230 
231 	if (ncsi_priv->packages[np].channels[nc].cap_aen != 0)
232 		ncsi_send_ae(np, nc);
233 	/* else, done */
234 }
235 
236 static void ncsi_rsp_ecnt(struct ncsi_rsp_pkt *pkt)
237 {
238 	struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&pkt->rsp;
239 	unsigned int np, nc;
240 
241 	np = NCSI_PACKAGE_INDEX(rsp->common.channel);
242 	nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
243 
244 	ncsi_send_command(np, nc, NCSI_PKT_CMD_EC, NULL, 0, true);
245 }
246 
247 static void ncsi_rsp_ebf(struct ncsi_rsp_pkt *pkt)
248 {
249 	struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&pkt->rsp;
250 	unsigned int np, nc;
251 
252 	np = NCSI_PACKAGE_INDEX(rsp->common.channel);
253 	nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
254 
255 	ncsi_send_command(np, nc, NCSI_PKT_CMD_ECNT, NULL, 0, true);
256 }
257 
258 static void ncsi_rsp_sma(struct ncsi_rsp_pkt *pkt)
259 {
260 	struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&pkt->rsp;
261 	unsigned int np, nc;
262 
263 	np = NCSI_PACKAGE_INDEX(rsp->common.channel);
264 	nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
265 
266 	ncsi_send_ebf(np, nc);
267 }
268 
269 static void ncsi_rsp_gc(struct ncsi_rsp_pkt *pkt)
270 {
271 	struct ncsi_rsp_gc_pkt *gc = (struct ncsi_rsp_gc_pkt *)pkt;
272 	struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&gc->rsp;
273 	struct ncsi_channel *c;
274 	unsigned int np, nc;
275 
276 	np = NCSI_PACKAGE_INDEX(rsp->common.channel);
277 	nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
278 
279 	if (np >= ncsi_priv->n_packages ||
280 	    nc >= ncsi_priv->packages[np].n_channels) {
281 		printf("NCSI: Invalid package / channel (0x%02x, 0x%02x)\n",
282 		       np, nc);
283 		return;
284 	}
285 
286 	c = &ncsi_priv->packages[np].channels[nc];
287 	c->cap_generic = ntohl(gc->cap) & NCSI_CAP_GENERIC_MASK;
288 	c->cap_bc = ntohl(gc->bc_cap) & NCSI_CAP_BC_MASK;
289 	c->cap_mc = ntohl(gc->mc_cap) & NCSI_CAP_MC_MASK;
290 	c->cap_aen = ntohl(gc->aen_cap) & NCSI_CAP_AEN_MASK;
291 	c->cap_vlan = ntohl(gc->vlan_mode) & NCSI_CAP_VLAN_MASK;
292 
293 	/* End of probe for this channel */
294 }
295 
296 static void ncsi_rsp_gvi(struct ncsi_rsp_pkt *pkt)
297 {
298 	struct ncsi_rsp_gvi_pkt *gvi = (struct ncsi_rsp_gvi_pkt *)pkt;
299 	struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&gvi->rsp;
300 	struct ncsi_channel *c;
301 	unsigned int np, nc, i;
302 
303 	np = NCSI_PACKAGE_INDEX(rsp->common.channel);
304 	nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
305 
306 	if (np >= ncsi_priv->n_packages ||
307 	    nc >= ncsi_priv->packages[np].n_channels) {
308 		printf("NCSI: Invalid package / channel (0x%02x, 0x%02x)\n",
309 		       np, nc);
310 		return;
311 	}
312 
313 	c = &ncsi_priv->packages[np].channels[nc];
314 	c->version.version = get_unaligned_be32(&gvi->ncsi_version);
315 	c->version.alpha2 = gvi->alpha2;
316 	memcpy(c->version.fw_name, gvi->fw_name, sizeof(c->version.fw_name));
317 	c->version.fw_version = get_unaligned_be32(&gvi->fw_version);
318 	for (i = 0; i < ARRAY_SIZE(c->version.pci_ids); i++)
319 		c->version.pci_ids[i] = get_unaligned_be16(gvi->pci_ids + i);
320 	c->version.mf_id = get_unaligned_be32(&gvi->mf_id);
321 
322 	if (ncsi_priv->state == NCSI_PROBE_CHANNEL)
323 		ncsi_send_command(np, nc, NCSI_PKT_CMD_GC, NULL, 0, true);
324 }
325 
326 static void ncsi_rsp_gls(struct ncsi_rsp_pkt *pkt)
327 {
328 	struct ncsi_rsp_gls_pkt *gls = (struct ncsi_rsp_gls_pkt *)pkt;
329 	struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)&gls->rsp;
330 	unsigned int np, nc;
331 
332 	np = NCSI_PACKAGE_INDEX(rsp->common.channel);
333 	nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
334 
335 	if (np >= ncsi_priv->n_packages ||
336 	    nc >= ncsi_priv->packages[np].n_channels) {
337 		printf("NCSI: Invalid package / channel (0x%02x, 0x%02x)\n",
338 		       np, nc);
339 		return;
340 	}
341 
342 	ncsi_priv->packages[np].channels[nc].has_link =
343 					!!(get_unaligned_be32(&gls->status));
344 
345 	if (ncsi_priv->state == NCSI_PROBE_CHANNEL)
346 		ncsi_send_command(np, nc, NCSI_PKT_CMD_GVI, NULL, 0, true);
347 }
348 
349 static void ncsi_rsp_cis(struct ncsi_rsp_pkt *pkt)
350 {
351 	struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)pkt;
352 	struct ncsi_package *package;
353 	unsigned int np, nc;
354 
355 	np = NCSI_PACKAGE_INDEX(rsp->common.channel);
356 	nc = NCSI_CHANNEL_INDEX(rsp->common.channel);
357 
358 	if (np >= ncsi_priv->n_packages) {
359 		printf("NCSI: Mystery package 0x%02x from CIS\n", np);
360 		return;
361 	}
362 
363 	package = &ncsi_priv->packages[np];
364 
365 	if (nc < package->n_channels) {
366 		/*
367 		 * This is fine in general but in the current design we
368 		 * don't send CIS commands to known channels.
369 		 */
370 		debug("NCSI: Duplicate channel 0x%02x\n", nc);
371 		return;
372 	}
373 
374 	package->channels = realloc(package->channels,
375 				    sizeof(struct ncsi_channel) *
376 				    (package->n_channels + 1));
377 	if (!package->channels) {
378 		printf("NCSI: Could not allocate memory for new channel\n");
379 		return;
380 	}
381 
382 	debug("NCSI: New channel 0x%02x\n", nc);
383 
384 	package->channels[nc].id = nc;
385 	package->channels[nc].has_link = false;
386 	package->n_channels++;
387 
388 	ncsi_send_gls(np, nc);
389 }
390 
391 static void ncsi_rsp_dp(struct ncsi_rsp_pkt *pkt)
392 {
393 	struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)pkt;
394 	unsigned int np;
395 
396 	printf("%s\n", __func__);
397 
398 	/* No action needed */
399 
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);
403 }
404 
405 static void ncsi_rsp_sp(struct ncsi_rsp_pkt *pkt)
406 {
407 	struct ncsi_rsp_pkt_hdr *rsp = (struct ncsi_rsp_pkt_hdr *)pkt;
408 	unsigned int np;
409 
410 	printf("%s\n", __func__);
411 
412 	np = NCSI_PACKAGE_INDEX(rsp->common.channel);
413 
414 	if (np < ncsi_priv->n_packages) {
415 		/* Already know about this package */
416 		debug("NCSI: package 0x%02x selected\n", np);
417 		return;
418 	}
419 
420 	debug("NCSI: adding new package %d\n", np);
421 
422 	ncsi_priv->packages = realloc(ncsi_priv->packages,
423 				      sizeof(struct ncsi_package) *
424 				      (ncsi_priv->n_packages + 1));
425 	if (!ncsi_priv->packages) {
426 		printf("NCSI: could not allocate memory for new package\n");
427 		return;
428 	}
429 
430 	ncsi_priv->packages[np].id = np;
431 	ncsi_priv->packages[np].n_channels = 0;
432 	ncsi_priv->packages[np].channels = NULL;
433 	ncsi_priv->n_packages++;
434 }
435 
436 static void ncsi_update_state(struct ncsi_rsp_pkt_hdr *nh)
437 {
438 	bool timeout = !nh;
439 	int np, nc;
440 
441 	switch (ncsi_priv->state) {
442 	case NCSI_PROBE_PACKAGE_SP:
443 		if (!timeout &&
444 		    ncsi_priv->current_package + 1 < NCSI_PACKAGE_MAX) {
445 			ncsi_priv->current_package++;
446 		} else {
447 			ncsi_priv->state = NCSI_PROBE_PACKAGE_DP;
448 			ncsi_priv->current_package = 0;
449 		}
450 		return ncsi_probe_packages();
451 	case NCSI_PROBE_PACKAGE_DP:
452 		if (ncsi_priv->current_package + 1 < ncsi_priv->n_packages &&
453 		    !timeout) {
454 			ncsi_priv->current_package++;
455 		} else {
456 			if (!ncsi_priv->n_packages) {
457 				printf("NCSI: no packages found\n");
458 				net_set_state(NETLOOP_FAIL);
459 				return;
460 			}
461 			printf("NCSI: probing channels\n");
462 			ncsi_priv->state = NCSI_PROBE_CHANNEL_SP;
463 			ncsi_priv->current_package = 0;
464 			ncsi_priv->current_channel = 0;
465 		}
466 		return ncsi_probe_packages();
467 	case NCSI_PROBE_CHANNEL_SP:
468 		if (!timeout && nh->common.type == NCSI_PKT_RSP_SP) {
469 			ncsi_priv->state = NCSI_PROBE_CHANNEL;
470 			return ncsi_probe_packages();
471 		}
472 		printf("NCSI: failed to select package 0x%0x2 or timeout\n",
473 		       ncsi_priv->current_package);
474 		net_set_state(NETLOOP_FAIL);
475 		break;
476 	case NCSI_PROBE_CHANNEL:
477 		// TODO only does package 0 for now
478 		if (ncsi_priv->pending_requests == 0) {
479 			np = ncsi_priv->current_package;
480 			nc = ncsi_priv->current_channel;
481 
482 			/* Configure first channel that has link */
483 			if (ncsi_priv->packages[np].channels[nc].has_link) {
484 				ncsi_priv->state = NCSI_CONFIG;
485 			} else if (ncsi_priv->current_channel + 1 <
486 				   NCSI_CHANNEL_MAX) {
487 				ncsi_priv->current_channel++;
488 			} else {
489 				// XXX As above only package 0
490 				printf("NCSI: no channel found with link\n");
491 				net_set_state(NETLOOP_FAIL);
492 				return;
493 			}
494 			return ncsi_probe_packages();
495 		}
496 		break;
497 	case NCSI_CONFIG:
498 		if (ncsi_priv->pending_requests == 0) {
499 			printf("NCSI: configuration done!\n");
500 			net_set_state(NETLOOP_SUCCESS);
501 		} else if (timeout) {
502 			printf("NCSI: timeout during configure\n");
503 			net_set_state(NETLOOP_FAIL);
504 		}
505 		break;
506 	default:
507 		printf("NCSI: something went very wrong, nevermind\n");
508 		net_set_state(NETLOOP_FAIL);
509 		break;
510 	}
511 }
512 
513 static void ncsi_timeout_handler(void)
514 {
515 	if (ncsi_priv->pending_requests)
516 		ncsi_priv->pending_requests--;
517 
518 	ncsi_update_state(NULL);
519 }
520 
521 static int ncsi_send_command(unsigned int np, unsigned int nc, unsigned int cmd,
522 			     uchar *payload, int len, bool wait)
523 {
524 	struct ncsi_pkt_hdr *hdr;
525 	__be32 *pchecksum;
526 	int eth_hdr_size;
527 	u32 checksum;
528 	uchar *pkt, *start;
529 	int final_len;
530 
531 	pkt = calloc(1, PKTSIZE_ALIGN + PKTALIGN);
532 	if (!pkt)
533 		return -ENOMEM;
534 	start = pkt;
535 
536 	eth_hdr_size = net_set_ether(pkt, net_bcast_ethaddr, PROT_NCSI);
537 	pkt += eth_hdr_size;
538 
539 	/* Set NCSI command header fields */
540 	hdr = (struct ncsi_pkt_hdr *)pkt;
541 	hdr->mc_id = 0;
542 	hdr->revision = NCSI_PKT_REVISION;
543 	hdr->id = ++ncsi_priv->last_request;
544 	ncsi_priv->requests[ncsi_priv->last_request] = 1;
545 	hdr->type = cmd;
546 	hdr->channel = NCSI_TO_CHANNEL(np, nc);
547 	hdr->length = htons(len);
548 
549 	if (payload && len)
550 		memcpy(pkt + sizeof(struct ncsi_pkt_hdr), payload, len);
551 
552 	/* Calculate checksum */
553 	checksum = ncsi_calculate_checksum((unsigned char *)hdr,
554 					   sizeof(*hdr) + len);
555 	pchecksum = (__be32 *)((void *)(hdr + 1) + len);
556 	put_unaligned_be32(checksum, pchecksum);
557 
558 	if (wait) {
559 		net_set_timeout_handler(1000UL, ncsi_timeout_handler);
560 		ncsi_priv->pending_requests++;
561 	}
562 
563 	if (len < 26)
564 		len = 26;
565 	/* frame header, packet header, payload, checksum */
566 	final_len = eth_hdr_size + sizeof(struct ncsi_cmd_pkt_hdr) + len + 4;
567 
568 	net_send_packet(start, final_len);
569 	free(start);
570 	return 0;
571 }
572 
573 static void ncsi_handle_aen(struct ip_udp_hdr *ip, unsigned int len)
574 {
575 	struct ncsi_aen_pkt_hdr *hdr = (struct ncsi_aen_pkt_hdr *)ip;
576 	int payload, i;
577 	__be32 pchecksum;
578 	u32 checksum;
579 
580 	switch (hdr->type) {
581 	case NCSI_PKT_AEN_LSC:
582 		printf("NCSI: link state changed\n");
583 		payload = 12;
584 		break;
585 	case NCSI_PKT_AEN_CR:
586 		printf("NCSI: re-configuration required\n");
587 		payload = 4;
588 		break;
589 	case NCSI_PKT_AEN_HNCDSC:
590 		/* Host notifcation - N/A but weird */
591 		debug("NCSI: HNCDSC AEN received\n");
592 		return;
593 	default:
594 		printf("%s: Invalid type 0x%02x\n", __func__, hdr->type);
595 		return;
596 	}
597 
598 	/* Validate packet */
599 	if (hdr->common.revision != 1) {
600 		printf("NCSI: 0x%02x response has unsupported revision 0x%x\n",
601 		       hdr->common.type, hdr->common.revision);
602 		return;
603 	}
604 
605 	if (ntohs(hdr->common.length) != payload) {
606 		printf("NCSI: 0x%02x response has incorrect length %d\n",
607 		       hdr->common.type, hdr->common.length);
608 		return;
609 	}
610 
611 	pchecksum = get_unaligned_be32((void *)(hdr + 1) + payload - 4);
612 	if (pchecksum != 0) {
613 		checksum = ncsi_calculate_checksum((unsigned char *)hdr,
614 						   sizeof(*hdr) + payload - 4);
615 		if (pchecksum != checksum) {
616 			printf("NCSI: 0x%02x response has invalid checksum\n",
617 			       hdr->common.type);
618 			return;
619 		}
620 	}
621 
622 	/* Link or configuration lost - just redo the discovery process */
623 	ncsi_priv->state = NCSI_PROBE_PACKAGE_SP;
624 	for (i = 0; i < ncsi_priv->n_packages; i++)
625 		free(ncsi_priv->packages[i].channels);
626 	free(ncsi_priv->packages);
627 	ncsi_priv->n_packages = 0;
628 
629 	ncsi_priv->current_package = NCSI_PACKAGE_MAX;
630 	ncsi_priv->current_channel = NCSI_CHANNEL_MAX;
631 
632 	ncsi_probe_packages();
633 }
634 
635 void ncsi_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip,
636 		  unsigned int len)
637 {
638 	struct ncsi_rsp_pkt *pkt = (struct ncsi_rsp_pkt *)ip;
639 	struct ncsi_rsp_pkt_hdr *nh = (struct ncsi_rsp_pkt_hdr *)&pkt->rsp;
640 	void (*handler)(struct ncsi_rsp_pkt *pkt) = NULL;
641 	unsigned short payload;
642 
643 	if (ncsi_priv->pending_requests)
644 		ncsi_priv->pending_requests--;
645 
646 	if (len < sizeof(struct ncsi_rsp_pkt_hdr)) {
647 		printf("NCSI: undersized packet: %u bytes\n", len);
648 		goto out;
649 	}
650 
651 	if (nh->common.type == NCSI_PKT_AEN)
652 		return ncsi_handle_aen(ip, len);
653 
654 	switch (nh->common.type) {
655 	case NCSI_PKT_RSP_SP:
656 		payload = 4;
657 		handler = ncsi_rsp_sp;
658 		break;
659 	case NCSI_PKT_RSP_DP:
660 		payload = 4;
661 		handler = ncsi_rsp_dp;
662 		break;
663 	case NCSI_PKT_RSP_CIS:
664 		payload = 4;
665 		handler = ncsi_rsp_cis;
666 		break;
667 	case NCSI_PKT_RSP_GLS:
668 		payload = 16;
669 		handler = ncsi_rsp_gls;
670 		break;
671 	case NCSI_PKT_RSP_GVI:
672 		payload = 40;
673 		handler = ncsi_rsp_gvi;
674 		break;
675 	case NCSI_PKT_RSP_GC:
676 		payload = 32;
677 		handler = ncsi_rsp_gc;
678 		break;
679 	case NCSI_PKT_RSP_SMA:
680 		payload = 4;
681 		handler = ncsi_rsp_sma;
682 		break;
683 	case NCSI_PKT_RSP_EBF:
684 		payload = 4;
685 		handler = ncsi_rsp_ebf;
686 		break;
687 	case NCSI_PKT_RSP_ECNT:
688 		payload = 4;
689 		handler = ncsi_rsp_ecnt;
690 		break;
691 	case NCSI_PKT_RSP_EC:
692 		payload = 4;
693 		handler = ncsi_rsp_ec;
694 		break;
695 	case NCSI_PKT_RSP_AE:
696 		payload = 4;
697 		handler = NULL;
698 		break;
699 	default:
700 		printf("NCSI: unsupported packet type 0x%02x\n",
701 		       nh->common.type);
702 		goto out;
703 	}
704 
705 	if (ncsi_validate_rsp(pkt, payload) != 0) {
706 		printf("NCSI: discarding invalid packet of type 0x%02x\n",
707 		       nh->common.type);
708 		goto out;
709 	}
710 
711 	if (handler)
712 		handler(pkt);
713 out:
714 	ncsi_update_state(nh);
715 }
716 
717 static void ncsi_send_sp(unsigned int np)
718 {
719 	uchar payload[4] = {0};
720 
721 	printf("%s\n", __func__);
722 
723 	ncsi_send_command(np, NCSI_RESERVED_CHANNEL, NCSI_PKT_CMD_SP,
724 			  (unsigned char *)&payload,
725 			  cmd_payload(NCSI_PKT_CMD_SP), true);
726 }
727 
728 static void ncsi_send_dp(unsigned int np)
729 {
730 	ncsi_send_command(np, NCSI_RESERVED_CHANNEL, NCSI_PKT_CMD_DP, NULL, 0,
731 			  true);
732 }
733 
734 static void ncsi_send_gls(unsigned int np, unsigned int nc)
735 {
736 	ncsi_send_command(np, nc, NCSI_PKT_CMD_GLS, NULL, 0, true);
737 }
738 
739 static void ncsi_send_cis(unsigned int np, unsigned int nc)
740 {
741 	ncsi_send_command(np, nc, NCSI_PKT_CMD_CIS, NULL, 0, true);
742 }
743 
744 static void ncsi_send_ae(unsigned int np, unsigned int nc)
745 {
746 	struct ncsi_cmd_ae_pkt cmd;
747 
748 	memset(&cmd, 0, sizeof(cmd));
749 	cmd.mode = htonl(ncsi_priv->packages[np].channels[nc].cap_aen);
750 
751 	ncsi_send_command(np, nc, NCSI_PKT_CMD_AE,
752 			  ((unsigned char *)&cmd)
753 			  + sizeof(struct ncsi_cmd_pkt_hdr),
754 			  cmd_payload(NCSI_PKT_CMD_AE), true);
755 }
756 
757 static void ncsi_send_ebf(unsigned int np, unsigned int nc)
758 {
759 	struct ncsi_cmd_ebf_pkt cmd;
760 
761 	memset(&cmd, 0, sizeof(cmd));
762 	cmd.mode = htonl(ncsi_priv->packages[np].channels[nc].cap_bc);
763 
764 	ncsi_send_command(np, nc, NCSI_PKT_CMD_EBF,
765 			  ((unsigned char *)&cmd)
766 			  + sizeof(struct ncsi_cmd_pkt_hdr),
767 			  cmd_payload(NCSI_PKT_CMD_EBF), true);
768 }
769 
770 static void ncsi_send_sma(unsigned int np, unsigned int nc)
771 {
772 	struct ncsi_cmd_sma_pkt cmd;
773 	unsigned char *addr, i;
774 
775 	addr = eth_get_ethaddr();
776 	if (!addr) {
777 		printf("NCSI: no MAC address configured\n");
778 		return;
779 	}
780 
781 	memset(&cmd, 0, sizeof(cmd));
782 	for (i = 0; i < ARP_HLEN; i++)
783 		cmd.mac[i] = addr[i];
784 	cmd.index = 1;
785 	cmd.at_e = 1;
786 
787 	ncsi_send_command(np, nc, NCSI_PKT_CMD_SMA,
788 			  ((unsigned char *)&cmd)
789 			  + sizeof(struct ncsi_cmd_pkt_hdr),
790 			  cmd_payload(NCSI_PKT_CMD_SMA), true);
791 }
792 
793 void ncsi_probe_packages(void)
794 {
795 	struct ncsi_package *package;
796 	unsigned int np, nc;
797 
798 	switch (ncsi_priv->state) {
799 	case NCSI_PROBE_PACKAGE_SP:
800 		if (ncsi_priv->current_package == NCSI_PACKAGE_MAX)
801 			ncsi_priv->current_package = 0;
802 		printf("%s: NCSI_PROBE_PACKAGE_SP current_package %d\n",
803 				__func__, ncsi_priv->current_package);
804 		ncsi_send_sp(ncsi_priv->current_package);
805 		break;
806 	case NCSI_PROBE_PACKAGE_DP:
807 		printf("%s: NCSI_PROBE_PACKAGE_DP current_package %d\n",
808 				__func__, ncsi_priv->current_package);
809 		ncsi_send_dp(ncsi_priv->current_package);
810 		break;
811 	case NCSI_PROBE_CHANNEL_SP:
812 		printf("%s: NCSI_PROBE_CHANNEL_SP\n", __func__);
813 		if (ncsi_priv->n_packages > 0)
814 			ncsi_send_sp(ncsi_priv->current_package);
815 		else
816 			printf("NCSI: no packages discovered, configuration not possible\n");
817 		break;
818 	case NCSI_PROBE_CHANNEL:
819 		printf("%s NCSI_PROBE_CHANNEL package %d channel %d\n",
820 				__func__,
821 				ncsi_priv->current_package,
822 				ncsi_priv->current_channel);
823 		/* Kicks off chain of channel discovery */
824 		ncsi_send_cis(ncsi_priv->current_package,
825 			      ncsi_priv->current_channel);
826 		break;
827 	case NCSI_CONFIG:
828 		for (np = 0; np < ncsi_priv->n_packages; np++) {
829 			package = &ncsi_priv->packages[np];
830 			for (nc = 0; nc < package->n_channels; nc++)
831 				if (package->channels[nc].has_link)
832 					break;
833 			if (nc < package->n_channels)
834 				break;
835 		}
836 		if (np == ncsi_priv->n_packages) {
837 			printf("NCSI: no link available\n");
838 			return;
839 		}
840 
841 		printf("NCSI: configuring channel %d\n", nc);
842 		ncsi_priv->current_package = np;
843 		ncsi_priv->current_channel = nc;
844 		/* Kicks off rest of configure chain */
845 		ncsi_send_sma(np, nc);
846 		break;
847 	default:
848 		printf("NCSI: unknown state 0x%x\n", ncsi_priv->state);
849 	}
850 }
851 
852 int ncsi_probe(struct phy_device *phydev)
853 {
854 	if (!phydev->priv) {
855 		phydev->priv = malloc(sizeof(struct ncsi));
856 		if (!phydev->priv)
857 			return -ENOMEM;
858 		memset(phydev->priv, 0, sizeof(struct ncsi));
859 	}
860 
861 	ncsi_priv = phydev->priv;
862 
863 	return 0;
864 }
865 
866 int ncsi_startup(struct phy_device *phydev)
867 {
868 	/* Set phydev parameters */
869 	phydev->speed = SPEED_100;
870 	phydev->duplex = DUPLEX_FULL;
871 	/* Normal phy reset is N/A */
872 	phydev->flags |= PHY_FLAG_BROKEN_RESET;
873 
874 	/* Set initial probe state */
875 	ncsi_priv->state = NCSI_PROBE_PACKAGE_SP;
876 
877 	/* No active package/channel yet */
878 	ncsi_priv->current_package = NCSI_PACKAGE_MAX;
879 	ncsi_priv->current_channel = NCSI_CHANNEL_MAX;
880 
881 	/* Pretend link works so the MAC driver sets final bits up */
882 	phydev->link = true;
883 
884 	/* Set ncsi_priv so we can use it when called from net_loop() */
885 	ncsi_priv = phydev->priv;
886 
887 	return 0;
888 }
889 
890 int ncsi_shutdown(struct phy_device *phydev)
891 {
892 	printf("NCSI: Disabling package %d\n", ncsi_priv->current_package);
893 	ncsi_send_dp(ncsi_priv->current_package);
894 	return 0;
895 }
896 
897 static struct phy_driver ncsi_driver = {
898 	.uid		= PHY_NCSI_ID,
899 	.mask		= 0xffffffff,
900 	.name		= "NC-SI",
901 	.features	= PHY_100BT_FEATURES | PHY_DEFAULT_FEATURES | SUPPORTED_100baseT_Full | SUPPORTED_MII,
902 	.probe		= ncsi_probe,
903 	.startup	= ncsi_startup,
904 	.shutdown	= ncsi_shutdown,
905 };
906 
907 int phy_ncsi_init(void)
908 {
909 	phy_register(&ncsi_driver);
910 	return 0;
911 }
912