예제 #1
0
static int
aic7770_attach(device_t dev)
{
	struct	 aic7770_identity *entry;
	struct	 ahc_softc *ahc;
	char	*name;
	int	 error;

	entry = aic7770_find_device(eisa_get_id(dev));
	if (entry == NULL)
		return (ENXIO);

	/*
	 * Allocate a softc for this card and
	 * set it up for attachment by our
	 * common detect routine.
	 */
	name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT);
	if (name == NULL)
		return (ENOMEM);
	strcpy(name, device_get_nameunit(dev));
	ahc = ahc_alloc(dev, name);
	if (ahc == NULL)
		return (ENOMEM);

	ahc_set_unit(ahc, device_get_unit(dev));

	/* Allocate a dmatag for our SCB DMA maps */
	/* XXX Should be a child of the PCI bus dma tag */
	error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev),
				   /*alignment*/1, /*boundary*/0,
				   /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
				   /*highaddr*/BUS_SPACE_MAXADDR,
				   /*filter*/NULL, /*filterarg*/NULL,
				   /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
				   /*nsegments*/AHC_NSEG,
				   /*maxsegsz*/AHC_MAXTRANSFER_SIZE,
				   /*flags*/0,
				   &ahc->parent_dmat);

	if (error != 0) {
		printf("ahc_eisa_attach: Could not allocate DMA tag "
		       "- error %d\n", error);
		ahc_free(ahc);
		return (ENOMEM);
	}
	ahc->dev_softc = dev;
	error = aic7770_config(ahc, entry, /*unused ioport arg*/0);
	if (error != 0) {
		ahc_free(ahc);
		return (error);
	}

	ahc_attach(ahc);
	return (0);
}
예제 #2
0
/*
 * Perform an EISA probe of the address with the addition
 * of a "priming" step.  The 284X requires priming (a write
 * to offset 0x80, the first EISA ID register) to ensure it
 * is not mistaken as an EISA card.  Once we have the ID,
 * lookup the controller in the aic7770 table of supported
 * devices.
 */
static struct aic7770_identity *
ahc_isa_find_device(bus_space_tag_t tag, bus_space_handle_t bsh) {
	uint32_t  id;
	u_int	  id_size;
	int	  i;

	id = 0;
	id_size = sizeof(id);
	for (i = 0; i < id_size; i++) {
		bus_space_write_1(tag, bsh, 0x80, 0x80 + i);
		id |= bus_space_read_1(tag, bsh, 0x80 + i)
		   << ((id_size - i - 1) * CHAR_BIT);
	}
                           
	return (aic7770_find_device(id));
}
예제 #3
0
static int
aic7770_probe(device_t dev)
{
	struct	 aic7770_identity *entry;
	struct	 resource *regs;
	uint32_t iobase;
	bus_space_handle_t bsh;
	bus_space_tag_t	tag;
	u_int	 irq;
	u_int	 intdef;
	u_int	 hcntrl;
	int	 shared;
	int	 rid;
	int	 error;

	entry = aic7770_find_device(eisa_get_id(dev));
	if (entry == NULL)
		return (ENXIO);
	device_set_desc(dev, entry->name);

	iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + AHC_EISA_SLOT_OFFSET;

	eisa_add_iospace(dev, iobase, AHC_EISA_IOSIZE, RESVADDR_NONE);

	rid = 0;
	regs = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
	if (regs == NULL) {
		device_printf(dev, "Unable to map I/O space?!\n");
		return ENOMEM;
	}

	tag = rman_get_bustag(regs);
	bsh = rman_get_bushandle(regs);
	error = 0;

	/* Pause the card preseving the IRQ type */
	hcntrl = bus_space_read_1(tag, bsh, HCNTRL) & IRQMS;
	bus_space_write_1(tag, bsh, HCNTRL, hcntrl | PAUSE);
	while ((bus_space_read_1(tag, bsh, HCNTRL) & PAUSE) == 0)
		;

	/* Make sure we have a valid interrupt vector */
	intdef = bus_space_read_1(tag, bsh, INTDEF);
	shared = (intdef & EDGE_TRIG) ? EISA_TRIGGER_EDGE : EISA_TRIGGER_LEVEL;
	irq = intdef & VECTOR;
	switch (irq) {
	case 9: 
	case 10:
	case 11:
	case 12:
	case 14:
	case 15:
		break;
	default:
		printf("aic7770 at slot %d: illegal irq setting %d\n",
		       eisa_get_slot(dev), intdef);
		error = ENXIO;
	}

	if (error == 0)
		eisa_add_intr(dev, irq, shared);

	bus_release_resource(dev, SYS_RES_IOPORT, rid, regs);
	return (error);
}
void
ahc_linux_eisa_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
	struct eisa_device_id *eid;
	struct aic7770_identity *id;
	int i;

	if (aic7xxx_probe_eisa_vl == 0)
		return;

	/*
	 * Linux requires the EISA IDs to be specified in
	 * the EISA ID string format.  Perform the conversion
	 * and setup a table with a NUL terminal entry.
	 */
	aic7770_driver.id_table = malloc(sizeof(struct eisa_device_id) *
					 (ahc_num_aic7770_devs + 1),
					 M_DEVBUF, M_NOWAIT);
	if (aic7770_driver.id_table == NULL)
		return;

	for (eid = (struct eisa_device_id *)aic7770_driver.id_table,
	     id = aic7770_ident_table, i = 0;
	     i < ahc_num_aic7770_devs; eid++, id++, i++) {

		sprintf(eid->sig, "%c%c%c%03X%01X",
			EISA_MFCTR_CHAR0(id->full_id),
			EISA_MFCTR_CHAR1(id->full_id),
			EISA_MFCTR_CHAR2(id->full_id),
			EISA_PRODUCT_ID(id->full_id),
			EISA_REVISION_ID(id->full_id));
		eid->driver_data = i;
	}
	eid->sig[0] = 0;

	eisa_driver_register(&aic7770_driver);
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */
	struct aic7770_identity *entry;
	u_int  slot;
	u_int  eisaBase;
	u_int  i;

	if (aic7xxx_probe_eisa_vl == 0)
		return;

	eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET;
	for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) {
		uint32_t eisa_id;
		size_t	 id_size;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
		if (check_region(eisaBase, AHC_EISA_IOSIZE) != 0)
			continue;
		request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx");
#else
		if (request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx") == 0)
			continue;
#endif

		eisa_id = 0;
		id_size = sizeof(eisa_id);
		for (i = 0; i < 4; i++) {
			/* VLcards require priming*/
			outb(0x80 + i, eisaBase + IDOFFSET);
			eisa_id |= inb(eisaBase + IDOFFSET + i)
				   << ((id_size-i-1) * 8);
		}
		release_region(eisaBase, AHC_EISA_IOSIZE);
		if (eisa_id & 0x80000000)
			continue;  /* no EISA card in slot */

		entry = aic7770_find_device(eisa_id);
		if (entry != NULL)
			aic7770_linux_config(entry, NULL, eisaBase);
	}
#endif
}