Exemplo n.º 1
0
/*
 * Device close processing
 */
LOCAL ER close_device( OpnCB *opncb, UINT option )
{
	ID	devid;
	DevCB	*devcb;
	INT	unitno;
	WaitQ	waiq;
	ER	ercd = E_OK;

	/* Abort all requests during processing */
	abort_allrequest(opncb);

	LockDM();

	devcb  = opncb->devcb;
	unitno = opncb->unitno;
	devid = DEVID(devcb, unitno);

	/* Multiple tasks can initiate open/close processing,
	   so ensure processing only by one task at a time. */
	if ( enterSyncWait(&devcb->syncq, &waiq) ) {
		/* Wait for synchronization for concurrent open/close */
		UnlockDM();
		SyncWaitDM();
		LockDM();
	}

	/* Is device driver call required? */
	if ( chkopen(devcb, unitno, opncb) ) {
		if ( (devcb->ddev.drvatr & TDA_OPENREQ) == 0 ) {
			goto no_drvcall;
		}
		option &= ~TD_EJECT;	/* EJECT is effective at last close */
	}
	/* Device driver call */
	UnlockDM();
	ercd = call_closefn(devcb, DEVID(devcb, unitno), option);
	LockDM();

no_drvcall:
	/* Free open management block */
	delOpnCB(opncb);

       /* Wake up task waiting for synchronization for concurrent open/close */
	leaveSyncWait(&devcb->syncq, &waiq);

	UnlockDM();

	ERCD_PRINT(("close_device ercd = %d\n", ercd));

	return ercd;
}
Exemplo n.º 2
0
/*
 * Opens a tty device.
 */
