Beispiel #1
0
VOID FASTCALL HWSetupClipping(DEVRC *pRc, RECTL *pClip)
{
    PDEV *ppdev = pRc->ppdev;
    BYTE *pjBase = ppdev->pjBase;

    CHECK_FIFO_FREE(pjBase, pRc->cFifo, 4);

    CP_WRITE(pjBase, DWG_CYTOP,
                  ((pClip->top + pRc->hwBufferYBias) * ppdev->cxMemory) +
                  ppdev->ulYDstOrg);
    CP_WRITE(pjBase, DWG_CXLEFT, pClip->left);
    CP_WRITE(pjBase, DWG_CXRIGHT, pClip->right - 1);
    CP_WRITE(pjBase, DWG_CYBOT,
                 ((pClip->bottom + pRc->hwBufferYBias - 1) * ppdev->cxMemory) +
                  ppdev->ulYDstOrg);

}
Beispiel #2
0
/*
 * Get device PROM values from CP
 * 
 * This function will issue a GET_PROM command to the CP in order to
 * initiate the DMA transfer of the CP's PROM structure to the host.
 * This will be called after CP initialization has completed.
 * There is (currently) no retry if this fails.
 *
 * Called at interrupt level.
 *
 * Arguments:
 *	fup	pointer to device unit structure
 *
 * Returns:
 *	none
 *
 */
static void
fore_get_prom(Fore_unit *fup)
{
	H_cmd_queue	*hcp;
	Cmd_queue	*cqp;

	/*
	 * Queue command at end of command queue
	 */
	hcp = fup->fu_cmd_tail;
	if ((*hcp->hcq_status) & QSTAT_FREE) {

		/*
		 * Queue entry available, so set our view of things up
		 */
		hcp->hcq_code = CMD_GET_PROM;
		hcp->hcq_arg = NULL;
		fup->fu_cmd_tail = hcp->hcq_next;

		/*
		 * Now set the CP-resident queue entry - the CP will grab
		 * the command when the op-code is set.
		 */
		cqp = hcp->hcq_cpelem;
		(*hcp->hcq_status) = QSTAT_PENDING;

		fup->fu_promd = DMA_GET_ADDR(fup->fu_prom, sizeof(Fore_prom),
			FORE_PROM_ALIGN, 0);
		if (fup->fu_promd == NULL) {
			fup->fu_stats->st_drv.drv_cm_nodma++;
			return;
		}
		cqp->cmdq_prom.prom_buffer = (CP_dma) CP_WRITE(fup->fu_promd);
		cqp->cmdq_prom.prom_cmd = CP_WRITE(CMD_GET_PROM | CMD_INTR_REQ);

	} else {
		/*
		 * Command queue full
		 */
		fup->fu_stats->st_drv.drv_cm_full++;
	}

	return;
}
Beispiel #3
0
/*
 * Supply Strategy 1 Large Buffers to CP
 *
 * May be called in interrupt state.
 * Must be called with interrupts locked out.
 *
 * Arguments:
 *	fup		pointer to device unit structure
 *
 * Returns:
 *	none
 */
