Exemple #1
0
static int
ray_fifo_push(		/* send finished ray to output (or queue it) */
	RAY *r
)
{
	int	rv, nsent = 0;

	if (ray_fifo_out == NULL)
		error(INTERNAL, "ray_fifo_out is NULL");
	if ((r->rno < r_fifo_start) | (r->rno >= r_fifo_next))
		error(INTERNAL, "unexpected ray number in ray_fifo_push()");

	if (r->rno > r_fifo_start) {		/* insert into output queue */
		while (r->rno - r_fifo_start >= r_fifo_len)
			ray_fifo_growbuf();	/* need more space */
		*r_fifo(r->rno) = *r;
		if (r->rno >= r_fifo_end)
			r_fifo_end = r->rno + 1;
		return(0);
	}
			/* r->rno == r_fifo_start, so transfer ray(s) */
	do {
		rv = (*ray_fifo_out)(r);
		r->rno = 0;			/* flag this entry complete */
		if (rv < 0)
			return(-1);
		nsent += rv;
		if (++r_fifo_start < r_fifo_end)
			r = r_fifo(r_fifo_start);
		else if (r_fifo_start > r_fifo_end)
			r_fifo_end = r_fifo_start;
	} while (r->rno == r_fifo_start);

	return(nsent);
}
Exemple #2
0
static void
ray_fifo_growbuf(void)	/* double buffer size (or set to minimum if NULL) */
{
	RAY	*old_buf = r_fifo_buf;
	int	old_len = r_fifo_len;
	int	i;

	if (r_fifo_buf == NULL)
		r_fifo_len = 1<<5;
	else
		r_fifo_len <<= 1;
						/* allocate new */
	r_fifo_buf = (RAY *)calloc(r_fifo_len, sizeof(RAY));
	if (r_fifo_buf == NULL)
		error(SYSTEM, "out of memory in ray_fifo_growbuf");
	if (old_buf == NULL)
		return;
						/* copy old & free */
	for (i = r_fifo_start; i < r_fifo_end; i++)
		*r_fifo(i) = old_buf[i&(old_len-1)];

	free(old_buf);
}
Exemple #3
0
u_char
ppc_io(device_t ppcdev, int iop, u_char *addr, int cnt, u_char byte)
{
	struct ppc_data *ppc = DEVTOSOFTC(ppcdev);
	switch (iop) {
	case PPB_OUTSB_EPP:
	    bus_space_write_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt);
		break;
	case PPB_OUTSW_EPP:
	    bus_space_write_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt);
		break;
	case PPB_OUTSL_EPP:
	    bus_space_write_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt);
		break;
	case PPB_INSB_EPP:
	    bus_space_read_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt);
		break;
	case PPB_INSW_EPP:
	    bus_space_read_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt);
		break;
	case PPB_INSL_EPP:
	    bus_space_read_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt);
		break;
	case PPB_RDTR:
		return (r_dtr(ppc));
	case PPB_RSTR:
		return (r_str(ppc));
	case PPB_RCTR:
		return (r_ctr(ppc));
	case PPB_REPP_A:
		return (r_epp_A(ppc));
	case PPB_REPP_D:
		return (r_epp_D(ppc));
	case PPB_RECR:
		return (r_ecr(ppc));
	case PPB_RFIFO:
		return (r_fifo(ppc));
	case PPB_WDTR:
		w_dtr(ppc, byte);
		break;
	case PPB_WSTR:
		w_str(ppc, byte);
		break;
	case PPB_WCTR:
		w_ctr(ppc, byte);
		break;
	case PPB_WEPP_A:
		w_epp_A(ppc, byte);
		break;
	case PPB_WEPP_D:
		w_epp_D(ppc, byte);
		break;
	case PPB_WECR:
		w_ecr(ppc, byte);
		break;
	case PPB_WFIFO:
		w_fifo(ppc, byte);
		break;
	default:
		panic("%s: unknown I/O operation", __func__);
		break;
	}

	return (0);	/* not significative */
}
Exemple #4
0
/*
 * ppc_detect_fifo()
 *
 * Detect parallel port FIFO
 */
