drivers/net/ethernet/alacritech/slicoss.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/alacritech/slicoss.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/alacritech/slicoss.c
Extension
.c
Size
47375 bytes
Lines
1848
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct net_device_ops slic_netdev_ops = {
	.ndo_open		= slic_open,
	.ndo_stop		= slic_close,
	.ndo_start_xmit		= slic_xmit,
	.ndo_set_mac_address	= eth_mac_addr,
	.ndo_get_stats64	= slic_get_stats,
	.ndo_set_rx_mode	= slic_set_rx_mode,
	.ndo_validate_addr	= eth_validate_addr,
};

static u16 slic_eeprom_csum(unsigned char *eeprom, unsigned int len)
{
	unsigned char *ptr = eeprom;
	u32 csum = 0;
	__le16 data;

	while (len > 1) {
		memcpy(&data, ptr, sizeof(data));
		csum += le16_to_cpu(data);
		ptr += 2;
		len -= 2;
	}
	if (len > 0)
		csum += *(u8 *)ptr;
	while (csum >> 16)
		csum = (csum & 0xFFFF) + ((csum >> 16) & 0xFFFF);
	return ~csum;
}

/* check eeprom size, magic and checksum */
static bool slic_eeprom_valid(unsigned char *eeprom, unsigned int size)
{
	const unsigned int MAX_SIZE = 128;
	const unsigned int MIN_SIZE = 98;
	__le16 magic;
	__le16 csum;

	if (size < MIN_SIZE || size > MAX_SIZE)
		return false;
	memcpy(&magic, eeprom, sizeof(magic));
	if (le16_to_cpu(magic) != SLIC_EEPROM_MAGIC)
		return false;
	/* cut checksum bytes */
	size -= 2;
	memcpy(&csum, eeprom + size, sizeof(csum));

	return (le16_to_cpu(csum) == slic_eeprom_csum(eeprom, size));
}

static int slic_read_eeprom(struct slic_device *sdev)
{
	unsigned int devfn = PCI_FUNC(sdev->pdev->devfn);
	struct slic_shmem *sm = &sdev->shmem;
	struct slic_shmem_data *sm_data = sm->shmem_data;
	const unsigned int MAX_LOOPS = 5000;
	unsigned int codesize;
	unsigned char *eeprom;
	struct slic_upr *upr;
	unsigned int i = 0;
	dma_addr_t paddr;
	int err = 0;
	u8 *mac[2];

	eeprom = dma_alloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE,
				    &paddr, GFP_KERNEL);
	if (!eeprom)
		return -ENOMEM;

	slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_OFF);
	/* setup ISP temporarily */
	slic_write(sdev, SLIC_REG_ISP, lower_32_bits(sm->isr_paddr));

	err = slic_new_upr(sdev, SLIC_UPR_CONFIG, paddr);
	if (!err) {
		for (i = 0; i < MAX_LOOPS; i++) {
			if (le32_to_cpu(sm_data->isr) & SLIC_ISR_UPC)
				break;
			mdelay(1);
		}
		if (i == MAX_LOOPS) {
			dev_err(&sdev->pdev->dev,
				"timed out while waiting for eeprom data\n");
			err = -ETIMEDOUT;
		}
		upr = slic_dequeue_upr(sdev);
		kfree(upr);
	}

	slic_write(sdev, SLIC_REG_ISP, 0);
	slic_write(sdev, SLIC_REG_ISR, 0);

Annotation

Implementation Notes