PRIVATE int tty_open(unsigned minor)
{	
	/* Assign controlling terminal. */
	if ((IS_LEADER(curr_proc)) && (curr_proc->tty == NULL_DEV))
	{
		/* tty already assigned. */
		if (tty.pgrp != NULL)
			return (-EBUSY);
		
		curr_proc->tty = DEVID(TTY_MAJOR, minor, CHRDEV);
		tty.pgrp = curr_proc;
	}
	
	return (0);
}
Exemplo n.º 3
0
int main(void)
{
	DEVID(usb_device_id);
	DEVID_FIELD(usb_device_id, match_flags);
	DEVID_FIELD(usb_device_id, idVendor);
	DEVID_FIELD(usb_device_id, idProduct);
	DEVID_FIELD(usb_device_id, bcdDevice_lo);
	DEVID_FIELD(usb_device_id, bcdDevice_hi);
	DEVID_FIELD(usb_device_id, bDeviceClass);
	DEVID_FIELD(usb_device_id, bDeviceSubClass);
	DEVID_FIELD(usb_device_id, bDeviceProtocol);
	DEVID_FIELD(usb_device_id, bInterfaceClass);
	DEVID_FIELD(usb_device_id, bInterfaceSubClass);
	DEVID_FIELD(usb_device_id, bInterfaceProtocol);
	DEVID_FIELD(usb_device_id, bInterfaceNumber);

	DEVID(hid_device_id);
	DEVID_FIELD(hid_device_id, bus);
	DEVID_FIELD(hid_device_id, group);
	DEVID_FIELD(hid_device_id, vendor);
	DEVID_FIELD(hid_device_id, product);

	DEVID(ieee1394_device_id);
	DEVID_FIELD(ieee1394_device_id, match_flags);
	DEVID_FIELD(ieee1394_device_id, vendor_id);
	DEVID_FIELD(ieee1394_device_id, model_id);
	DEVID_FIELD(ieee1394_device_id, specifier_id);
	DEVID_FIELD(ieee1394_device_id, version);

	DEVID(pci_device_id);
	DEVID_FIELD(pci_device_id, vendor);
	DEVID_FIELD(pci_device_id, device);
	DEVID_FIELD(pci_device_id, subvendor);
	DEVID_FIELD(pci_device_id, subdevice);
	DEVID_FIELD(pci_device_id, class);
	DEVID_FIELD(pci_device_id, class_mask);

	DEVID(ccw_device_id);
	DEVID_FIELD(ccw_device_id, match_flags);
	DEVID_FIELD(ccw_device_id, cu_type);
	DEVID_FIELD(ccw_device_id, cu_model);
	DEVID_FIELD(ccw_device_id, dev_type);
	DEVID_FIELD(ccw_device_id, dev_model);

	DEVID(ap_device_id);
	DEVID_FIELD(ap_device_id, dev_type);

	DEVID(css_device_id);
	DEVID_FIELD(css_device_id, type);

	DEVID(serio_device_id);
	DEVID_FIELD(serio_device_id, type);
	DEVID_FIELD(serio_device_id, proto);
	DEVID_FIELD(serio_device_id, id);
	DEVID_FIELD(serio_device_id, extra);

	DEVID(acpi_device_id);
	DEVID_FIELD(acpi_device_id, id);
	DEVID_FIELD(acpi_device_id, cls);
	DEVID_FIELD(acpi_device_id, cls_msk);

	DEVID(pnp_device_id);
	DEVID_FIELD(pnp_device_id, id);

	DEVID(pnp_card_device_id);
	DEVID_FIELD(pnp_card_device_id, devs);

	DEVID(pcmcia_device_id);
	DEVID_FIELD(pcmcia_device_id, match_flags);
	DEVID_FIELD(pcmcia_device_id, manf_id);
	DEVID_FIELD(pcmcia_device_id, card_id);
	DEVID_FIELD(pcmcia_device_id, func_id);
	DEVID_FIELD(pcmcia_device_id, function);
	DEVID_FIELD(pcmcia_device_id, device_no);
	DEVID_FIELD(pcmcia_device_id, prod_id_hash);

	DEVID(of_device_id);
	DEVID_FIELD(of_device_id, name);
	DEVID_FIELD(of_device_id, type);
	DEVID_FIELD(of_device_id, compatible);

	DEVID(vio_device_id);
	DEVID_FIELD(vio_device_id, type);
	DEVID_FIELD(vio_device_id, compat);

	DEVID(input_device_id);
	DEVID_FIELD(input_device_id, flags);
	DEVID_FIELD(input_device_id, bustype);
	DEVID_FIELD(input_device_id, vendor);
	DEVID_FIELD(input_device_id, product);
	DEVID_FIELD(input_device_id, version);
	DEVID_FIELD(input_device_id, evbit);
	DEVID_FIELD(input_device_id, keybit);
	DEVID_FIELD(input_device_id, relbit);
	DEVID_FIELD(input_device_id, absbit);
	DEVID_FIELD(input_device_id, mscbit);
	DEVID_FIELD(input_device_id, ledbit);
	DEVID_FIELD(input_device_id, sndbit);
	DEVID_FIELD(input_device_id, ffbit);
	DEVID_FIELD(input_device_id, swbit);

	DEVID(eisa_device_id);
	DEVID_FIELD(eisa_device_id, sig);

	DEVID(parisc_device_id);
	DEVID_FIELD(parisc_device_id, hw_type);
	DEVID_FIELD(parisc_device_id, hversion);
	DEVID_FIELD(parisc_device_id, hversion_rev);
	DEVID_FIELD(parisc_device_id, sversion);

	DEVID(sdio_device_id);
	DEVID_FIELD(sdio_device_id, class);
	DEVID_FIELD(sdio_device_id, vendor);
	DEVID_FIELD(sdio_device_id, device);

	DEVID(ssb_device_id);
	DEVID_FIELD(ssb_device_id, vendor);
	DEVID_FIELD(ssb_device_id, coreid);
	DEVID_FIELD(ssb_device_id, revision);

	DEVID(bcma_device_id);
	DEVID_FIELD(bcma_device_id, manuf);
	DEVID_FIELD(bcma_device_id, id);
	DEVID_FIELD(bcma_device_id, rev);
	DEVID_FIELD(bcma_device_id, class);

	DEVID(virtio_device_id);
	DEVID_FIELD(virtio_device_id, device);
	DEVID_FIELD(virtio_device_id, vendor);

	DEVID(hv_vmbus_device_id);
	DEVID_FIELD(hv_vmbus_device_id, guid);

	DEVID(i2c_device_id);
	DEVID_FIELD(i2c_device_id, name);

	DEVID(spi_device_id);
	DEVID_FIELD(spi_device_id, name);

	DEVID(dmi_system_id);
	DEVID_FIELD(dmi_system_id, matches);

	DEVID(platform_device_id);
	DEVID_FIELD(platform_device_id, name);

	DEVID(mdio_device_id);
	DEVID_FIELD(mdio_device_id, phy_id);
	DEVID_FIELD(mdio_device_id, phy_id_mask);

	DEVID(zorro_device_id);
	DEVID_FIELD(zorro_device_id, id);

	DEVID(isapnp_device_id);
	DEVID_FIELD(isapnp_device_id, vendor);
	DEVID_FIELD(isapnp_device_id, function);

	DEVID(ipack_device_id);
	DEVID_FIELD(ipack_device_id, format);
	DEVID_FIELD(ipack_device_id, vendor);
	DEVID_FIELD(ipack_device_id, device);

	DEVID(amba_id);
	DEVID_FIELD(amba_id, id);
	DEVID_FIELD(amba_id, mask);

	DEVID(mips_cdmm_device_id);
	DEVID_FIELD(mips_cdmm_device_id, type);

	DEVID(x86_cpu_id);
	DEVID_FIELD(x86_cpu_id, feature);
	DEVID_FIELD(x86_cpu_id, family);
	DEVID_FIELD(x86_cpu_id, model);
	DEVID_FIELD(x86_cpu_id, vendor);

	DEVID(cpu_feature);
	DEVID_FIELD(cpu_feature, feature);

	DEVID(mei_cl_device_id);
	DEVID_FIELD(mei_cl_device_id, name);
	DEVID_FIELD(mei_cl_device_id, uuid);
	DEVID_FIELD(mei_cl_device_id, version);

	DEVID(rio_device_id);
	DEVID_FIELD(rio_device_id, did);
	DEVID_FIELD(rio_device_id, vid);
	DEVID_FIELD(rio_device_id, asm_did);
	DEVID_FIELD(rio_device_id, asm_vid);

	DEVID(ulpi_device_id);
	DEVID_FIELD(ulpi_device_id, vendor);
	DEVID_FIELD(ulpi_device_id, product);

	DEVID(hda_device_id);
	DEVID_FIELD(hda_device_id, vendor_id);
	DEVID_FIELD(hda_device_id, rev_id);
	DEVID_FIELD(hda_device_id, api_version);

	DEVID(fsl_mc_device_id);
	DEVID_FIELD(fsl_mc_device_id, vendor);
	DEVID_FIELD(fsl_mc_device_id, obj_type);

	return 0;
}
Exemplo n.º 4
0
/*
 * This checks for, and validates, the presence of the 460GX chipset, and sets
 * cbn_460gx to a positive value accordingly.  This function returns TRUE if
 * the chipset scan is to be stopped, or FALSE if the scan is to move on to the
 * next chipset.
 */