static void
fore_buf_supply_1l(Fore_unit *fup)
{
	H_buf_queue	*hbp;
	Buf_queue	*cqp;
	Buf_descr	*bdp;
	Buf_handle	*bhp;
	KBuffer		*m;
	int		nvcc, nbuf, i;

	/*
	 * Figure out how many buffers we should be giving to the CP.
	 * We're basing this calculation on the current number of open
	 * VCCs thru this device, with certain minimum and maximum values
	 * enforced.  This will then allow us to figure out how many more 
	 * buffers we need to supply to the CP.  This will be rounded up 
	 * to fill a supply queue entry.
	 */
	nvcc = MAX(fup->fu_open_vcc, BUF_MIN_VCC);
	nbuf = nvcc * 4 * RECV_MAX_SEGS;
	nbuf = MIN(nbuf, BUF1_LG_CPPOOL);
	nbuf -= fup->fu_buf1l_cnt;
	nbuf = roundup(nbuf, BUF1_LG_ENTSIZE);

	/*
	 * OK, now supply the buffers to the CP
	 */
	while (nbuf > 0) {

		/*
		 * Acquire a supply queue entry
		 */
		hbp = fup->fu_buf1l_tail;
		if (!((*hbp->hbq_status) & QSTAT_FREE))
			break;
		bdp = hbp->hbq_descr;

		/*
		 * Get a buffer for each descriptor in the queue entry
		 */
		for (i = 0; i < BUF1_LG_ENTSIZE; i++, bdp++) {
			caddr_t		cp;

			/*
			 * Get a cluster buffer
			 */
			KB_ALLOCEXT(m, BUF1_LG_SIZE, KB_F_NOWAIT, KB_T_DATA);
			if (m == NULL) {
				break;
			}
			KB_HEADSET(m, BUF1_LG_DOFF);

			/*
			 * Point to buffer handle structure
			 */
			bhp = (Buf_handle *)((caddr_t)m + BUF1_LG_HOFF);
			bhp->bh_type = BHT_S1_LARGE;

			/*
			 * Setup buffer descriptor
			 */
			bdp->bsd_handle = bhp;
			KB_DATASTART(m, cp, caddr_t);
			bhp->bh_dma = bdp->bsd_buffer = (H_dma) DMA_GET_ADDR(
				cp, BUF1_LG_SIZE, BUF_DATA_ALIGN, 0);
			if (bdp->bsd_buffer == 0) {
				/*
				 * Unable to assign dma address - free up
				 * this descriptor's buffer
				 */
				fup->fu_stats->st_drv.drv_bf_segdma++;
				KB_FREEALL(m);
				break;
			}

			/*
			 * All set, so queue buffer (handle)
			 */
			ENQUEUE(bhp, Buf_handle, bh_qelem, fup->fu_buf1l_bq);
		}

		/*
		 * If we we're not able to fill all the descriptors for
		 * an entry, free up what's been partially built
		 */
		if (i != BUF1_LG_ENTSIZE) {
			caddr_t		cp;

			/*
			 * Clean up each used descriptor
			 */
			for (bdp = hbp->hbq_descr; i; i--, bdp++) {
				bhp = bdp->bsd_handle;

				DEQUEUE(bhp, Buf_handle, bh_qelem, 
					fup->fu_buf1l_bq);

				m = (KBuffer *)
					((caddr_t)bhp - BUF1_LG_HOFF);
				KB_DATASTART(m, cp, caddr_t);
				DMA_FREE_ADDR(cp, bhp->bh_dma, BUF1_LG_SIZE, 0);
				KB_FREEALL(m);
			}
			break;
		}

		/*
		 * Finally, we've got an entry ready for the CP.
		 * So claim the host queue entry and setup the CP-resident
		 * queue entry.  The CP will (potentially) grab the supplied
		 * buffers when the descriptor pointer is set.
		 */
		fup->fu_buf1l_tail = hbp->hbq_next;
		(*hbp->hbq_status) = QSTAT_PENDING;
		cqp = hbp->hbq_cpelem;
		cqp->cq_descr = (CP_dma) CP_WRITE((u_long)hbp->hbq_descr_dma);

		/*
		 * Update counters, etc for supplied buffers
		 */
		fup->fu_buf1l_cnt += BUF1_LG_ENTSIZE;
		nbuf -= BUF1_LG_ENTSIZE;
	}

	return;
}
Beispiel #4
0
/*
 * Buffer Supply Queues Initialization
 *
 * Allocate and initialize the host-resident buffer supply queue structures
 * and then initialize the CP-resident queue structures.
 * 
 * Called at interrupt level.
 *
 * Arguments:
 *	fup		pointer to device unit structure
 *
 * Returns:
 *	none
 */
