コード例 #1
0
ファイル: ldevent.c プロジェクト: Nat-Stein/abstract_dots_NS
void
ldevent_plexon_low(EVENT *evp, int flag)
{
	int scrb_msg0 = 0, scrb_msg1= 0;
	unsigned eflags;
	
	/*
	 * Must be done with interrupts disabled.  Critical
	 * sections with interrupt routine, or scheduling of other processes
	 * which might call ldevent().
	 */
	if((eflags= pswget()) & INTR_IF) InterruptDisable();
	if(!flag) {
	    i_b->bevent[i_b->evlx]= *evp;
	    if(++i_b->evlx >= EBUFNUM) i_b->evlx= 0;
	    if(i_b->evlx == i_b->evdx) scrb_msg0= SC_EVERR;
	    if(i_b->evlx == i_b->evdump) {    /* time to set new dump? */

		i_b->evdump += EDUMPINC;
		if(i_b->evdump >= EBUFNUM) i_b->evdump -= EBUFNUM;

		/*
		 * If writing to disk, alert scribe.
		 */
		if(i_b->i_flags & I_EOUT) scrb_msg1= SC_EDUMP;

	    }
	}

	/* 
	 * Send ecode to Plexon box.
	 * Don't send negative ecodes, because only lower 15 bits of 
	 * code can be sent to Plexon box.  Critical section- this must be done
	 * high priority to avoid conflict with other places events are sent
	 * to plexon box.  Don't send ecode directly to Plexon box from here-
	 * just buffer it.  This lets high priority ecodes have precendence.
	 */ 
	if( (evp->e_code >= 0) ) {
		i_b->pl_lopri[i_b->pl_lolx]= evp->e_code;
		if(++i_b->pl_lolx >= PL_MAXCODES) i_b->pl_lolx= 0;
		if(i_b->pl_lolx == i_b->pl_lodx)
		    rxerr("Plexon lo pri buffer overflow"); /* overflow error */
	}

	if(eflags & INTR_IF) InterruptEnable();
	if(scrb_msg0) r_sendmsg(SCRB, scrb_msg0);
	if(scrb_msg1) r_sendmsg(SCRB, scrb_msg1);
}
コード例 #2
0
ファイル: mdriver.c プロジェクト: vocho/openqnx
static const struct sigevent *
md_intr(void *d, int id) {
	struct mdriver_entry *md = d;
	int					r;

	if(md->intr != _NTO_INTR_SPARE) {
		InterruptDisable();
		r = md->handler(MDRIVER_PROCESS, md->data);
		InterruptEnable();
		if(r != 0) {
			md->intr = _NTO_INTR_SPARE;
			SIGEV_THREAD_INIT(&sigev, md_detach, md, &attr);
			return &sigev;
		}	
	}	
	return NULL;
}
コード例 #3
0
static T_uezError LPC17xx_40xx_SSP_TransferNoBlock(
        void *aWorkspace,
        SPI_Request *aRequest,
        T_spiCompleteCallback aCallback,
        void *aCallbackWorkspace)
{
    T_LPC17xx_40xx_SSP_Workspace *aW = (T_LPC17xx_40xx_SSP_Workspace *)aWorkspace;
    T_LPC17xx_40xx_SSP_Registers *p = aW->iReg;

    // This routine only works with transfer of 8 bits or lower
    if (aRequest->iBitsPerTransfer > 8)
        return UEZ_ERROR_INVALID_PARAMETER;

    // Disable any potential SSP interrupts
    InterruptDisable(aW->iIRQChannel);

    aRequest->iNumTransferredOut = 0;
    aRequest->iNumTransferredIn = 0;

    // Setup the callback and the parameters
    aW->iCompleteCallback = aCallback;
    aW->iCompleteCallbackWorkspace = aCallbackWorkspace;
    aW->iRequest = aRequest;

    // Setup SSP for this configuration
    ISSPConfig(aW, aRequest);

    // Start SSP
    ISSPStart(aRequest);

    // Note we are in the middle of a transaction
    aW->iIsBusy = ETrue;

    // Allow receive half full, receive idle, and transmit half empty interrupts
    p->iIMSC = SSP_RTIM|SSP_RXIM|SSP_TXIM;

    // Prime the pump and output in an amount of data
    // On interrupting, we'll feed in the data
    ISSPOutput(aW);

    // Now allow processing of the interrupts (which probably just occurred)
    InterruptEnable(aW->iIRQChannel);

    return UEZ_ERROR_NONE;
}
コード例 #4
0
ファイル: fam_pte.c プロジェクト: vocho/openqnx
void
fam_pte_asid_release(ADDRESS *adp) {
	int		flush = 0;

	// Have to do the following atomically, so that an interrupt can't
	// come in and invalidate the asid on us.
	InterruptDisable();
	if(adp->cpu.asid != PPC_INVALID_ASID) {
		asid_map[adp->cpu.asid] = NULL;
		adp->cpu.asid = PPC_INVALID_ASID;
		flush = 1;
	}
	InterruptEnable();
	if(flush) {
		ppc_tlbia();
		ppc_isync();
	}
}
コード例 #5
0
ファイル: lpt_lib.cpp プロジェクト: BoonieBear/7000m
// Function: LPT_IntAEnable()
//   Enable the interrupt.
// Parameters:
//   hLPT [in] handle to the card as received from LPT_Open.
//   funcIntHandler [in] The call back function to be called upon interrupt.
// Return Value:
//   TRUE if the interrupt was successfully enabled. FALSE otherwise.
BOOL LPT_IntAEnable (LPT_HANDLE hLPT, LPT_IntA_HANDLER funcIntHandler)
{
    DWORD dwStatus;

    // Check if interrupt is already enabled
    if (hLPT->IntA.hThread)
        return FALSE;

    // Calls WD_IntEnable() and creates an interrupt handler thread
    hLPT->IntA.funcIntHandler = funcIntHandler;
    dwStatus = InterruptEnable(&hLPT->IntA.hThread, hLPT->hWD, &hLPT->IntA.Int, LPT_IntAHandler, (PVOID) hLPT);
    if (dwStatus)
    {
        sprintf(LPT_ErrorString, "InterruptEnable() failed with status 0x%lx - %s\n",
            dwStatus, Stat2Str(dwStatus));
        return FALSE;
    }

    return TRUE;
}
コード例 #6
0
ファイル: LPC2478_GPDMA.c プロジェクト: pixma/uEZ
/*---------------------------------------------------------------------------*
* Routine:  LPC2478_GPDMA_Enable
*---------------------------------------------------------------------------*
* Description:
*      Enable GPDMA controller and register interrupt handler.
* Inputs:
*      void *aW                    -- Particular GPDMA workspace
* Outputs:
*      T_uezError                  -- Error code
*---------------------------------------------------------------------------*/
static void LPC2478_GPDMA_Enable(void *aWorkspace)
{
    (void)aWorkspace;

    // Increase number of G_opened channels.
    G_opened++;

    // Enable peripheral power
    PCONP |= PCONP_PCGPDMA;

    // Was registered already?
    if(EFalse == InterruptIsRegistered(INTERRUPT_CHANNEL_GP_DMA)) {
        // Enable interrupt.
        InterruptRegister(INTERRUPT_CHANNEL_GP_DMA, (TISRFPtr)IGPDMA, INTERRUPT_PRIORITY_NORMAL, "GPDMA");
        InterruptEnable(INTERRUPT_CHANNEL_GP_DMA);
    }

    // Enable GPDMA by writing ENABLE bit.
    // Always little-endian.
    DMACConfiguration = DMACConfiguration_E;
}
コード例 #7
0
ファイル: LPC1756_Timer.c プロジェクト: FutureDesigns/uEZ
/*---------------------------------------------------------------------------*
 * Routine:  LPC247x_Timer_SetMatchCallback
 *---------------------------------------------------------------------------*
 * Description:
 *      Setup a callback routine for this timer on one of the match
 *      registers.  The callback is called when a match occurs and an
 *      interrupt occurs.  The callback is called from within the ISR.
 * Inputs:
 *      void *aWorkspace -- Timer workspace
 *      TUInt8 aMatchRegister -- Which match register to set callback
 *      T_Timer_Callback aCallbackFunc -- Function to call, or 0 to clear.
 *      void *aCallbackWorkspace -- Workspace to pass to callback
 * Outputs:
 *      T_uezError -- UEZ_ERROR_ILLEGAL_PARAMETER if match register is out
 *          of range.
 *---------------------------------------------------------------------------*/