Bool
xf86PreScan460GX(void)
{
    pciBusInfo_t *pBusInfo;
    PCITAG tag;
    CARD32 tmp;
    int i, devno;

    /* Bus zero should already be set up */
    if (!(pBusInfo = pciBusInfo[0])) {
	cbn_460gx = -1;
	return FALSE;
    }

    /* First look for a 460GX's primary host bridge */
    tag = PCI_MAKE_TAG(0, 0x10, 0);
    if (pciReadLong(tag, PCI_ID_REG) != DEVID(INTEL, 460GX_SAC)) {
	cbn_460gx = -1;
	return FALSE;
    }

    /* Get CBN (Chipset bus number) */
    if (!(cbn_460gx = (unsigned int)pciReadByte(tag, CBN))) {
	/* Sanity check failed */
	cbn_460gx = -1;
	return TRUE;
    }

    if (pciNumBuses <= cbn_460gx)
	pciNumBuses = cbn_460gx + 1;

    /* Set up bus CBN */
    if (!pciBusInfo[cbn_460gx]) {
	pciBusInfo[cbn_460gx] = xnfalloc(sizeof(pciBusInfo_t));
	*pciBusInfo[cbn_460gx] = *pBusInfo;
    }

    tag = PCI_MAKE_TAG(cbn_460gx, 0, 0);
    if (pciReadLong(tag, PCI_ID_REG) != DEVID(INTEL, 460GX_SAC)) {
	/* Sanity check failed */
	cbn_460gx = -1;
	return TRUE;
    }

    /*
     * Find out which CBN devices the firmware thinks are present.  Of these,
     * we are only interested in devices 0x10 through 0x17.
     */
    cbdevs_460gx = pciReadLong(tag, DEVNPRES);

    for (i = 0, devno = 0x10;  devno <= 0x17;  i++, devno++) {
	tag = PCI_MAKE_TAG(cbn_460gx, devno, 0);
	if (pciReadLong(tag, PCI_ID_REG) != DEVID(INTEL, 460GX_SAC)) {
	    /* Sanity check failed */
	    cbn_460gx = -1;
	    return TRUE;
	}

	if (devno == 0x10)
	    iord_460gx = pciReadWord(tag, IORD);

	busno_460gx[i] = (unsigned int)pciReadByte(tag, BUSNO);
	subno_460gx[i] = (unsigned int)pciReadByte(tag, SUBNO);
	pcis_460gx[i] = pciReadByte(tag, PCIS);
	ior_460gx[i] = pciReadByte(tag, IOR);

	has_err_460gx[i] = err_460gx[i] = 0;	/* Insurance */

	tag = PCI_MAKE_TAG(cbn_460gx, devno, 1);
	tmp = pciReadLong(tag, PCI_ID_REG);
	switch (tmp) {
	case DEVID(INTEL, 460GX_PXB):
	case DEVID(INTEL, 460GX_WXB):
	    if (cbdevs_460gx & (1 << devno)) {
		/* Sanity check failed */
		cbn_460gx = -1;
		return TRUE;
	    }

	    /*
	     * XXX  I don't have WXB docs, but PCI register dumps indicate that
	     * the registers we are interested in are consistent with those of
	     * the PXB.
	     */
	    err_460gx[i] = pciReadByte(tag, ERRCMD);
	    has_err_460gx[i] = 1;
	    break;

	case DEVID(INTEL, 460GX_GXB_1):
	    if (cbdevs_460gx & (1 << devno)) {
		/* Sanity check failed */
		cbn_460gx = -1;
		return TRUE;
	    }

	    /*
	     * XXX  GXB isn't documented to have an ERRCMD register, nor any
	     * other means of failing master aborts.  For now, assume master
	     * aborts are always allowed to complete normally.
	     */
	    break;

	default:
	    if (((CARD16)(tmp + 1U) <= (CARD16)1U) &&
		(cbdevs_460gx & (1U << devno)))
		break;
	    /* Sanity check failed */
	    cbn_460gx = -1;
	    return TRUE;
	}
    }

    /* Allow master aborts to complete normally */
    for (i = 0, devno = 0x10;  devno <= 0x17;  i++, devno++) {
	if (!(err_460gx[i] & 0x01))
	    continue;

	pciWriteByte(PCI_MAKE_TAG(cbn_460gx, devno, 1),
		     ERRCMD, err_460gx[i] & ~0x01);
    }

    /*
     * The 460GX spec says that any access to busses higher than CBN will be
     * master-aborted.  It seems possible however that this is not the case in
     * all 460GX implementations.  For now, limit the bus scan to CBN, unless
     * we have already found a higher bus number.
     */
    for (i = 0;  subno_460gx[i] < cbn_460gx;  ) {
	if (++i < 8)
	    continue;

	pciMaxBusNum = cbn_460gx + 1;
	break;
    }

    return TRUE;
}
Exemplo n.º 5
0
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Nanvix. If not, see <http://www.gnu.org/licenses/>.
 */

