Example #1
0
static cam_status
pmpregister(struct cam_periph *periph, void *arg)
{
	struct pmp_softc *softc;
	struct ccb_getdev *cgd;

	cgd = (struct ccb_getdev *)arg;
	if (periph == NULL) {
		printf("pmpregister: periph was NULL!!\n");
		return(CAM_REQ_CMP_ERR);
	}

	if (cgd == NULL) {
		printf("pmpregister: no getdev CCB, can't register device\n");
		return(CAM_REQ_CMP_ERR);
	}

	softc = (struct pmp_softc *)malloc(sizeof(*softc), M_DEVBUF,
	    M_NOWAIT|M_ZERO);

	if (softc == NULL) {
		printf("pmpregister: Unable to probe new device. "
		       "Unable to allocate softc\n");				
		return(CAM_REQ_CMP_ERR);
	}
	periph->softc = softc;

	softc->pm_pid = ((uint32_t *)&cgd->ident_data)[0];
	softc->pm_prv = ((uint32_t *)&cgd->ident_data)[1];
	TASK_INIT(&softc->sysctl_task, 0, pmpsysctlinit, periph);

	xpt_announce_periph(periph, NULL);

	/*
	 * Add async callbacks for bus reset and
	 * bus device reset calls.  I don't bother
	 * checking if this fails as, in most cases,
	 * the system will function just fine without
	 * them and the only alternative would be to
	 * not attach the device on failure.
	 */
	xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE |
		AC_SCSI_AEN, pmpasync, periph, periph->path);

	/*
	 * Take an exclusive refcount on the periph while pmpstart is called
	 * to finish the probe.  The reference will be dropped in pmpdone at
	 * the end of probe.
	 */
	(void)cam_periph_acquire(periph);
	xpt_hold_boot();
	softc->state = PMP_STATE_PORTS;
	softc->events = PMP_EV_RESCAN;
	xpt_schedule(periph, CAM_PRIORITY_DEV);

	return(CAM_REQ_CMP);
}
Example #2
0
static void
pmpasync(void *callback_arg, u_int32_t code,
	struct cam_path *path, void *arg)
{
	struct cam_periph *periph;
	struct pmp_softc *softc;

	periph = (struct cam_periph *)callback_arg;
	switch (code) {
	case AC_FOUND_DEVICE:
	{
		struct ccb_getdev *cgd;
		cam_status status;
 
		cgd = (struct ccb_getdev *)arg;
		if (cgd == NULL)
			break;

		if (cgd->protocol != PROTO_SATAPM)
			break;

		/*
		 * Allocate a peripheral instance for
		 * this device and start the probe
		 * process.
		 */
		status = cam_periph_alloc(pmpregister, pmponinvalidate,
					  pmpcleanup, pmpstart,
					  "pmp", CAM_PERIPH_BIO,
					  cgd->ccb_h.path, pmpasync,
					  AC_FOUND_DEVICE, cgd);

		if (status != CAM_REQ_CMP
		 && status != CAM_REQ_INPROG)
			printf("pmpasync: Unable to attach to new device "
				"due to status 0x%x\n", status);
		break;
	}
	case AC_SCSI_AEN:
	case AC_SENT_BDR:
	case AC_BUS_RESET:
		softc = (struct pmp_softc *)periph->softc;
		cam_periph_async(periph, code, path, arg);
		if (code == AC_SCSI_AEN)
			softc->events |= PMP_EV_RESCAN;
		else
			softc->events |= PMP_EV_RESET;
		if (code == AC_SCSI_AEN && softc->state != PMP_STATE_NORMAL)
			break;
		xpt_hold_boot();
		pmpfreeze(periph, softc->found);
		if (code == AC_SENT_BDR || code == AC_BUS_RESET)
			softc->found = 0; /* We have to reset everything. */
		if (softc->state == PMP_STATE_NORMAL) {
			softc->state = PMP_STATE_PRECONFIG;
			cam_periph_acquire(periph);
			xpt_schedule(periph, CAM_PRIORITY_DEV);
		} else
			softc->restart = 1;
		break;
	default:
		cam_periph_async(periph, code, path, arg);
		break;
	}
}