static T_uezError LPC1756_Timer_SetMatchCallback(
        void *aWorkspace,
        TUInt8 aMatchRegister,
        T_HALTimer_Callback aCallbackFunc,
        void *aCallbackWorkspace)
{
    T_LPC1756_Timer_Workspace *p = (T_LPC1756_Timer_Workspace *)aWorkspace;
    TBool any;
    TUInt8 i;

    // Determine if legal match register
    if (aMatchRegister >= 4)
        return UEZ_ERROR_ILLEGAL_PARAMETER;

    // Set the callback (which can be 0 as well as an address)
    p->iCallbacks[aMatchRegister].iCallbackFunc = aCallbackFunc;
    p->iCallbacks[aMatchRegister].iCallbackWorkspace = aCallbackWorkspace;

    // Check to see if there are any callbacks
    any = EFalse;
    for (i = 0; i < 4; i++) {
        if (p->iCallbacks[i].iCallbackFunc) {
            any = ETrue;
            break;
        }
    }

    // Register or deregister the interrupt
    if (any) {
        // Register if not already registered
        if (!InterruptIsRegistered(p->iInfo->iVector))
            InterruptRegister(p->iInfo->iVector, p->iInfo->iISR,
                    INTERRUPT_PRIORITY_HIGH, p->iInfo->iName);
        InterruptEnable(p->iInfo->iVector);
    } else {
        // No one registered anymore, turn off this callback (but leave registered)
        InterruptDisable(p->iInfo->iVector);
    }
    return UEZ_ERROR_NONE;
}
コード例 #8
0
/*---------------------------------------------------------------------------*
 * Routine:  ExternalInterrupt_NXP_LPC1756_Enable
 *---------------------------------------------------------------------------*
 * Description:
 *      Enable the given external interrupt
 * Inputs:
 *      TUInt32 aChannel            -- EINT channel (0 to 3)
 * Outputs:
 *      T_uezError                   -- Error code
 *---------------------------------------------------------------------------*/