#include <nanvix/const.h>
#include <nanvix/dev.h>
#include <nanvix/klib.h>
#include <sys/types.h>
#include <stdarg.h>

/**
 * @brief Kernel's output device.
 */
PUBLIC dev_t kout = DEVID(NULL_MAJOR, 0, CHRDEV);

/**
 * @brief Changes kernel's output device.
 * 
 * @param dev New output device.
 */
PUBLIC void chkout(dev_t dev)
{	
	ssize_t n;                 /* Number of bytes to be flushed. */
	char buffer[KBUFFER_SIZE]; /* Temporary buffer.              */
	
	kout = dev;
	
	/* Flush the content of kernel log. */
	n = klog_read(0, buffer, KLOG_SIZE);
Exemplo n.º 6
0
/*
 * Request for starting input/output to device
 */
EXPORT ID knl_request( ID dd, W start, VP buf, W size, TMO tmout, INT cmd )
{
	EXCFN	execfn;
	VP	exinf;
#if TA_GP
	VP	gp;
#endif
	OpnCB	*opncb;
	DevCB	*devcb;
	ReqCB	*reqcb;
	UINT	m;
	ER	ercd;

	LockDM();

	if ( start <= -0x00010000 && start >= -0x7fffffff ) {
		m = 0; /* Ignore open mode */
	} else {
		m = ( cmd == TDC_READ )? TD_READ: TD_WRITE;
	}
	ercd = knl_check_devdesc(dd, m, &opncb);
	if ( ercd < E_OK ) {
		goto err_ret1;
	}

	devcb = opncb->devcb;
	execfn = (EXCFN)devcb->ddev.execfn;
	exinf = devcb->ddev.exinf;
#if TA_GP
	gp = devcb->ddev.gp;
#endif

	/* Get request management block */
	reqcb = newReqCB(opncb);
	if ( reqcb == NULL ) {
		ercd = E_LIMIT;
		goto err_ret1;
	}

	/* Set request packet */
	reqcb->req.next   = NULL;
	reqcb->req.exinf  = NULL;
	reqcb->req.devid  = DEVID(devcb, opncb->unitno);
	reqcb->req.cmd    = cmd;
	reqcb->req.abort  = FALSE;
	reqcb->req.start  = start;
	reqcb->req.size   = size;
	reqcb->req.buf    = buf;
	reqcb->req.asize  = 0;
	reqcb->req.error  = 0;

	/* Indicate that it is during processing */
	reqcb->tskid = tk_get_tid_impl();

	UnlockDM();

	/* Device driver call */
	DISABLE_INTERRUPT;
	knl_ctxtsk->sysmode++;
	ENABLE_INTERRUPT;
#if TA_GP
	ercd = CallDeviceDriver(&reqcb->req, tmout, exinf, 0, (FP)execfn, gp);
#else
	ercd = (*execfn)(&reqcb->req, tmout, exinf);
#endif
	DISABLE_INTERRUPT;
	knl_ctxtsk->sysmode--;
	ENABLE_INTERRUPT;

	LockDM();

	/* Indicate that it is not during processing */
	reqcb->tskid = 0;

	/* If there is an abort completion wait task,
	   notify abort completion */
	if ( opncb->abort_tskid > 0 && --opncb->abort_cnt == 0 ) {
		tk_sig_sem_impl(opncb->abort_semid, 1);
	}

	if ( ercd < E_OK ) {
		goto err_ret2;
	}

	UnlockDM();

	return REQID(reqcb);

err_ret2:
	knl_delReqCB(reqcb);
err_ret1:
	UnlockDM();
	DEBUG_PRINT(("knl_request ercd = %d\n", ercd));
	return ercd;
}
Exemplo n.º 7
0
/*
 * Device close processing
 */
EXPORT ER knl_close_device( OpnCB *opncb, UINT option )
{
	CLSFN	closefn;
	VP	exinf;
#if TA_GP
	VP	gp;
#endif
	ID	devid;
	DevCB	*devcb;
	INT	unitno;
	ER	ercd = E_OK;

	/* Abort all requests during processing */
	abort_allrequest(opncb);

	LockDM();

	devcb  = opncb->devcb;
	unitno = opncb->unitno;
	closefn = (CLSFN)devcb->ddev.closefn;
	exinf = devcb->ddev.exinf;
#if TA_GP
	gp = devcb->ddev.gp;
#endif
	devid = DEVID(devcb, unitno);

	/* Delete semaphore for completion check of abortion */
	tk_del_sem_impl(opncb->abort_semid);

	/* Free open management block */
	knl_delOpnCB(opncb, FALSE);

	/* Is device driver call required? */
	if ( knl_chkopen(devcb, unitno) ) {
		option &= ~TD_EJECT;
		if ( (devcb->ddev.drvatr & TDA_OPENREQ) == 0 ) {
			closefn = NULL;
		}
	}

	UnlockDM();

	if ( closefn != NULL ) {
		/* Device driver call */
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode++;
		ENABLE_INTERRUPT;
#if TA_GP
		ercd = CallDeviceDriver(devid, option, exinf, 0, (FP)closefn, gp);
#else
		ercd = (*closefn)(devid, option, exinf);
#endif
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode--;
		ENABLE_INTERRUPT;
	}

	LockDM();
	/* Return open management block to FreeQue */
	QueInsert(&opncb->q, &knl_FreeOpnCB);
	UnlockDM();

#ifdef DEBUG
	if ( ercd < E_OK ) {
		DEBUG_PRINT(("knl_close_device ercd = %d\n", ercd));
	}
#endif
	return ercd;
}
Exemplo n.º 8
0
/*
 * Device open
 */
SYSCALL ID tk_opn_dev_impl( UB *devnm, UINT omode )
{
	OPNFN	openfn;
	VP	exinf;
#if TA_GP
	VP	gp;
#endif
	UB	pdevnm[L_DEVNM + 1];
	INT	unitno;
	ResCB	*rescb;
	DevCB	*devcb;
	OpnCB	*opncb;
	ER	ercd;
	ID	semid;

	unitno = knl_phydevnm(pdevnm, devnm);

	/* Get resource management information */
	rescb = knl_GetResCB();
	if ( rescb == NULL ) {
		ercd = E_CTX;
		goto err_ret1;
	}

	LockDM();

	/* Search device to open */
	devcb = knl_searchDevCB(pdevnm);
	if ( devcb == NULL || unitno > devcb->ddev.nsub ) {
		ercd = E_NOEXS;
		goto err_ret2;
	}

	/* Check open mode */
	ercd = chkopenmode(devcb, unitno, omode);
	if ( ercd < E_OK ) {
		goto err_ret2;
	}

	openfn = (OPNFN)devcb->ddev.openfn;
	exinf = devcb->ddev.exinf;
#if TA_GP
	gp = devcb->ddev.gp;
#endif

	/* Is device driver call required? */
	if ( knl_chkopen(devcb, unitno) && (devcb->ddev.drvatr & TDA_OPENREQ) == 0 ) {
		openfn = NULL;
	}

	/* Get open management block */
	opncb = newOpnCB(devcb, unitno, omode, rescb);
	if ( opncb == NULL ) {
		ercd = E_LIMIT;
		goto err_ret2;
	}

	semid = tk_cre_sem_impl(&knl_pk_csem_DM);
	if ( semid < E_OK ) {
		ercd = E_SYS;
		goto err_ret2_5;
	}
	opncb->abort_semid = semid;

	UnlockDM();

	if ( openfn != NULL ) {
		/* Device driver call */
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode++;
		ENABLE_INTERRUPT;
#if TA_GP
		ercd = CallDeviceDriver(DEVID(devcb, unitno), omode, exinf, 0,
								(FP)openfn, gp);
#else
		ercd = (*openfn)(DEVID(devcb, unitno), omode, exinf);
#endif
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode--;
		ENABLE_INTERRUPT;

		if ( ercd < E_OK ) {
			goto err_ret3;
		}
	}

	LockDM();
	opncb->resid = 1; /* Indicate that open processing is completed */
	UnlockDM();

	return DD(opncb);

err_ret3:
	LockDM();
err_ret2_5:
	knl_delOpnCB(opncb, TRUE);
err_ret2:
	UnlockDM();
err_ret1:
	DEBUG_PRINT(("tk_opn_dev_impl ercd = %d\n", ercd));
	return ercd;
}
Exemplo n.º 9
0
/*
 * Request for starting input/output to device
 */
LOCAL ID request( ID dd, D start, void *buf, INT size, TMO_U tmout,
					INT cmd, enum ReqType syncreq )
{
	ATR	drvatr;
	OpnCB	*opncb;
	DevCB	*devcb;
	ReqCB	*reqcb;
	UINT	m;
	ER	ercd;

	LockDM();

	/* Check whether there is a break request */
	ercd = check_break();
	if ( ercd < E_OK ) {
		goto err_ret1;
	}

	m = ( cmd == TDC_READ )? TD_READ: TD_WRITE;
	ercd = check_devdesc(dd, m, &opncb);
	if ( ercd < E_OK ) {
		goto err_ret1;
	}

	if ( syncreq == SyncReq ) {
		/* synchronous I/O is prohibited while there are
					pending I/O requests for completion */
		if ( opncb->nwaireq > 0 ) { ercd = E_OBJ; goto err_ret1; }
		opncb->syncreq++;
	}

	devcb = opncb->devcb;
	drvatr = devcb->ddev.drvatr;

	/* check the range of parameter value */
	if ( (drvatr & TDA_DEV_D) == 0 ) {
		if ( start > 0x7fffffff || start < (-0x7fffffff-1) ) {
			ercd = E_PAR; goto err_ret2;
		}
	}

	/* Get request management block */
	reqcb = newReqCB(opncb);
	if ( reqcb == NULL ) {
		ercd = E_LIMIT;
		goto err_ret2;
	}

	/* Set request packet */
	MEMSET(&reqcb->req, 0, sizeof(DEVREQ));
	reqcb->req.c.devid  = DEVID(devcb, opncb->unitno);
	reqcb->req.c.cmd    = cmd;
	if ( (opncb->omode & TD_NOLOCK) != 0 ) {
		reqcb->req.c.nolock = TRUE;
	}
	if ( (drvatr & TDA_DEV_D) == 0 ) {
		reqcb->req.s.start   = start;
		reqcb->req.s.size    = size;
		reqcb->req.s.buf     = buf;
	} else {
		reqcb->req.l.start_d = start;
		reqcb->req.l.size    = size;
		reqcb->req.l.buf     = buf;
	}
	ercd = tk_get_tsp(TSK_SELF, &reqcb->req.c.tskspc);
	if ( ercd < E_OK ) {
		goto err_ret3;
	}

	/* Indicate that it is during processing */
	reqcb->tskid = tk_get_tid();

	/* Device driver call */
	UnlockDM();
	ercd = call_execfn(devcb, &reqcb->req, tmout);
	LockDM();

	LockDAbort();

	/* Indicate that it is not during processing */
	reqcb->tskid = 0;

	/* If there is an abort completion wait task,
	   notify abort completion */
	if ( opncb->abort_tskid > 0 && --opncb->abort_cnt == 0 ) {
		SyncSignalDM(opncb->abort_tskid);
	}
	UnlockDAbort();

	if ( ercd < E_OK ) {
		goto err_ret3;
	}

	UnlockDM();

	return REQID(reqcb);

err_ret3:
	delReqCB(reqcb);
err_ret2:
	if ( syncreq == SyncReq ) {
		opncb->syncreq--;
	}
err_ret1:
	UnlockDM();
	DEBUG_PRINT(("request ercd = %d\n", ercd));
	return ercd;
}
Exemplo n.º 10
0
/*
 * Device open
 */
EXPORT ID _tk_opn_dev( CONST UB *devnm, UINT omode )
{
	UB	pdevnm[L_DEVNM + 1];
	INT	unitno;
	ResCB	*rescb;
	DevCB	*devcb;
	OpnCB	*opncb;
	WaitQ	waiq;
	ER	ercd;

	ercd = ChkSpaceBstrR(devnm, 0);
	if ( ercd < E_OK ) {
		goto err_ret1;
	}

	unitno = phydevnm(pdevnm, devnm);

	/* Get resource management information */
	rescb = GetResCB(DEVICE_SVC, TSK_SELF);
	if ( rescb == NULL ) {
		ercd = E_CTX;
		goto err_ret1;
	}

	LockDM();

	/* Search device to open */
	devcb = searchDevCB(pdevnm);
	if ( devcb == NULL || unitno > devcb->ddev.nsub ) {
		ercd = E_NOEXS;
		goto err_ret2;
	}

	/* Check open mode */
	ercd = chkopenmode(devcb, unitno, omode);
	if ( ercd < E_OK ) {
		goto err_ret2;
	}

	/* Get open management block */
	opncb = newOpnCB(devcb, unitno, omode, rescb);
	if ( opncb == NULL ) {
		ercd = E_LIMIT;
		goto err_ret2;
	}

	/* Multiple tasks can initiate open/close processing,
	   so ensure processing only by one task at a time. */
	if ( enterSyncWait(&devcb->syncq, &waiq) ) {
		/* Wait for synchronization for concurrent open/close */
		UnlockDM();
		SyncWaitDM();
		LockDM();
	}

	/* Is device driver call required? */
	if ( ! ( chkopen(devcb, unitno, opncb) &&
				(devcb->ddev.drvatr & TDA_OPENREQ) == 0 ) ) {
		/* Device driver call */
		UnlockDM();
		ercd = call_openfn(devcb, DEVID(devcb, unitno), omode);
		LockDM();
		if ( ercd < E_OK ) {
			goto err_ret3;
		}
	}
	opncb->resid = tk_get_rid(TSK_SELF);
			/* Indicate that open processing is completed */

       /* Wake up task waiting for synchronization for concurrent open/close */
	leaveSyncWait(&devcb->syncq, &waiq);
	UnlockDM();

	return DD(opncb);

err_ret3:
	delOpnCB(opncb);
	leaveSyncWait(&devcb->syncq, &waiq);
err_ret2:
	UnlockDM();
err_ret1:
	DEBUG_PRINT(("_tk_opn_dev ercd = %d\n", ercd));
	return ercd;
}