void
fore_buf_initialize(Fore_unit *fup)
{
	Aali		*aap = fup->fu_aali;
	Buf_queue	*cqp;
	H_buf_queue	*hbp;
	Buf_descr	*bdp;
	Buf_descr	*bdp_dma;
	Q_status	*qsp;
	Q_status	*qsp_dma;
	int		i;

	/*
	 * Initialize Strategy 1 Small Queues
	 */

	/*
	 * Point to CP-resident buffer supply queue
	 */
	cqp = (Buf_queue *)(fup->fu_ram + CP_READ(aap->aali_buf1s_q));

	/*
	 * Point to host-resident buffer supply queue structures
	 */
	hbp = fup->fu_buf1s_q;
	qsp = fup->fu_buf1s_stat;
	qsp_dma = fup->fu_buf1s_statd;
	bdp = fup->fu_buf1s_desc;
	bdp_dma = fup->fu_buf1s_descd;

	/*
	 * Loop thru all queue entries and do whatever needs doing
	 */
	for (i = 0; i < BUF1_SM_QUELEN; i++) {

		/*
		 * Set queue status word to free
		 */
		*qsp = QSTAT_FREE;

		/*
		 * Set up host queue entry and link into ring
		 */
		hbp->hbq_cpelem = cqp;
		hbp->hbq_status = qsp;
		hbp->hbq_descr = bdp;
		hbp->hbq_descr_dma = bdp_dma;
		if (i == (BUF1_SM_QUELEN - 1))
			hbp->hbq_next = fup->fu_buf1s_q;
		else
			hbp->hbq_next = hbp + 1;

		/*
		 * Now let the CP into the game
		 */
		cqp->cq_status = (CP_dma) CP_WRITE(qsp_dma);

		/*
		 * Bump all queue pointers
		 */
		hbp++;
		qsp++;
		qsp_dma++;
		bdp += BUF1_SM_ENTSIZE;
		bdp_dma += BUF1_SM_ENTSIZE;
		cqp++;
	}

	/*
	 * Initialize queue pointers
	 */
	fup->fu_buf1s_head = fup->fu_buf1s_tail = fup->fu_buf1s_q;


	/*
	 * Initialize Strategy 1 Large Queues
	 */

	/*
	 * Point to CP-resident buffer supply queue
	 */
	cqp = (Buf_queue *)(fup->fu_ram + CP_READ(aap->aali_buf1l_q));

	/*
	 * Point to host-resident buffer supply queue structures
	 */
	hbp = fup->fu_buf1l_q;
	qsp = fup->fu_buf1l_stat;
	qsp_dma = fup->fu_buf1l_statd;
	bdp = fup->fu_buf1l_desc;
	bdp_dma = fup->fu_buf1l_descd;

	/*
	 * Loop thru all queue entries and do whatever needs doing
	 */
	for (i = 0; i < BUF1_LG_QUELEN; i++) {

		/*
		 * Set queue status word to free
		 */
		*qsp = QSTAT_FREE;

		/*
		 * Set up host queue entry and link into ring
		 */
		hbp->hbq_cpelem = cqp;
		hbp->hbq_status = qsp;
		hbp->hbq_descr = bdp;
		hbp->hbq_descr_dma = bdp_dma;
		if (i == (BUF1_LG_QUELEN - 1))
			hbp->hbq_next = fup->fu_buf1l_q;
		else
			hbp->hbq_next = hbp + 1;

		/*
		 * Now let the CP into the game
		 */
		cqp->cq_status = (CP_dma) CP_WRITE(qsp_dma);

		/*
		 * Bump all queue pointers
		 */
		hbp++;
		qsp++;
		qsp_dma++;
		bdp += BUF1_LG_ENTSIZE;
		bdp_dma += BUF1_LG_ENTSIZE;
		cqp++;
	}

	/*
	 * Initialize queue pointers
	 */
	fup->fu_buf1l_head = fup->fu_buf1l_tail = fup->fu_buf1l_q;

	return;
}
Beispiel #5
0
/*
 * Begin CP Initialization
 *
 * This function will poll for the successful downloading and starting of
 * the CP microcode program.  After the microcode is running, we will allocate
 * any needed kernel memory (must do it in non-interrupt mode), build the CP
 * queue configurations and issue an Initialize command to the CP.
 *
 * Arguments:
 *	fup		pointer to device unit structure
 *
 * Returns:
 *	none
 */