T_uezError ExternalInterrupt_NXP_LPC1756_Enable(
        void *aWorkspace,
        TUInt32 aChannel)
{
    TUInt32 irqNum;
    T_ExternalInterrupt_NXP_LPC1756_Workspace *p =
        (T_ExternalInterrupt_NXP_LPC1756_Workspace *)aWorkspace;
    T_eintCallback *p_callback;
    T_uezError error = UEZ_ERROR_NONE;

    IGrab(p);

    // Fake loop
    while (1) {
        // Is this a valid channel?
        if (aChannel >= NUM_EXTERNAL_INTERRUPTS) {
            error = UEZ_ERROR_OUT_OF_RANGE;
            break;
        }

        // Is this external interrupt available?
        p_callback = G_eintCallbacks+aChannel;
        if (!p_callback->iCallbackFunc) {
            error = UEZ_ERROR_NOT_FOUND;
            break;
        }

        // Disable it
        irqNum = EINT0_IRQn+aChannel;
        InterruptEnable(irqNum);

        // Do not loop
        break;
    }

    IRelease(p);

    return error;
}
コード例 #9
0
ファイル: vmm_aspace.c プロジェクト: vocho/openqnx
void 
vmm_aspace(PROCESS *actprp, PROCESS **pactprp) {
	ADDRESS					*adp;

	if((adp = actprp->memory)) {
		InterruptDisable();
		SPINLOCK(&asid_spin);
		if(adp->cpu.asid > VM_ASID_BOUNDARY) {
			// later move it out for minimize int disable time
			alloc_asid(adp); 
		}
		SPINUNLOCK(&asid_spin);
		smp_tlb_sync(actprp);

		// Set the ASID
		out32(SH_MMR_CCN_PTEH, 
				(in32(SH_MMR_CCN_PTEH) & ~VM_ASID_MASK)  | adp->cpu.asid);
		// Set the page table
		out32(SH_MMR_CCN_TTB, (uintptr_t)adp->cpu.pgdir);
		*pactprp = actprp;

		InterruptEnable();
	}
}
コード例 #10
0
ファイル: i386_video.c プロジェクト: vocho/qnxpkgsrcmirror
_X_EXPORT void
xf86EnableInterrupts()
{
	InterruptEnable();
	return;
}
コード例 #11
0
ファイル: LPC1768_Serial.c プロジェクト: FutureDesigns/uEZ
/*---------------------------------------------------------------------------*
 * Routine:  SerialEnable
 *---------------------------------------------------------------------------*
 * Description:
 *      Enable serial processing on this port.
 * Inputs:
 *      T_serialPort aPort        -- Serial port to enable
 * Outputs:
 *      T_uezError                 -- Error code
 *---------------------------------------------------------------------------*/