static int
ppc_detect_fifo(struct ppc_data *ppc)
{
	char ecr_sav;
	char ctr_sav, ctr, cc;
	short i;
	
	/* save registers */
	ecr_sav = r_ecr(ppc);
	ctr_sav = r_ctr(ppc);

	/* enter ECP configuration mode, no interrupt, no DMA */
	w_ecr(ppc, 0xf4);

	/* read PWord size - transfers in FIFO mode must be PWord aligned */
	ppc->ppc_pword = (r_cnfgA(ppc) & PPC_PWORD_MASK);

	/* XXX 16 and 32 bits implementations not supported */
	if (ppc->ppc_pword != PPC_PWORD_8) {
		LOG_PPC(__func__, ppc, "PWord not supported");
		goto error;
	}

	w_ecr(ppc, 0x34);		/* byte mode, no interrupt, no DMA */
	ctr = r_ctr(ppc);
	w_ctr(ppc, ctr | PCD);		/* set direction to 1 */

	/* enter ECP test mode, no interrupt, no DMA */
	w_ecr(ppc, 0xd4);

	/* flush the FIFO */
	for (i=0; i<1024; i++) {
		if (r_ecr(ppc) & PPC_FIFO_EMPTY)
			break;
		cc = r_fifo(ppc);
	}

	if (i >= 1024) {
		LOG_PPC(__func__, ppc, "can't flush FIFO");
		goto error;
	}

	/* enable interrupts, no DMA */
	w_ecr(ppc, 0xd0);

	/* determine readIntrThreshold
	 * fill the FIFO until serviceIntr is set
	 */
	for (i=0; i<1024; i++) {
		w_fifo(ppc, (char)i);
		if (!ppc->ppc_rthr && (r_ecr(ppc) & PPC_SERVICE_INTR)) {
			/* readThreshold reached */
			ppc->ppc_rthr = i+1;
		}
		if (r_ecr(ppc) & PPC_FIFO_FULL) {
			ppc->ppc_fifo = i+1;
			break;
		}
	}

	if (i >= 1024) {
		LOG_PPC(__func__, ppc, "can't fill FIFO");
		goto error;
	}

	w_ecr(ppc, 0xd4);		/* test mode, no interrupt, no DMA */
	w_ctr(ppc, ctr & ~PCD);		/* set direction to 0 */
	w_ecr(ppc, 0xd0);		/* enable interrupts */

	/* determine writeIntrThreshold
	 * empty the FIFO until serviceIntr is set
	 */
	for (i=ppc->ppc_fifo; i>0; i--) {
		if (r_fifo(ppc) != (char)(ppc->ppc_fifo-i)) {
			LOG_PPC(__func__, ppc, "invalid data in FIFO");
			goto error;
		}
		if (r_ecr(ppc) & PPC_SERVICE_INTR) {
			/* writeIntrThreshold reached */
			ppc->ppc_wthr = ppc->ppc_fifo - i+1;
		}
		/* if FIFO empty before the last byte, error */
		if (i>1 && (r_ecr(ppc) & PPC_FIFO_EMPTY)) {
			LOG_PPC(__func__, ppc, "data lost in FIFO");
			goto error;
		}
	}

	/* FIFO must be empty after the last byte */
	if (!(r_ecr(ppc) & PPC_FIFO_EMPTY)) {
		LOG_PPC(__func__, ppc, "can't empty the FIFO");
		goto error;
	}
	
	w_ctr(ppc, ctr_sav);
	w_ecr(ppc, ecr_sav);

	return (0);

error:
	w_ctr(ppc, ctr_sav);
	w_ecr(ppc, ecr_sav);

	return (EINVAL);
}