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