T_uezError LPC1768_Serial_Activate(void *aWorkspace)
{
    T_Serial_LPC1768_Workspace *p = (T_Serial_LPC1768_Workspace *)aWorkspace;
    InterruptEnable(p->iInfo->iInterruptChannel);
    return UEZ_ERROR_NONE;
}
コード例 #12
0
int hsmci_init (SIM_HBA *hba)
{
	CONFIG_INFO	*cfg;
	SIM_MMC_EXT	*ext;
	hsmci_ext_t	*hsmci = NULL;
	uintptr_t	base;

	ext = (SIM_MMC_EXT *)hba->ext;
	cfg = (CONFIG_INFO *)&hba->cfg;
	hba->verbosity = 4;

	if (!ext->opts) {
		slogf (_SLOGC_SIM_MMC, _SLOG_ERROR, "MMC: missing board-specific options\n");
		goto ARGSERR;
	}

	if ((hsmci = calloc(1, sizeof(hsmci_ext_t))) == NULL) {
		slogf (_SLOGC_SIM_MMC, _SLOG_ERROR, "MMC: alloc memory failed\n");
		goto ERR;
	}

	cfg->MemLength[0] = 0x1000;
	cfg->NumMemWindows = 1;
	cfg->MemBase[0] = cfg->IOPort_Base[0];

	base = (uintptr_t)mmap_device_memory(NULL, cfg->MemLength[0],
		PROT_READ | PROT_WRITE | PROT_NOCACHE, MAP_SHARED, cfg->MemBase[0]);

	if (base == (uintptr_t)MAP_FAILED) {
		slogf (_SLOGC_SIM_MMC, _SLOG_ERROR, "MMC: mmap_device_memory failed\n");
		goto ERR;
	}

	hsmci->clock     = 133000000;
	hsmci->base      = base;
	hsmci->hba       = hba;
	ext->handle    = hsmci;
	ext->clock     = hsmci->clock;
	ext->detect    = _hsmci_detect;
	ext->powerup   = _hsmci_powerup;
	ext->powerdown = _hsmci_powerdown;
	ext->cfg_bus   = _hsmci_cfg_bus;
	ext->set_clock = _hsmci_clock;
	ext->set_blksz = _hsmci_block_size;
	ext->interrupt = _hsmci_interrupt;
	ext->command   = _hsmci_command;
	ext->setup_dma = _hsmci_setup_dma;
	ext->dma_done  = _hsmci_dma_done;
	ext->setup_pio = _hsmci_setup_pio;
	ext->pio_done  = _hsmci_pio_done;
	ext->shutdown  = _hsmci_shutdown;

	/* Parse options */
	hsmci->port = -1;
	hsmci->blksz = BLK_LENGTH;
	hsmci->slot = 0;

	/* Hardcode DMAC controller base address according to G45 datasheet
	 * since this driver is specifically for G45 SoC */
	hsmci->dbase = DMAC_BASE;

	if (!ext->opts)
		goto ARGSERR;

	if (hsmci_args(hba, ext->opts) == -1)
		goto ARGSERR;

	/*
	 * Set Src/Dst Request peripheral identifier SRC_PER/DST_PER
	 * handshaking interface # according to Table 41-1 DMA Channel Definition
	 * According to datasheet Table 35-2, the I/O line of mci0_da0 is pa2.
	 * According to datasheet Table 35-2, the I/O line of mci1_da0 is pa23.
	 */
	if (hsmci->port == 0) {
		hsmci->dintf = 0;
		hsmci->da0_mask = (1<<2);
	} else {
		hsmci->dintf=13;
		hsmci->da0_mask = (1<<23);
	}

	/* Map G45 PIOA for polling busy signal */
	pioa_pdsr = (uint32_t *)mmap_device_memory(NULL, 4,
		PROT_READ | PROT_WRITE | PROT_NOCACHE, MAP_SHARED, PIOA_PDSR);

	if (pioa_pdsr == (uint32_t *)MAP_FAILED) {
		slogf (_SLOGC_SIM_MMC, _SLOG_ERROR, "MMC: mmap_device_memory failed\n");
		goto ERR;
	}

	if ( (uintptr_t) MAP_FAILED == ( hsmci->pio_base = mmap_device_io( AT91SAM9G45_PIO_SIZE, AT91SAM9G45_PIOD_BASE ) ) ) {
        slogf( _SLOGC_SIM_MMC, _SLOG_ERROR, "MMC: mmap_device_io for PIOD_PDSR failed" );
        goto ERR;
    }

    /* Configure CD and WP PIO */
    InterruptDisable();
#define CFG_PIO(reg)    out32( hsmci->pio_base + (reg), AT91SAM9G45_MCI_PIO_BITS )
    CFG_PIO( AT91SAM9G45_PIO_PER );     /* Ensable PIO */
    CFG_PIO( AT91SAM9G45_PIO_ODR );     /* Disable output */
    CFG_PIO( AT91SAM9G45_PIO_IFDR );        /* Disable glitch input filter */
    CFG_PIO( AT91SAM9G45_PIO_CODR );        /* Clear output data */
    CFG_PIO( AT91SAM9G45_PIO_IDR );     /* Disable interrupt */
    CFG_PIO( AT91SAM9G45_PIO_MDDR );        /* Disable multi-driver */
    CFG_PIO( AT91SAM9G45_PIO_PUER );        /* Enable pull-up */
    CFG_PIO( AT91SAM9G45_PIO_OWDR );        /* Output write disable */
#undef CFG_PIO
    InterruptEnable();

    /* Configure capacity of controller */
	ext->hccap |= MMC_HCCAP_BW1 | MMC_HCCAP_BW4 | MMC_HCCAP_DMA | MMC_HCCAP_BW8 | MMC_HCCAP_HS;

	// Use the flag MMC_HCCAP_NOCD_BUSY to inform the MMCSD stack that this hardware has R1B bug
//	ext->hccap |= MMC_HCCAP_BW1 | MMC_HCCAP_BW4 | MMC_HCCAP_DMA | MMC_HCCAP_BW8 | MMC_HCCAP_HS | MMC_HCCAP_NOCD_BUSY;

	/* Disable the controller and soft reset */
	WRITE32(MCI_CR, SWRST | PWSDIS);
	delay (100);
	WRITE32(MCI_CR, MCIDIS | PWSDIS);

	/* Disable DMA */
	WRITE32(MCI_DMA, (READ32(MCI_DMA) & (~(DMAEN))));

	/* Enable the controller */
	WRITE32(MCI_CR, MCIEN | PWSDIS);
	WRITE32(MCI_IDR, 0xffffffff);

	/* Set Timeout to Max */
	WRITE32(MCI_DTOR, 0x7f);

	/* Use the lowest baudrate */
	WRITE32 (MCI_MR, 0xff | WRPROOF| RDPROOF);

	hsmci->dmac_dev = dmac_init(hsmci);

	if (hsmci->dmac_dev == NULL) {
		slogf (_SLOGC_SIM_MMC, _SLOG_ERROR, "MMC: dmafuncs init FAILED\n");
		goto ERR;
	}

	hsmci->dmac_dev->io_addr = cfg->MemBase[0] + MCI_FIFO;
	hsmci->dmac_dev->blksz = hsmci->blksz;

	/* Select slot, set bus to 1 bit */
	WRITE32 (MCI_SDCR, hsmci->slot);

	if (!cfg->Description[0])
		strncpy(cfg->Description, "Atmel HSMCI ", sizeof(cfg->Description));

   if ( (uintptr_t) MAP_FAILED == ( hsmci->pmc_base = mmap_device_io(PMC_SIZE, PMC_BASE) ) ) {
        slogf( _SLOGC_SIM_MMC, _SLOG_ERROR, "MMC: mmap_device_io for PMC failed" );
        goto ERR;
    }

	return (MMC_SUCCESS);

ARGSERR:
	printf("\nImproper board-specific options used. Accepting args: \n");
	printf("    port=#       The MCI port been used (0 or 1)\n");
	printf("NOTE:\n");
	printf("    1. The args are seperated by colon ':'\n");
	printf("Example:\n");
	printf("at91sam9g45 port 0: devb-mmcsd-at91sam9g45 mmcsd ioport=0xFFF80000,irq=11,bs=port=0\n");
	printf("at91sam9g45 port 1: devb-mmcsd-at91sam9g45 mmcsd ioport=0xFFFD0000,irq=29,bs=port=1\n");

ERR:
	if (hsmci) {
		munmap_device_memory ((void *)hsmci->base, (uint32_t)cfg->MemLength[0]);

		if (hsmci->pio_base)
			munmap_device_io (hsmci->pio_base, AT91SAM9G45_PIO_SIZE);

		free (hsmci);
	}

	if (pioa_pdsr != (uint32_t *)MAP_FAILED)
		munmap_device_memory ((void *)pioa_pdsr, 4);
	return (MMC_FAILURE);
}
コード例 #13
0
ファイル: kerext_process.c プロジェクト: vocho/openqnx
static void
kerext_process_shutdown(void *data) {
	struct kerargs_process_shutdown	*args = data;
	PROCESS			*prp = args->prp;
	THREAD			*act = actives[KERNCPU];
	SIGTABLE		*stp;
	int				tid;
	int				i;
	int				try_again;

	lock_kernel();
	if(prp == NULL) {
		prp = act->process;
	}

	if(prp->memory) {
		// Make sure no threads reference the aspace before it's removed
		for(tid = 0; tid < prp->threads.nentries; tid++) {
			THREAD				*thp;

			if(VECP(thp, &prp->threads, tid)) {
				thp->aspace_prp = 0;
			}
		}

		try_again = 0;
		for(i = 0; i < NUM_PROCESSORS; ++i) {
			PROCESS *prp0;

			// The code between interrupt disable and enable should be short,
			// so that other CPUs will not have chance to get a interrupt and
			// switch aspace during the check
			InterruptDisable();
			if(get_inkernel() & INKERNEL_INTRMASK) {
				try_again = 1;
			}
			prp0 = *((PROCESS* volatile *)&aspaces_prp[i]);
			if(get_inkernel() & INKERNEL_INTRMASK) {
				try_again = 1;
			}
			InterruptEnable();

			if(prp == prp0) {
				// Switch current address space
				if(i == KERNCPU) {
					set_safe_aspace(i);
				} else {
					args->tlb_safe_cpu = i;
					SENDIPI(i, IPI_TLB_SAFE);
					try_again = 1;
				}
			}
		}
		if(try_again) {
			//Another CPU is pointing at this address space. We've sent
			//an IPI to get it to point at a safe entry (the process manager's),
			//but we have to wait until it's been processed before we can
			//destroy this address space.
			kererr(act, EAGAIN);
			return;
		}

		if(prp->flags & _NTO_PF_VFORKED) {
			// We're shutting down a vfork'd process. Don't free the
			// aspace, the parent process is still using it.
			prp->memory = NULL; 
		} else {
			memmgr.mdestroy(prp);
		}

		if(prp->memory || aspaces_prp[KERNCPU] == prp) {
			crash();
		}
		SETKSTATUS(act, 0);
		return;
	}

	// Remove all signal tables
	while((stp = prp->sig_table)) {
		prp->sig_table = stp->next;
		object_free(NULL, &sigtable_souls, stp);
	}

	// Check for guardian
	if(prp->guardian && (prp->guardian->flags & (_NTO_PF_LOADING | _NTO_PF_TERMING | _NTO_PF_ZOMBIE)) == 0) {
		process_swap(prp->guardian);
		prp->guardian = 0;
	}		

	if(prp == act->process) {
		if(!args->exec) {
			// if we need to, send a sigchld to the parent
			if (!(prp->flags & _NTO_PF_NOZOMBIE)) {
				signal_kill_process(prp->parent, SIGCHLD, prp->siginfo.si_code,
					prp->siginfo.si_value.sival_int, prp->siginfo.si_pid, 0 );
			}
			prp->siginfo.si_signo = SIGCHLD;
		}
		actives_prp[KERNCPU] = sysmgr_prp;
		thread_destroyall(act);
	} else {
		SETKSTATUS(act, prp->siginfo.si_status);
	}
}
コード例 #14
0
ファイル: sendmsg.c プロジェクト: Nat-Stein/abstract_dots_NS
static int
do_send(PROCTBL_P p, u_int msg, int msg_flag)
{
	u_int msgbit;
	int killRet;

#ifdef A_DEBUG
dprintf("-smsg: p %d, msg 0%o-", p, s_(msg));
#endif

	if(p->p_id <= 0) {
		rxerr("r_sendmsg(): Attempt to send msg to non-existant proc");
		return(-1);
	}
	if(msg_flag) msgbit= msg;
	else msgbit= s_(msg);

	/*
	 * Procs that are stopped can receive only certain messages.
	 */
	if(p != COMM && ((p->p_state & P_RUN_ST) == 0) &&
	   ((msgbit & (s_(G_KILL)|s_(G_STOP)|s_(G_RUN))) == 0)) {
		rxerr("r_sendmsg(): Cannot send msg; process is in stop state");
		return(-1);
	}

	if(inside_clock) {
	    /*
	     * This is the 'int' process, and we are inside the clock
	     * routine.  Don't call protect() if it would block!
	     */
		InterruptDisable();
	    if(!p->p_sem) {
			/*
			 * Just return -2.  'clock()' will try again next
			 * interrupt.
			 */
			InterruptEnable();
			return(-2);
	    }
		else protect(&p->p_sem);
		InterruptEnable();
	}
	else {
		protect(&p->p_sem);
	}
	p->p_msg |= msgbit;		/* set message bit */

	/*
	 * Signal sending is interlocked so that a signal is sent only
	 * when necessary to wake up the receiving process, OR re-interrupt
	 * a lower priority message currently executing in the receiving
	 * process.
	 */
	if( ! (p->p_state & P_NOSIG_ST)) {	/* signalling allowed */
		/*
		 * If the receiving process is currently not asleep but
		 * processing a message that has allowed re-interrupts, the
		 * re-interrupt mask will specify which messages are permitted
		 * to signal and cause a re-interrupt.
		 */
		if(msgbit & ~p->p_rmask) {
			p->p_state |= P_NOSIG_ST;
			release_(&p->p_sem);
#ifdef A_DEBUG
dprintf("-smsg: killing %d-", p->p_id);
#endif
            killRet = kill(p->p_id, S_ALERT);
			if(killRet == -1) {
				perror("do_send() kill error");
				stufs(p->p_name, &noproc[BLANKS], &noproc[0] +
								sizeof(noproc));
				rxerr(noproc);
				p->p_state &= ~P_NOSIG_ST;
				return(-1);
			}
			return(0);
		}
	}
	release_(&p->p_sem);
	return(0);
}