Beispiel #1
0
static int
plsetparam(Serialport *p)
{
	uint8_t buf[ParamReqSz];
	int res;
	Serial *ser;

	ser = p->s;

	PUT4(buf, p->baud);

	if(p->stop == 1)
		buf[4] = 0;
	else if(p->stop == 2)
		buf[4] = 2; 			/* see comment in getparam */
	buf[5] = p->parity;
	buf[6] = p->bits;

	dsprint(2, "serial: setparam: ");
	if(serialdebug)
		dumpbuf(buf, sizeof buf);
	res = usbcmd(ser->dev, Rh2d | Rclass | Riface, SetLineReq,
		0, 0, buf, sizeof buf);
	plmodemctl(p, p->mctl);
	plgetparam(p);		/* make sure our state corresponds */

	dsprint(2, "serial: setparam res: %d\n", res);
	return res;
}
Beispiel #2
0
static int
ftinit(Serialport *p)
{
    Serial *ser;
    uint timerval;
    int res;

    ser = p->s;
    if(p->isjtag) {
        res = ftdiwrite(p, FTSETFLOWCTRL, 0, FTDISABLEFLOWCTRL);
        if(res < 0)
            return -1;
        res = ftdiread(p, FTSETLATENCYTIMER, 0, (uchar *)&timerval,
                       FTLATENCYTIMERSZ);
        if(res < 0)
            return -1;
        dsprint(2, "serial: jtag latency timer is %d\n", timerval);
        timerval = 2;
        ftdiwrite(p, FTLATENCYDEFAULT, 0, FTSETLATENCYTIMER);
        res = ftdiread(p, FTSETLATENCYTIMER, 0, (uchar *)&timerval,
                       FTLATENCYTIMERSZ);
        if(res < 0)
            return -1;

        dsprint(2, "serial: jtag latency timer set to %d\n", timerval);
        /* 0xb is the mask for lines. plug dependant? */
        ftdiwrite(p, BMMPSSE|0x0b, 0, FTSETBITMODE);
    }
    incref(ser->dev);
    proccreate(statusreader, p, 8*1024);
    return 0;
}
Beispiel #3
0
static int
ftsendlines(Serialport *p)
{
    int res;

    dsprint(2, "serial: sendlines: %#2.2x\n", p->ctlstate);
    res = setctl(p);
    dsprint(2, "serial: sendlines res: %d\n", res);
    return 0;
}
Beispiel #4
0
static int
plinit(Serialport *p)
{
	char *st;
	uint8_t *buf;
	uint32_t csp, maxpkt, dno;
	Serial *ser;

	ser = p->s;
	buf = emallocz(VendorReqSz, 1);
	dsprint(2, "plinit\n");

	csp = ser->dev->usb->csp;
	maxpkt = ser->dev->maxpkt;
	dno = ser->dev->usb->dno;

	if((ser->type = revid(dno)) == TypeUnk)
		ser->type = heuristicid(csp, maxpkt);

	dsprint(2, "serial: type %d\n", ser->type);

	vendorread(p, 0x8484, 0, buf);
	vendorwrite(p, 0x0404, 0);
	vendorread(p, 0x8484, 0, buf);
	vendorread(p, 0x8383, 0, buf);
	vendorread(p, 0x8484, 0, buf);
	vendorwrite(p, 0x0404, 1);
	vendorread(p, 0x8484, 0, buf);
	vendorread(p, 0x8383, 0, buf);

	vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init);
	vendorwrite(p, Dcr1Idx|DcrSet, Dcr1Init);

	if(ser->type == TypeHX)
		vendorwrite(p, Dcr2Idx|DcrSet, Dcr2InitX);
	else
		vendorwrite(p, Dcr2Idx|DcrSet, Dcr2InitH);

	plgetparam(p);
	qunlock(ser);
	free(buf);
	st = emallocz(255, 1);
	qlock(ser);
	if(serialdebug)
		serdumpst(p, st, 255);
	dsprint(2, st);
	free(st);
	/* p gets freed by closedev, the process has a reference */
	incref(ser->dev);
	proccreate(statusreader, p, 8*1024);
	return 0;
}
Beispiel #5
0
static int
vendorwrite(Serialport *p, int val, int index)
{
	int res;
	Serial *ser;

	ser = p->s;

	dsprint(2, "serial: vendorwrite val: 0x%x idx:%d\n", val, index);
	res = usbcmd(ser->dev, Rh2d | Rvendor | Rdev, VendorWriteReq,
		val, index, nil, 0);
	dsprint(2, "serial: vendorwrite res:%d\n", res);
	return res;
}
Beispiel #6
0
static int
vendorread(Serialport *p, int val, int index, uint8_t *buf)
{
	int res;
	Serial *ser;

	ser = p->s;

	dsprint(2, "serial: vendorread val: 0x%x idx:%d buf:%p\n",
		val, index, buf);
	res = usbcmd(ser->dev,  Rd2h | Rvendor | Rdev, VendorReadReq,
		val, index, buf, 1);
	dsprint(2, "serial: vendorread res:%d\n", res);
	return res;
}
Beispiel #7
0
static int
ftsetparam(Serialport *p)
{
    int res;
    ushort val;
    ulong bauddiv;

    val = 0;
    if(p->stop == 1)
        val |= FTSETDATASTOPBITS1;
    else if(p->stop == 2)
        val |= FTSETDATASTOPBITS2;
    else if(p->stop == 15)
        val |= FTSETDATASTOPBITS15;
    switch(p->parity) {
    case 0:
        val |= FTSETDATAParNONE;
        break;
    case 1:
        val |= FTSETDATAParODD;
        break;
    case 2:
        val |= FTSETDATAParEVEN;
        break;
    case 3:
        val |= FTSETDATAParMARK;
        break;
    case 4:
        val |= FTSETDATAParSPACE;
        break;
    };

    dsprint(2, "serial: setparam\n");

    res = ftdiwrite(p, val, 0, FTSETDATA);
    if(res < 0)
        return res;

    res = ftmodemctl(p, p->mctl);
    if(res < 0)
        return res;

    bauddiv = ftbaudcalcdiv(p->s, p->baud);
    res = ftdiwrite(p, bauddiv, (bauddiv>>16) & 1, FTSETBAUDRATE);

    dsprint(2, "serial: setparam res: %d\n", res);
    return res;
}
Beispiel #8
0
static int
ftdiread(Serialport *p, int index, int req, uchar *buf, int len)
{
    int res;
    Serial *ser;

    ser = p->s;

    if(req != FTGETE2READ)
        index |= p->interfc + 1;
    dsprint(2, "serial: ftdiread %#p [%d] req: %#x val: %#x idx:%d buf:%p len:%d\n",
            p, p->interfc, req, 0, index, buf, len);
    res = usbcmd(ser->dev,  Rd2h | Rftdireq | Rdev, req, 0, index, buf, len);
    dsprint(2, "serial: ftdiread res:%d\n", res);
    return res;
}
Beispiel #9
0
static int
ftdiwrite(Serialport *p, int val, int index, int req)
{
    int res;
    Serial *ser;

    ser = p->s;

    if(req != FTGETE2READ || req != FTSETE2ERASE || req != FTSETBAUDRATE)
        index |= p->interfc + 1;
    dsprint(2, "serial: ftdiwrite %#p [%d] req: %#x val: %#x idx:%d\n",
            p, p->interfc, req, val, index);
    res = usbcmd(ser->dev, Rh2d | Rftdireq | Rdev, req, val, index, nil, 0);
    dsprint(2, "serial: ftdiwrite res:%d\n", res);
    return res;
}
Beispiel #10
0
static void
statusreader(void *u)
{
	Areader *a;
	Channel *c;
	Packser *pk;
	Serialport *p;
	Serial *ser;
	int cl;

	p = u;
	ser = p->s;
	threadsetname("statusreader thread");
	/* big buffering, fewer bytes lost */
	c = chancreate(sizeof(Packser *), 128);
	a = emallocz(sizeof(Areader), 1);
	a->p = p;
	a->c = c;
	incref(ser->dev);
	proccreate(epreader, a, 16*1024);

	while((pk = recvp(c)) != nil){
		memmove(p->data, pk->b, pk->nb);
		p->ndata = pk->nb;
		free(pk);
		dsprint(2, "serial %p: status reader %d \n", p, p->ndata);
		/* consume it all */
		while(p->ndata != 0){
			dsprint(2, "serial %p: status reader to consume: %d\n",
				p, p->ndata);
			cl = recvul(p->w4data);
			if(cl  < 0)
				break;
			cl = sendul(p->gotdata, 1);
			if(cl  < 0)
				break;
		}
	}

	shutdownchan(c);
	devctl(ser->dev, "detach");
	closedev(ser->dev);
	usbfsdel(&p->fs);
}
Beispiel #11
0
static int
plgetparam(Serialport *p)
{
	uint8_t buf[ParamReqSz];
	int res;
	Serial *ser;

	ser = p->s;


	res = usbcmd(ser->dev, Rd2h | Rclass | Riface, GetLineReq,
		0, 0, buf, sizeof buf);
	p->baud = GET4(buf);

	/*
	 * with the Pl9 interface it is not possible to set `1.5' as stop bits
	 * for the prologic:
	 *	0 is 1 stop bit
	 *	1 is 1.5 stop bits
	 *	2 is 2 stop bits
	 */
	if(buf[4] == 1)
		fprint(2, "warning, stop bit set to 1.5 unsupported");
	else if(buf[4] == 0)
		p->stop = 1;
	else if(buf[4] == 2)
		p->stop = 2;
	p->parity = buf[5];
	p->bits = buf[6];

	dsprint(2, "serial: getparam: ");
	if(serialdebug)
		dumpbuf(buf, sizeof buf);
	dsprint(2, "serial: getparam res: %d\n", res);
	return res;
}
Beispiel #12
0
int
plmatch(char *info)
{
	Cinfo *ip;
	char buf[50];

	for(ip = plinfo; ip->vid != 0; ip++){
		snprint(buf, sizeof buf, "vid %#06x did %#06x",
			ip->vid, ip->did);
		dsprint(2, "serial: %s %s\n", buf, info);
		if(strstr(info, buf) != nil)
			return 0;
	}
	return -1;
}
Beispiel #13
0
static int
slinit(Serialport *p)
{
	Serial *ser;

	ser = p->s;
	dsprint(2, "slinit\n");

	slput(p, Enable, 1);

	slops.getparam(p);

	/* p gets freed by closedev, the process has a reference */
	incref(ser->dev);
	return 0;
}
Beispiel #14
0
int
ftmatch(Serial *ser, char *info)
{
	Cinfo *ip;
	char buf[50];

	for(ip = ftinfo; ip->vid != 0; ip++){
		snprint(buf, sizeof buf, "vid %#06x did %#06x", ip->vid, ip->did);
		dsprint(2, "serial: %s %s\n", buf, info);
		if(strstr(info, buf) != nil){
			if(ser != nil){
				qlock(ser);
				ftgettype(ser);
				qunlock(ser);
			}
			return 0;
		}
	}
	return -1;
}
Beispiel #15
0
static int
plreadstatus(Serialport *p)
{
	int nr, dfd;
	char err[40];
	uint8_t buf[VendorReqSz];
	Serial *ser;

	ser = p->s;

	qlock(ser);
	dsprint(2, "serial: reading from interrupt\n");
	dfd = p->epintr->dfd;

	qunlock(ser);
	nr = read(dfd, buf, sizeof buf);
	qlock(ser);
	snprint(err, sizeof err, "%r");
	dsprint(2, "serial: interrupt read %d %r\n", nr);

	if(nr < 0 && strstr(err, "timed out") == nil){
		dsprint(2, "serial: need to recover, status read %d %r\n", nr);
		if(serialrecover(ser, nil, nil, err) < 0){
			qunlock(ser);
			return -1;
		}
	}
	if(nr < 0)
		dsprint(2, "serial: reading status: %r");
	else if(nr >= sizeof buf - 1){
		p->dcd = buf[8] & DcdStatus;
		p->dsr = buf[8] & DsrStatus;
		p->cts = buf[8] & BreakerrStatus;
		p->ring = buf[8] & RingStatus;
		p->cts = buf[8] & CtsStatus;
		if(buf[8] & FrerrStatus)
			p->nframeerr++;
		if(buf[8] & ParerrStatus)
			p->nparityerr++;
		if(buf[8] & OvererrStatus)
			p->novererr++;
	} else
		dsprint(2, "serial: bad status read %d\n", nr);
	dsprint(2, "serial: finished read from interrupt %d\n", nr);
	qunlock(ser);
	return 0;
}
Beispiel #16
0
/* ser locked */
static void
ftgettype(Serial *ser)
{
    int i, outhdrsz, dno, pksz;
    ulong baudbase;
    Conf *cnf;

    pksz = Packsz;
    /* Assume it is not the original SIO device for now. */
    baudbase = ClockNew / 2;
    outhdrsz = 0;
    dno = ser->dev->usb->dno;
    cnf = ser->dev->usb->conf[0];
    ser->nifcs = 0;
    for(i = 0; i < Niface; i++)
        if(cnf->iface[i] != nil)
            ser->nifcs++;
    if(ser->nifcs > 1) {
        /*
         * Multiple interfaces.  default assume FT2232C,
         */
        if(dno == 0x500)
            ser->type = FT2232C;
        else if(dno == 0x600)
            ser->type = FTKINDR;
        else if(dno == 0x700) {
            ser->type = FT2232H;
            pksz = Maxpacksz;
        } else if(dno == 0x800) {
            ser->type = FT4232H;
            pksz = Maxpacksz;
        } else
            ser->type = FT2232C;

        if(hasjtag(ser->dev->usb))
            ser->jtag = 0;

        /*
         * BM-type devices have a bug where dno gets set
         * to 0x200 when serial is 0.
         */
        if(dno < 0x500)
            fprint(2, "serial: warning: dno %d too low for "
                   "multi-interface device\n", dno);
    } else if(dno < 0x200) {
        /* Old device.  Assume it is the original SIO. */
        ser->type = SIO;
        baudbase = ClockOld/16;
        outhdrsz = 1;
    } else if(dno < 0x400)
        /*
         * Assume its an FT8U232AM (or FT8U245AM)
         * (It might be a BM because of the iSerialNumber bug,
         * but it will still work as an AM device.)
         */
        ser->type = FT8U232AM;
    else			/* Assume it is an FT232BM (or FT245BM) */
        ser->type = FT232BM;

    ser->maxrtrans = ser->maxwtrans = pksz;
    ser->baudbase = baudbase;
    ser->outhdrsz = outhdrsz;
    ser->inhdrsz = 2;
    ser->Serialops = ftops;

    dsprint (2, "serial: detected type: %#x\n", ser->type);
}
Beispiel #17
0
static void
epreader(void *u)
{
    int dfd, rcount, cl, ntries, recov;
    Areader *a;
    Channel *c;
    Packser *pk;
    Serial *ser;
    Serialport *p;

    threadsetname("epreader proc");
    a = u;
    p = a->p;
    ser = p->s;
    c = a->c;
    free(a);

    qlock(ser);	/* this makes the reader wait end of initialization too */
    dfd = p->epin->dfd;
    qunlock(ser);

    ntries = 0;
    pk = nil;
    for(;;) {
        if (pk == nil)
            pk = emallocz(sizeof(Packser), 1);
Eagain:
        rcount = read(dfd, pk->b, sizeof pk->b);
        if(serialdebug > 5)
            dsprint(2, "%d %#ux%#ux ", rcount, p->data[0],
                    p->data[1]);

        if(rcount < 0) {
            if(ntries++ > 100)
                break;
            qlock(ser);
            recov = serialrecover(ser, p, nil, "epreader: bulkin error");
            qunlock(ser);
            if(recov >= 0)
                goto Eagain;
        }
        if(rcount == 0)
            continue;
        if(rcount >= ser->inhdrsz) {
            rcount = cpdata(ser, p, pk->b, pk->b, rcount);
            if(rcount != 0) {
                pk->nb = rcount;
                cl = sendp(c, pk);
                if(cl < 0) {
                    /*
                     * if it was a time-out, I don't want
                     * to give back an error.
                     */
                    rcount = 0;
                    break;
                }
            } else
                free(pk);
            qlock(ser);
            ser->recover = 0;
            qunlock(ser);
            ntries = 0;
            pk = nil;
        }
    }

    if(rcount < 0)
        fprint(2, "%s: error reading %s: %r\n", argv0, p->name);
    free(pk);
    nbsendp(c, nil);
    if(p->w4data != nil)
        chanclose(p->w4data);
    if(p->gotdata != nil)
        chanclose(p->gotdata);
    devctl(ser->dev, "detach");
    closedev(ser->dev);
}