void
fore_initialize(void *xfup)
{
	Fore_unit	*fup = xfup;
	Aali		*aap;
	Init_parms	*inp;
	caddr_t		errmsg;
	u_long		vers;

	/*
	 * Must wait until firmware has been downloaded and is running
	 */
	if (CP_READ(fup->fu_mon->mon_bstat) != BOOT_RUNNING) {

		/*
		 * Try again later
		 */
		callout_reset(&fup->fu_init_timer, hz, fore_initialize, fup);
		return;
	}

	/*
	 * Allocate queues and whatever else is needed
	 */
	if (fore_xmit_allocate(fup)) {
		errmsg = "transmit queue allocation";
		goto failed;
	}
	if (fore_recv_allocate(fup)) {
		errmsg = "receive queue allocation";
		goto failed;
	}
	if (fore_buf_allocate(fup)) {
		errmsg = "buffer supply queue allocation";
		goto failed;
	}
	if (fore_cmd_allocate(fup)) {
		errmsg = "command queue allocation";
		goto failed;
	}

	/*
	 * CP microcode is downloaded - locate shared memory interface 
	 */
	aap = (Aali *)(fup->fu_ram + CP_READ(fup->fu_mon->mon_appl));
	fup->fu_aali = aap;

	/*
	 * Pick out any interesting info from the microcode
	 */
	vers = CP_READ(aap->aali_ucode_ver);
	if (vers < FORE_MIN_UCODE) {
		errmsg = "unsupported microcode version";
		goto failed;
	}
	ksnprintf(fup->fu_config.ac_firm_vers,
	    sizeof(fup->fu_config.ac_firm_vers), "%ld.%ld.%ld",
		(vers >> 16) & 0xff, (vers >> 8) & 0xff, vers & 0xff);

#ifdef notdef
	/*
	 * Turn on CP debugging
	 */
	aap->aali_hostlog = 1;
#endif

	/*
	 * Build the initialization block
	 */
	inp = &aap->aali_init;
	inp->init_numvcc = CP_WRITE(FORE_MAX_VCC);
	inp->init_cmd_elem = CP_WRITE(CMD_QUELEN);
	inp->init_xmit_elem = CP_WRITE(XMIT_QUELEN);
	inp->init_recv_elem = CP_WRITE(RECV_QUELEN);
	inp->init_recv_ext = CP_WRITE(RECV_EXTRA_SEGS);
	inp->init_xmit_ext = CP_WRITE(XMIT_EXTRA_SEGS);
	inp->init_buf1s.bfs_quelen = CP_WRITE(BUF1_SM_QUELEN);
	inp->init_buf1s.bfs_bufsize = CP_WRITE(BUF1_SM_SIZE);
	inp->init_buf1s.bfs_cppool = CP_WRITE(BUF1_SM_CPPOOL);
	inp->init_buf1s.bfs_entsize = CP_WRITE(BUF1_SM_ENTSIZE);
	inp->init_buf1l.bfs_quelen = CP_WRITE(BUF1_LG_QUELEN);
	inp->init_buf1l.bfs_bufsize = CP_WRITE(BUF1_LG_SIZE);
	inp->init_buf1l.bfs_cppool = CP_WRITE(BUF1_LG_CPPOOL);
	inp->init_buf1l.bfs_entsize = CP_WRITE(BUF1_LG_ENTSIZE);
	inp->init_buf2s.bfs_quelen = CP_WRITE(0);
	inp->init_buf2s.bfs_bufsize = CP_WRITE(0);
	inp->init_buf2s.bfs_cppool = CP_WRITE(0);
	inp->init_buf2s.bfs_entsize = CP_WRITE(0);
	inp->init_buf2l.bfs_quelen = CP_WRITE(0);
	inp->init_buf2l.bfs_bufsize = CP_WRITE(0);
	inp->init_buf2l.bfs_cppool = CP_WRITE(0);
	inp->init_buf2l.bfs_entsize = CP_WRITE(0);

	/*
	 * Enable device interrupts
	 */
	aap->aali_intr_ena = CP_WRITE(1);

	/*
	 * Issue the Initialize command to the CP and wait for
	 * the CP to interrupt to signal completion
	 */
	inp->init_status = CP_WRITE(QSTAT_PENDING);
	inp->init_cmd = CP_WRITE(CMD_INIT | CMD_INTR_REQ);
	return;

failed:
	/*
	 * Initialization failure
	 */
	fore_interface_free(fup);
	log(LOG_ERR, "fore initialization failed: intf=%s%d, err=%s\n",
		fup->fu_pif.pif_name, fup->fu_pif.pif_unit, errmsg);
	return;
}
Beispiel #6
0
/*
 * Get device statistics from CP
 * 
 * This function will issue a GET_STATS command to the CP in order to
 * initiate the DMA transfer of the CP's statistics structure to the host.
 * We will then sleep pending command completion.  This must only be called
 * from the ioctl system call handler.
 *
 * Called from a critical section.
 *
 * Arguments:
 *	fup	pointer to device unit structure
 *
 * Returns:
 *	0	stats retrieval successful
 *	errno 	stats retrieval failed - reason indicated
 *
 */
