struct bootpath *bp;
xdattach(parent, self, aux)	struct device *parent, *self;	void   *aux;{	struct xd_softc *xd = (void *) self;	struct xdc_softc *xdc = (void *) parent;	struct xdc_attach_args *xa = aux;	int     rqno, err, spt, mb, blk, lcv, fmode, s, newstate;	struct xd_iopb_drive *driopb;	struct dkbad *dkb;	struct bootpath *bp;	/*	 * Always re-initialize the disk structure.  We want statistics	 * to start with a clean slate.	 */	bzero(&xd->sc_dk, sizeof(xd->sc_dk));	xd->sc_dk.dk_driver = &xddkdriver;	xd->sc_dk.dk_name = xd->sc_dev.dv_xname;	/* if booting, init the xd_softc */	if (xa->booting) {		xd->state = XD_DRIVE_UNKNOWN;	/* to start */		xd->flags = 0;		xd->parent = xdc;	}	xd->xd_drive = xa->driveno;	fmode = xa->fullmode;	xdc->sc_drives[xa->driveno] = xd;	/* if not booting, make sure we are the only process in the attach for	 * this drive.   if locked out, sleep on it. */	if (!xa->booting) {		s = splbio();		while (xd->state == XD_DRIVE_ATTACHING) {			if (tsleep(&xd->state, PRIBIO, "xdattach", 0)) {				splx(s);				return;			}		}		printf("%s at %s",			xd->sc_dev.dv_xname,			xd->parent->sc_dev.dv_xname);	}	/* we now have control */	xd->state = XD_DRIVE_ATTACHING;	newstate = XD_DRIVE_UNKNOWN;	/* first try and reset the drive */	rqno = xdc_cmd(xdc, XDCMD_RST, 0, xd->xd_drive, 0, 0, 0, fmode);	XDC_DONE(xdc, rqno, err);	if (err == XD_ERR_NRDY) {		printf(" drive %d: off-line\n", xa->driveno);		goto done;	}	if (err) {		printf(": ERROR 0x%02x (%s)\n", err, xdc_e2str(err));		goto done;	}	printf(" drive %d: ready\n", xa->driveno);	/* now set format parameters */	rqno = xdc_cmd(xdc, XDCMD_WRP, XDFUN_FMT, xd->xd_drive, 0, 0, 0, fmode);	XDC_DONE(xdc, rqno, err);	if (err) {		printf("%s: write format parameters failed: %s\n",			xd->sc_dev.dv_xname, xdc_e2str(err));		goto done;	}	/* get drive parameters */	rqno = xdc_cmd(xdc, XDCMD_RDP, XDFUN_DRV, xd->xd_drive, 0, 0, 0, fmode);	if (rqno != XD_ERR_FAIL) {		driopb = (struct xd_iopb_drive *) & xdc->iopbase[rqno];		spt = driopb->sectpertrk;	}	XDC_DONE(xdc, rqno, err);	if (err) {		printf("%s: read drive parameters failed: %s\n",			xd->sc_dev.dv_xname, xdc_e2str(err));		goto done;	}	/*	 * now set drive parameters (to semi-bogus values) so we can read the	 * disk label.	 */	xd->pcyl = xd->ncyl = 1;	xd->acyl = 0;	xd->nhead = 1;	xd->nsect = 1;	xd->sectpercyl = 1;	for (lcv = 0; lcv < 126; lcv++)	/* init empty bad144 table */		xd->dkb.bt_bad[lcv].bt_cyl = xd->dkb.bt_bad[lcv].bt_trksec = 0xffff;	rqno = xdc_cmd(xdc, XDCMD_WRP, XDFUN_DRV, xd->xd_drive, 0, 0, 0, fmode);	XDC_DONE(xdc, rqno, err);	if (err) {		printf("%s: write drive parameters failed: %s\n",			xd->sc_dev.dv_xname, xdc_e2str(err));		goto done;	}	/* read disk label */	rqno = xdc_cmd(xdc, XDCMD_RD, 0, xd->xd_drive, 0, 1,				   xa->dvmabuf, fmode);	XDC_DONE(xdc, rqno, err);	if (err) {		printf("%s: reading disk label failed: %s\n",			xd->sc_dev.dv_xname, xdc_e2str(err));		goto done;	}	newstate = XD_DRIVE_NOLABEL;	xd->hw_spt = spt;	/* Attach the disk: must be before getdisklabel to malloc label */	disk_attach(&xd->sc_dk);	if (xdgetdisklabel(xd, xa->dvmabuf) != XD_ERR_AOK)		goto done;	/* inform the user of what is up */	printf("%s: <%s>, pcyl %d, hw_spt %d\n",		xd->sc_dev.dv_xname,		xa->dvmabuf, xd->pcyl, spt);	mb = xd->ncyl * (xd->nhead * xd->nsect) / (1048576 / XDFM_BPS);	printf("%s: %dMB, %d cyl, %d head, %d sec, %d bytes/sec\n",		xd->sc_dev.dv_xname, mb,		xd->ncyl, xd->nhead, xd->nsect, XDFM_BPS);	/* now set the real drive parameters! */	rqno = xdc_cmd(xdc, XDCMD_WRP, XDFUN_DRV, xd->xd_drive, 0, 0, 0, fmode);	XDC_DONE(xdc, rqno, err);	if (err) {		printf("%s: write real drive parameters failed: %s\n",			xd->sc_dev.dv_xname, xdc_e2str(err));		goto done;	}	newstate = XD_DRIVE_ONLINE;	/*	 * read bad144 table. this table resides on the first sector of the	 * last track of the disk (i.e. second cyl of "acyl" area).	 */	blk = (xd->ncyl + xd->acyl - 1) * (xd->nhead * xd->nsect) + /* last cyl */	    (xd->nhead - 1) * xd->nsect;	/* last head */	rqno = xdc_cmd(xdc, XDCMD_RD, 0, xd->xd_drive, blk, 1, xa->dvmabuf, fmode);	XDC_DONE(xdc, rqno, err);	if (err) {		printf("%s: reading bad144 failed: %s\n",			xd->sc_dev.dv_xname, xdc_e2str(err));		goto done;	}	/* check dkbad for sanity */	dkb = (struct dkbad *) xa->dvmabuf;	for (lcv = 0; lcv < 126; lcv++) {		if ((dkb->bt_bad[lcv].bt_cyl == 0xffff ||				dkb->bt_bad[lcv].bt_cyl == 0) &&		     dkb->bt_bad[lcv].bt_trksec == 0xffff)			continue;	/* blank */		if (dkb->bt_bad[lcv].bt_cyl >= xd->ncyl)			break;		if ((dkb->bt_bad[lcv].bt_trksec >> 8) >= xd->nhead)			break;		if ((dkb->bt_bad[lcv].bt_trksec & 0xff) >= xd->nsect)			break;	}	if (lcv != 126) {		printf("%s: warning: invalid bad144 sector!\n",			xd->sc_dev.dv_xname);	} else {		bcopy(xa->dvmabuf, &xd->dkb, XDFM_BPS);	}	/* XXX - Where is this and what does it do? -gwr */	dk_establish(&xd->sc_dk, &xd->sc_dev);done:	xd->state = newstate;	if (!xa->booting) {		wakeup(&xd->state);		splx(s);	}}