TWE_DPRINTF(TWE_D_CMD, ("stat=%b ", bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));  bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL, TWE_CTRL_CHOSTI | TWE_CTRL_CATTNI | TWE_CTRL_CERR); TWE_DPRINTF(TWE_D_CMD, ("stat=%b ", bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));  bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL, TWE_CTRL_EINT | TWE_CTRL_ERDYI |  TWE_CTRL_MCMDI);  return 0;
kthread_create_deferred(twe_thread_create, sc);  return (0);
twe_attach(sc)	struct twe_softc *sc;{	/* this includes a buffer for drive config req, and a capacity req */	u_int8_t	param_buf[2 * TWE_SECTOR_SIZE + TWE_ALIGN - 1];	struct twe_param *pb = (void *)	    (((u_long)param_buf + TWE_ALIGN - 1) & ~(TWE_ALIGN - 1));	struct twe_param *cap = (void *)((u_int8_t *)pb + TWE_SECTOR_SIZE);	struct twe_ccb	*ccb;	struct twe_cmd	*cmd;	u_int32_t	status;	int		error, i, retry, nunits, nseg;	const char	*errstr;	twe_lock_t	lock;	paddr_t		pa;	error = bus_dmamem_alloc(sc->dmat, sizeof(struct twe_cmd) * TWE_MAXCMDS,	    PAGE_SIZE, 0, sc->sc_cmdseg, 1, &nseg, BUS_DMA_NOWAIT);	if (error) {		printf(": cannot allocate commands (%d)\n", error);		return (1);	}	error = bus_dmamem_map(sc->dmat, sc->sc_cmdseg, nseg,	    sizeof(struct twe_cmd) * TWE_MAXCMDS,	    (caddr_t *)&sc->sc_cmds, BUS_DMA_NOWAIT);	if (error) {		printf(": cannot map commands (%d)\n", error);		bus_dmamem_free(sc->dmat, sc->sc_cmdseg, 1);		return (1);	}	error = bus_dmamap_create(sc->dmat,	    sizeof(struct twe_cmd) * TWE_MAXCMDS, TWE_MAXCMDS,	    sizeof(struct twe_cmd) * TWE_MAXCMDS, 0,	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_cmdmap);	if (error) {		printf(": cannot create ccb cmd dmamap (%d)\n", error);		twe_dispose(sc);		return (1);	}	error = bus_dmamap_load(sc->dmat, sc->sc_cmdmap, sc->sc_cmds,	    sizeof(struct twe_cmd) * TWE_MAXCMDS, NULL, BUS_DMA_NOWAIT);	if (error) {		printf(": cannot load command dma map (%d)\n", error);		twe_dispose(sc);		return (1);	}	TAILQ_INIT(&sc->sc_ccb2q);	TAILQ_INIT(&sc->sc_ccbq);	TAILQ_INIT(&sc->sc_free_ccb);	pa = sc->sc_cmdmap->dm_segs[0].ds_addr +	    sizeof(struct twe_cmd) * (TWE_MAXCMDS - 1);;	for (cmd = sc->sc_cmds + sizeof(struct twe_cmd) * (TWE_MAXCMDS - 1);	     cmd >= (struct twe_cmd *)sc->sc_cmds; cmd--, pa -= sizeof(*cmd)) {		cmd->cmd_index = cmd - (struct twe_cmd *)sc->sc_cmds;		ccb = &sc->sc_ccbs[cmd->cmd_index];		error = bus_dmamap_create(sc->dmat,		    TWE_MAXFER, TWE_MAXOFFSETS, TWE_MAXFER, 0,		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap);		if (error) {			printf(": cannot create ccb dmamap (%d)\n", error);			twe_dispose(sc);			return (1);		}		ccb->ccb_sc = sc;		ccb->ccb_cmd = cmd;		ccb->ccb_cmdpa = pa;		ccb->ccb_state = TWE_CCB_FREE;		TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);	}	for (errstr = NULL, retry = 3; retry--; ) {		int		veseen_srst;		u_int16_t	aen;		if (errstr)			TWE_DPRINTF(TWE_D_MISC, ("%s ", errstr));		for (i = 350000; i--; DELAY(100)) {			status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);			if (status & TWE_STAT_CPURDY)				break;		}		if (!(status & TWE_STAT_CPURDY)) {			errstr = ": card CPU is not ready\n";			continue;		}		/* soft reset, disable ints */		bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,		    TWE_CTRL_SRST |		    TWE_CTRL_CHOSTI | TWE_CTRL_CATTNI | TWE_CTRL_CERR |		    TWE_CTRL_MCMDI | TWE_CTRL_MRDYI |		    TWE_CTRL_MINT);		for (i = 350000; i--; DELAY(100)) {			status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);			if (status & TWE_STAT_ATTNI)				break;		}		if (!(status & TWE_STAT_ATTNI)) {			errstr = ": cannot get card's attention\n";			continue;		}		/* drain aen queue */		for (veseen_srst = 0, aen = -1; aen != TWE_AEN_QEMPTY; ) {			if ((ccb = twe_get_ccb(sc)) == NULL) {				errstr = ": out of ccbs\n";				continue;			}			ccb->ccb_xs = NULL;			ccb->ccb_data = pb;			ccb->ccb_length = TWE_SECTOR_SIZE;			ccb->ccb_state = TWE_CCB_READY;			cmd = ccb->ccb_cmd;			cmd->cmd_unit_host = TWE_UNITHOST(0, 0);			cmd->cmd_op = TWE_CMD_GPARAM;			cmd->cmd_param.count = 1;			pb->table_id = TWE_PARAM_AEN;			pb->param_id = 2;			pb->param_size = 2;			if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {				errstr = ": error draining attention queue\n";				break;			}			aen = *(u_int16_t *)pb->data;			TWE_DPRINTF(TWE_D_AEN, ("aen=%x ", aen));			if (aen == TWE_AEN_SRST)				veseen_srst++;		}		if (!veseen_srst) {			errstr = ": we don't get it\n";			continue;		}		if (status & TWE_STAT_CPUERR) {			errstr = ": card CPU error detected\n";			continue;		}		if (status & TWE_STAT_PCIPAR) {			errstr = ": PCI parity error detected\n";			continue;		}		if (status & TWE_STAT_QUEUEE ) {			errstr = ": queuing error detected\n";			continue;		}		if (status & TWE_STAT_PCIABR) {			errstr = ": PCI abort\n";			continue;		}		while (!(status & TWE_STAT_RQE)) {			bus_space_read_4(sc->iot, sc->ioh, TWE_READYQUEUE);			status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);		}		break;	}	if (retry < 0) {		printf(errstr);		twe_dispose(sc);		return 1;	}	if ((ccb = twe_get_ccb(sc)) == NULL) {		printf(": out of ccbs\n");		twe_dispose(sc);		return 1;	}	ccb->ccb_xs = NULL;	ccb->ccb_data = pb;	ccb->ccb_length = TWE_SECTOR_SIZE;	ccb->ccb_state = TWE_CCB_READY;	cmd = ccb->ccb_cmd;	cmd->cmd_unit_host = TWE_UNITHOST(0, 0);	cmd->cmd_op = TWE_CMD_GPARAM;	cmd->cmd_param.count = 1;	pb->table_id = TWE_PARAM_UC;	pb->param_id = TWE_PARAM_UC;	pb->param_size = TWE_MAX_UNITS;	if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {		printf(": failed to fetch unit parameters\n");		twe_dispose(sc);		return 1;	}	/* we are assuming last read status was good */	printf(": Escalade V%d.%d\n", TWE_MAJV(status), TWE_MINV(status));	for (nunits = i = 0; i < TWE_MAX_UNITS; i++) {		if (pb->data[i] == 0)			continue;		if ((ccb = twe_get_ccb(sc)) == NULL) {			printf(": out of ccbs\n");			twe_dispose(sc);			return 1;		}		ccb->ccb_xs = NULL;		ccb->ccb_data = cap;		ccb->ccb_length = TWE_SECTOR_SIZE;		ccb->ccb_state = TWE_CCB_READY;		cmd = ccb->ccb_cmd;		cmd->cmd_unit_host = TWE_UNITHOST(0, 0);		cmd->cmd_op = TWE_CMD_GPARAM;		cmd->cmd_param.count = 1;		cap->table_id = TWE_PARAM_UI + i;		cap->param_id = 4;		cap->param_size = 4;	/* 4 bytes */		lock = TWE_LOCK_TWE(sc);		if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {			TWE_UNLOCK_TWE(sc, lock);			printf("%s: error fetching capacity for unit %d\n",			    sc->sc_dev.dv_xname, i);			continue;		}		TWE_UNLOCK_TWE(sc, lock);		nunits++;		sc->sc_hdr[i].hd_present = 1;		sc->sc_hdr[i].hd_devtype = 0;		sc->sc_hdr[i].hd_size = letoh32(*(u_int32_t *)cap->data);		/* this is evil. they never learn */		if (sc->sc_hdr[i].hd_size > 0x200000) {			sc->sc_hdr[i].hd_secs = 63;			sc->sc_hdr[i].hd_heads = 255;		} else {			sc->sc_hdr[i].hd_secs = 32;			sc->sc_hdr[i].hd_heads = 64;		}		TWE_DPRINTF(TWE_D_MISC, ("twed%d: size=%d secs=%d heads=%d\n",		    i, sc->sc_hdr[i].hd_size, sc->sc_hdr[i].hd_secs,		    sc->sc_hdr[i].hd_heads));	}	if (!nunits)		nunits++;	/* TODO: fetch & print cache params? */	sc->sc_link.adapter_softc = sc;	sc->sc_link.adapter = &twe_switch;	sc->sc_link.adapter_target = TWE_MAX_UNITS;	sc->sc_link.device = &twe_dev;	sc->sc_link.openings = TWE_MAXCMDS / nunits;	sc->sc_link.adapter_buswidth = TWE_MAX_UNITS;	config_found(&sc->sc_dev, &sc->sc_link, scsiprint);	TWE_DPRINTF(TWE_D_CMD, ("stat=%b ",	    bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));	/*	 * ack all before enable, cannot be done in one	 * operation as it seems clear is not processed	 * if enable is specified.	 */	bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,	    TWE_CTRL_CHOSTI | TWE_CTRL_CATTNI | TWE_CTRL_CERR);	TWE_DPRINTF(TWE_D_CMD, ("stat=%b ",	    bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));	/* enable interrupts */	bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,	    TWE_CTRL_EINT | TWE_CTRL_ERDYI |	    /*TWE_CTRL_HOSTI |*/ TWE_CTRL_MCMDI);	return 0;}