int
fore_get_stats(Fore_unit *fup)
{
	H_cmd_queue	*hcp;
	Cmd_queue	*cqp;
	int		sst;

	ATM_DEBUG1("fore_get_stats: fup=%p\n", fup);

	/*
	 * Make sure device has been initialized
	 */
	if ((fup->fu_flags & CUF_INITED) == 0) {
		return (EIO);
	}

	/*
	 * If someone has already initiated a stats request, we'll
	 * just wait for that one to complete
	 */
	crit_enter();
	if (fup->fu_flags & FUF_STATCMD) {

		sst = tsleep((caddr_t)&fup->fu_stats, PCATCH, "fore", 0);
		crit_exit();
		return (sst ? sst : fup->fu_stats_ret);
	}

	/*
	 * Limit stats gathering to once a second or so
	 */
	if (time_second == fup->fu_stats_time) {
		crit_exit();
		return (0);
	} else
		fup->fu_stats_time = time_second;

	/*
	 * Queue command at end of command queue
	 */
	hcp = fup->fu_cmd_tail;
	if ((*hcp->hcq_status) & QSTAT_FREE) {
		void	*dma;

		/*
		 * Queue entry available, so set our view of things up
		 */
		hcp->hcq_code = CMD_GET_STATS;
		hcp->hcq_arg = NULL;
		fup->fu_cmd_tail = hcp->hcq_next;

		/*
		 * Now set the CP-resident queue entry - the CP will grab
		 * the command when the op-code is set.
		 */
		cqp = hcp->hcq_cpelem;
		(*hcp->hcq_status) = QSTAT_PENDING;

		dma = DMA_GET_ADDR(fup->fu_stats, sizeof(Fore_cp_stats),
			FORE_STATS_ALIGN, 0);
		if (dma == NULL) {
			fup->fu_stats->st_drv.drv_cm_nodma++;
			crit_exit();
			return (EIO);
		}
		fup->fu_statsd = dma;
		cqp->cmdq_stats.stats_buffer = (CP_dma) CP_WRITE(dma);

		fup->fu_flags |= FUF_STATCMD;
		cqp->cmdq_stats.stats_cmd = 
			CP_WRITE(CMD_GET_STATS | CMD_INTR_REQ);

		/*
		 * Now wait for command to finish
		 */
		sst = tsleep((caddr_t)&fup->fu_stats, PCATCH, "fore", 0);
		crit_exit();
		return (sst ? sst : fup->fu_stats_ret);

	} else {
		/*
		 * Command queue full
		 */
		fup->fu_stats->st_drv.drv_cm_full++;
		crit_exit();
		return (EIO);
	}
}