drivers/scsi/isci/probe_roms.c

Source file repositories/reference/linux-study-clean/drivers/scsi/isci/probe_roms.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/isci/probe_roms.c
Extension
.c
Size
5456 bytes
Lines
232
Domain
Driver Families
Bucket
drivers/scsi
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 (memcmp(oem_sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) == 0) {
			size_t copy_len;

			memcpy_fromio(&oem_hdr, oprom + i, sizeof(oem_hdr));

			copy_len = min(oem_hdr.len - sizeof(oem_hdr),
				       sizeof(*rom));

			memcpy_fromio(rom,
				      oprom + i + sizeof(oem_hdr),
				      copy_len);

			/* calculate checksum */
			tmp = (u8 *)&oem_hdr;
			for (j = 0, sum = 0; j < sizeof(oem_hdr); j++, tmp++)
				sum += *tmp;

			tmp = (u8 *)rom;
			for (j = 0; j < sizeof(*rom); j++, tmp++)
				sum += *tmp;

			if (sum != 0) {
				dev_warn(&pdev->dev,
					 "OEM table checksum failed\n");
				continue;
			}

			/* keep going if that's not the oem param table */
			if (memcmp(rom->hdr.signature,
				   ISCI_ROM_SIG,
				   ISCI_ROM_SIG_SIZE) != 0)
				continue;

			dev_info(&pdev->dev,
				 "OEM parameter table found in OROM\n");
			break;
		}
	}

	if (i >= len) {
		dev_err(&pdev->dev, "oprom parse error\n");
		rom = NULL;
	}
	pci_unmap_biosrom(oprom);

	return rom;
}

struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw)
{
	struct isci_orom *orom = NULL, *data;
	int i, j;

	if (request_firmware(&fw, ISCI_FW_NAME, &pdev->dev) != 0)
		return NULL;

	if (fw->size < sizeof(*orom))
		goto out;

	data = (struct isci_orom *)fw->data;

	if (strncmp(ISCI_ROM_SIG, data->hdr.signature,
		    strlen(ISCI_ROM_SIG)) != 0)
		goto out;

	orom = devm_kzalloc(&pdev->dev, fw->size, GFP_KERNEL);
	if (!orom)
		goto out;

	memcpy(orom, fw->data, fw->size);

	if (is_c0(pdev) || is_c1(pdev))
		goto out;

	/*
	 * deprecated: override default amp_control for pre-preproduction
	 * silicon revisions
	 */
	for (i = 0; i < ARRAY_SIZE(orom->ctrl); i++)
		for (j = 0; j < ARRAY_SIZE(orom->ctrl[i].phys); j++) {
			orom->ctrl[i].phys[j].afe_tx_amp_control0 = 0xe7c03;
			orom->ctrl[i].phys[j].afe_tx_amp_control1 = 0xe7c03;
			orom->ctrl[i].phys[j].afe_tx_amp_control2 = 0xe7c03;
			orom->ctrl[i].phys[j].afe_tx_amp_control3 = 0xe7c03;
		}
 out:
	release_firmware(fw);

	return orom;
}

Annotation

Implementation Notes