drivers/net/ethernet/dec/tulip/eeprom.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/dec/tulip/eeprom.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/dec/tulip/eeprom.c
Extension
.c
Size
12548 bytes
Lines
382
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ee_data[0] == 0xff) {
			if (last_mediatable) {
				controller_index++;
				pr_info("%s: Controller %d of multiport board\n",
					dev->name, controller_index);
				tp->mtable = last_mediatable;
				ee_data = last_ee_data;
				goto subsequent_board;
			} else
				pr_info("%s: Missing EEPROM, this interface may not work correctly!\n",
					dev->name);
			return;
		}
	  /* Do a fix-up based on the vendor half of the station address prefix. */
	  for (i = 0; eeprom_fixups[i].name; i++) {
		  if (dev->dev_addr[0] == eeprom_fixups[i].addr0 &&
		      dev->dev_addr[1] == eeprom_fixups[i].addr1 &&
		      dev->dev_addr[2] == eeprom_fixups[i].addr2) {
		  if (dev->dev_addr[2] == 0xE8 && ee_data[0x1a] == 0x55)
			  i++;			/* An Accton EN1207, not an outlaw Maxtech. */
		  memcpy(ee_data + 26, eeprom_fixups[i].newtable,
				 sizeof(eeprom_fixups[i].newtable));
		  pr_info("%s: Old format EEPROM on '%s' board.  Using substitute media control info\n",
			  dev->name, eeprom_fixups[i].name);
		  break;
		}
	  }
	  if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
		  pr_info("%s: Old style EEPROM with no media selection information\n",
			  dev->name);
		return;
	  }
	}

	controller_index = 0;
	if (ee_data[19] > 1) {		/* Multiport board. */
		last_ee_data = ee_data;
	}
subsequent_board:

	if (ee_data[27] == 0) {		/* No valid media table. */
		tulip_build_fake_mediatable(tp);
	} else {
		unsigned char *p = (void *)ee_data + ee_data[27];
		unsigned char csr12dir = 0;
		int count, new_advertise = 0;
		struct mediatable *mtable;
		u16 media = get_u16(p);

		p += 2;
		if (tp->flags & CSR12_IN_SROM)
			csr12dir = *p++;
		count = *p++;

	        /* there is no phy information, don't even try to build mtable */
	        if (count == 0) {
			if (tulip_debug > 0)
				pr_warn("%s: no phy info, aborting mtable build\n",
					dev->name);
		        return;
		}

		mtable = devm_kmalloc(&tp->pdev->dev, struct_size(mtable, mleaf, count),
				      GFP_KERNEL);
		if (mtable == NULL)
			return;				/* Horrible, impossible failure. */
		last_mediatable = tp->mtable = mtable;
		mtable->defaultmedia = media;
		mtable->leafcount = count;
		mtable->csr12dir = csr12dir;
		mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
		mtable->csr15dir = mtable->csr15val = 0;

		pr_info("%s: EEPROM default media type %s\n",
			dev->name,
			media & 0x0800 ? "Autosense"
				       : medianame[media & MEDIA_MASK]);
		for (i = 0; i < count; i++) {
			struct medialeaf *leaf = &mtable->mleaf[i];

			if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
				leaf->type = 0;
				leaf->media = p[0] & 0x3f;
				leaf->leafdata = p;
				if ((p[2] & 0x61) == 0x01)	/* Bogus, but Znyx boards do it. */
					mtable->has_mii = 1;
				p += 4;
			} else {
				leaf->type = p[1];
				if (p[1] == 0x05) {

Annotation

Implementation Notes