static int ti12xx_2nd_slot_empty()

in ti113x.h [651:735]


static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
{
	struct pci_dev *func;
	struct yenta_socket *slot2;
	int devfn;
	unsigned int state;
	int ret = 1;
	u32 sysctl;

	/* catch the two-slot controllers */
	switch (socket->dev->device) {
	case PCI_DEVICE_ID_TI_1220:
	case PCI_DEVICE_ID_TI_1221:
	case PCI_DEVICE_ID_TI_1225:
	case PCI_DEVICE_ID_TI_1251A:
	case PCI_DEVICE_ID_TI_1251B:
	case PCI_DEVICE_ID_TI_1420:
	case PCI_DEVICE_ID_TI_1450:
	case PCI_DEVICE_ID_TI_1451A:
	case PCI_DEVICE_ID_TI_1520:
	case PCI_DEVICE_ID_TI_1620:
	case PCI_DEVICE_ID_TI_4520:
	case PCI_DEVICE_ID_TI_4450:
	case PCI_DEVICE_ID_TI_4451:
		/*
		 * there are way more, but they need to be added in yenta_socket.c
		 * and pci_ids.h first anyway.
		 */
		break;

	case PCI_DEVICE_ID_TI_XX12:
	case PCI_DEVICE_ID_TI_X515:
	case PCI_DEVICE_ID_TI_X420:
	case PCI_DEVICE_ID_TI_X620:
	case PCI_DEVICE_ID_TI_XX21_XX11:
	case PCI_DEVICE_ID_TI_7410:
	case PCI_DEVICE_ID_TI_7610:
		/*
		 * those are either single or dual slot CB with additional functions
		 * like 1394, smartcard reader, etc. check the TIEALL flag for them
		 * the TIEALL flag binds the IRQ of all functions together.
		 * we catch the single slot variants later.
		 */
		sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
		if (sysctl & TIXX21_SCR_TIEALL)
			return 0;

		break;

	/* single-slot controllers have the 2nd slot empty always :) */
	default:
		return 1;
	}

	/* get other slot */
	devfn = socket->dev->devfn & ~0x07;
	func = pci_get_slot(socket->dev->bus,
	                    (socket->dev->devfn & 0x07) ? devfn : devfn | 0x01);
	if (!func)
		return 1;

	/*
	 * check that the device id of both slots match. this is needed for the
	 * XX21 and the XX11 controller that share the same device id for single
	 * and dual slot controllers. return '2nd slot empty'. we already checked
	 * if the interrupt is tied to another function.
	 */
	if (socket->dev->device != func->device)
		goto out;

	slot2 = pci_get_drvdata(func);
	if (!slot2)
		goto out;

	/* check state */
	yenta_get_status(&slot2->socket, &state);
	if (state & SS_DETECT) {
		ret = 0;
		goto out;
	}

out:
	pci_dev_put(func);
	return ret;
}