static int cmd64x_init_one()

in pata_cmd64x.c [377:489]


static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
	static const struct ata_port_info cmd_info[7] = {
		{	/* CMD 643 - no UDMA */
			.flags = ATA_FLAG_SLAVE_POSS,
			.pio_mask = ATA_PIO4,
			.mwdma_mask = ATA_MWDMA2,
			.port_ops = &cmd64x_port_ops
		},
		{	/* CMD 646 with broken UDMA */
			.flags = ATA_FLAG_SLAVE_POSS,
			.pio_mask = ATA_PIO4,
			.mwdma_mask = ATA_MWDMA2,
			.port_ops = &cmd64x_port_ops
		},
		{	/* CMD 646U with broken UDMA */
			.flags = ATA_FLAG_SLAVE_POSS,
			.pio_mask = ATA_PIO4,
			.mwdma_mask = ATA_MWDMA2,
			.port_ops = &cmd646r3_port_ops
		},
		{	/* CMD 646U2 with working UDMA */
			.flags = ATA_FLAG_SLAVE_POSS,
			.pio_mask = ATA_PIO4,
			.mwdma_mask = ATA_MWDMA2,
			.udma_mask = ATA_UDMA2,
			.port_ops = &cmd646r3_port_ops
		},
		{	/* CMD 646 rev 1  */
			.flags = ATA_FLAG_SLAVE_POSS,
			.pio_mask = ATA_PIO4,
			.mwdma_mask = ATA_MWDMA2,
			.port_ops = &cmd646r1_port_ops
		},
		{	/* CMD 648 */
			.flags = ATA_FLAG_SLAVE_POSS,
			.pio_mask = ATA_PIO4,
			.mwdma_mask = ATA_MWDMA2,
			.udma_mask = ATA_UDMA4,
			.port_ops = &cmd648_port_ops
		},
		{	/* CMD 649 */
			.flags = ATA_FLAG_SLAVE_POSS,
			.pio_mask = ATA_PIO4,
			.mwdma_mask = ATA_MWDMA2,
			.udma_mask = ATA_UDMA5,
			.port_ops = &cmd648_port_ops
		}
	};
	const struct ata_port_info *ppi[] = {
		&cmd_info[id->driver_data],
		&cmd_info[id->driver_data],
		NULL
	};
	u8 reg;
	int rc;
	struct pci_dev *bridge = pdev->bus->self;
	/* mobility split bridges don't report enabled ports correctly */
	int port_ok = !(bridge && bridge->vendor ==
			PCI_VENDOR_ID_MOBILITY_ELECTRONICS);
	/* all (with exceptions below) apart from 643 have CNTRL_CH0 bit */
	int cntrl_ch0_ok = (id->driver_data != 0);

	rc = pcim_enable_device(pdev);
	if (rc)
		return rc;

	if (id->driver_data == 0)	/* 643 */
		ata_pci_bmdma_clear_simplex(pdev);

	if (pdev->device == PCI_DEVICE_ID_CMD_646)
		switch (pdev->revision) {
		/* UDMA works since rev 5 */
		default:
			ppi[0] = &cmd_info[3];
			ppi[1] = &cmd_info[3];
			break;
		/* Interrupts in MRDMODE since rev 3 */
		case 3:
		case 4:
			ppi[0] = &cmd_info[2];
			ppi[1] = &cmd_info[2];
			break;
		/* Rev 1 with other problems? */
		case 1:
			ppi[0] = &cmd_info[4];
			ppi[1] = &cmd_info[4];
			fallthrough;
		/* Early revs have no CNTRL_CH0 */
		case 2:
		case 0:
			cntrl_ch0_ok = 0;
			break;
		}

	cmd64x_fixup(pdev);

	/* check for enabled ports */
	pci_read_config_byte(pdev, CNTRL, &reg);
	if (!port_ok)
		dev_notice(&pdev->dev, "Mobility Bridge detected, ignoring CNTRL port enable/disable\n");
	if (port_ok && cntrl_ch0_ok && !(reg & CNTRL_CH0)) {
		dev_notice(&pdev->dev, "Primary port is disabled\n");
		ppi[0] = &ata_dummy_port_info;

	}
	if (port_ok && !(reg & CNTRL_CH1)) {
		dev_notice(&pdev->dev, "Secondary port is disabled\n");
		ppi[1] = &ata_dummy_port_info;
	}

	return ata_pci_bmdma_init_one(pdev, ppi, &cmd64x_sht, NULL, 0);
}