9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* Re: [9fans] devpcidev.c
@ 2002-02-28  0:28 David Gordon Hogan
  0 siblings, 0 replies; 4+ messages in thread
From: David Gordon Hogan @ 2002-02-28  0:28 UTC (permalink / raw)
  To: 9fans

audio%g ls -l /dev/pci
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.0.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.0.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.1.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.1.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.20.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.20.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.3.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.3.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.4.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.4.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.7.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.7.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.7.1ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.7.1raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.7.2ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.7.2raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.7.3ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.7.3raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/1.0.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/1.0.0raw
audio%g cat /dev/pci/*ctl
class 06 subclass 00 piclass 00 vid 8086 did 7190 intl 0
class 06 subclass 04 piclass 00 vid 8086 did 7191 intl 0
class 02 subclass 00 piclass 00 vid 8086 did 1229 intl 10
class 04 subclass 01 piclass 00 vid 1073 did 000c intl 11
class 02 subclass 00 piclass 00 vid 8086 did 1229 intl 11
class 06 subclass 01 piclass 00 vid 8086 did 7110 intl 0
class 01 subclass 01 piclass 80 vid 8086 did 7111 intl 0
class 0c subclass 03 piclass 00 vid 8086 did 7112 intl 11
class 06 subclass 80 piclass 00 vid 8086 did 7113 intl 0
class 03 subclass 00 piclass 00 vid 1002 did 4742 intl 11



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9fans] devpcidev.c
@ 2002-02-28  0:49 David Gordon Hogan
  0 siblings, 0 replies; 4+ messages in thread
From: David Gordon Hogan @ 2002-02-28  0:49 UTC (permalink / raw)
  To: 9fans

> oops :)

To be fair, "/dev/pci" is actually served by devpnp.c, a
driver I wrote for mucking with ISA PnP devices.  I added
PCI as an afterthought.



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9fans] devpcidev.c
@ 2002-02-28  0:35 andrey mirtchovski
  0 siblings, 0 replies; 4+ messages in thread
From: andrey mirtchovski @ 2002-02-28  0:35 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 11 bytes --]

oops :)


[-- Attachment #2: Type: message/rfc822, Size: 3722 bytes --]

From: David Gordon Hogan <dhog@plan9.bell-labs.com>
To: 9fans@cse.psu.edu
Subject: Re: [9fans] devpcidev.c
Date: Wed, 27 Feb 2002 19:28:59 -0500
Message-ID: <628cd61f9c2e1bfc4c42cc5e169965fa@plan9.bell-labs.com>

audio%g ls -l /dev/pci
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.0.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.0.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.1.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.1.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.20.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.20.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.3.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.3.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.4.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.4.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.7.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.7.0raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.7.1ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.7.1raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.7.2ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.7.2raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/0.7.3ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/0.7.3raw
--r--r--r-- $ 0 dhog dhog   0 Feb 20 19:29 /dev/pci/1.0.0ctl
--r--r--r-- $ 0 dhog dhog 128 Feb 20 19:29 /dev/pci/1.0.0raw
audio%g cat /dev/pci/*ctl
class 06 subclass 00 piclass 00 vid 8086 did 7190 intl 0
class 06 subclass 04 piclass 00 vid 8086 did 7191 intl 0
class 02 subclass 00 piclass 00 vid 8086 did 1229 intl 10
class 04 subclass 01 piclass 00 vid 1073 did 000c intl 11
class 02 subclass 00 piclass 00 vid 8086 did 1229 intl 11
class 06 subclass 01 piclass 00 vid 8086 did 7110 intl 0
class 01 subclass 01 piclass 80 vid 8086 did 7111 intl 0
class 0c subclass 03 piclass 00 vid 8086 did 7112 intl 11
class 06 subclass 80 piclass 00 vid 8086 did 7113 intl 0
class 03 subclass 00 piclass 00 vid 1002 did 4742 intl 11

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [9fans] devpcidev.c
@ 2002-02-28  0:25 andrey mirtchovski
  0 siblings, 0 replies; 4+ messages in thread
From: andrey mirtchovski @ 2002-02-28  0:25 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 3280 bytes --]

Hi, 

This little program allows me to read/write to random memory addresses
from userland.  Russ Cox indicated that he has something similar, but
since i wanted to learn how to write /dev/ stuff i decided to give it
a try myself...  I find it helpful when debugging vga (for example)
from serial console.  Maybe some of you will find it helpful for
other things :)

Something to note: it is unsafe to use peek and poke at the hardware
from userland.  There are so many ways to render your machine
inoperable that I'm not going to bother listing them here.  (Normally
a reboot fixes things, but...)  Don't take it out on me or on LANL if
your hardware chokes as a consequence of pcidev.  Do not attempt to
remove bread stuck in a plugged toaster with a knife either.
*shrug*...  You know all this, bot nevertheless you have been warned.

Pcidev (sorry, couldn't think of a better name) sits between you and
the hardware devices on your computer.  It allows the user to
read/write (standard inb, inw, inl, outb, outw, outl) using simple
shell scripts.

Pcidev could be found as a drive named #Z.  When bound to a directory
it presents itself as a sigle file named 'base'.  This file takes as
input a memory address, to which the user wants to write or read.  
Having been given an address, pcidev creates a directory named after 
the it and populates it with 6 files used for reading/writing, namely:

	inb -> read a byte
	inw -> read a word (16 bits)  
	inl -> read a long   

	outb -> write to the port (byte)
	outw -> short
	outl 	-> long

That's pretty much it.. It's really simple.

Here's a sample session with it:

----

% bind -a '#Z' /tmp/z
% cd /tmp/z
% ls
base
% echo 0x3cc > base  	# address should be a valid atol()-understandable string, 0xF, 0F, 15 -> all accepted
% ls
0x3cc				# 0x3cc is VGA's Miscellaneous Output Register
base
% cd 0x3cc
% ls
inb
inl
inw
outb
outl
outw
% cat inb
0xe3%				# no \n appended...
% cat inl
0xff0800e3%
% cd ..
% echo 0x80 > base
% rm 0x3cc
% ls
0x80				# a pci post-card. write-only
base
% cd 0x80
% echo 0xf > outb		# 0F shows on the device, 
% echo 14 > outb		# 0D shows on the device

----

That's about it.  The maximum addresses opened at a single time is 128.
Just rm some stuff to open up space (rm base will not work, of
course).

To compile a kernel with pcidev:

cd /sys/src/9/pc 
cp devpcidev.c .  
edit pcdisk and add 'pcidev' at the bottom of the 'dev' list 
mk 'CONF=9pcdisk' (or your favorite way ofdoing it) 
9fat:; cp 9pcdisk /n/9fat 
reboot...

Sorry, there is no man page for it, but there are no plans to put it
into the official distribution either :)

While discussing the 'design' with Ron Minnich another way of doing it
came up -- have a single file for input, another one for output and
manage the addresses with seek().  That way a 5-line C program could
read and report the entire status of a device.  I'm posting this
implementation because it's a bit more complex (dealing with
subdirectories, adding/deleting addresses) and not because it's
necessarily the better way to present files for inb and outb.

regards: andrey

ps: as usual, flame me privately if you don't like it or if it doesn't work..


[-- Attachment #2: devpcidev.c --]
[-- Type: text/plain, Size: 5893 bytes --]

#include "u.h"
#include "../port/lib.h" 
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"

static	char Etoomany[] = 	"too many ports opened";
static	char Enoclient[] =	"no such pci device...";

static void *pcidevbase = 0;
enum {
	Qtopdir = 0,
	Qbase,

	Qpcidir,
	Qinb,	/* reading */
	Qinw,	
	Qinl,	
	Qoutb,	/* writing */
	Qoutw,
	Qoutl,	
	
};

typedef struct Mypci Mypci;
typedef struct Devpci Devpci;

struct Mypci
{
	QLock;
	ulong base;
};

enum {
	Maxpcidev = 128,		/* looks like a good number */
};

struct Devpci 
{
	Mypci *pci[Maxpcidev];
	uint npci;
};

static Devpci devpci;

static Dirtab pcidevdir[] = {
	"inb", {Qinb}, 0, 0440,
	"inw", {Qinw}, 0, 0440,
	"inl", {Qinl}, 0, 0440,
	"outb", {Qoutb}, 0, 0220,
	"outw", {Qoutw}, 0, 0220,
	"outl", {Qoutl}, 0, 0220,
};

static Dirtab pcitopdir[] = {
	"base", {Qbase}, 0, 0220,
};

#define	QSHIFT	4	/* location in qid of client # */

#define	QID(q)		(((q).path&0x0000000F)>>0)
#define	CLIENTPATH(q)	((q&0x07FFFFFF0)>>QSHIFT)
#define	CLIENT(q)	CLIENTPATH((q).path)


Mypci*
pcislotpath(ulong path)
{
	Mypci *cl;
	int slot;

	slot = CLIENTPATH(path);
	if(slot == 0)
		return nil;
	cl = devpci.pci[slot-1];
	if(cl==0 || cl->base==0)
		return nil;
	return cl;
}


Mypci*
pcislot(Chan *c)
{
	Mypci *client;

	client = pcislotpath(c->qid.path);
	if(client == nil)
		error(Enoclient);
	return client;
}


static int
pcidevgen(Chan *c, Dirtab *tab, int x, int s, Dir *dp)
{
	int t;
	Qid q;
	ulong path;
	Mypci *cl;
	char buf[NAMELEN];
	

	USED(tab, x);
	q.vers = 0;

	if(s == DEVDOTDOT){
		switch(QID(c->qid)){
		case Qpcidir:
			cl = pcislot(c);
			sprint(buf, "0x%lux", cl->base);
			devdir(c, (Qid){CHDIR|Qtopdir, 0}, buf, 0, eve, 0500, dp);
			break;
		default:
			panic("pcidevwalk %lux", c->qid.path);
		}
		return 1;
	}


	t = QID(c->qid);
	if(t == Qtopdir){
		if(s == 0){
			q = (Qid){Qbase, 0};
			devdir(c, q, "base", 0, eve, 0600, dp);
		}
		else if(s <= devpci.npci){
			cl = devpci.pci[s-1];
			if(cl == 0)
				return 0;
			sprint(buf, "0x%lux", cl->base);
			q = (Qid){CHDIR|(s<<QSHIFT)|Qpcidir, 0};
			devdir(c, q, buf, 0, eve, 0555, dp);
			return 1;
		}
		else
			return -1;
		return 1;
	}


	path = c->qid.path&~(CHDIR|((1<<QSHIFT)-1));	/* slot component */
	q.vers = c->qid.vers;
	switch(s){
	case 0:
		q = (Qid){path|Qinb, c->qid.vers};
		devdir(c, q, "inb", 0, eve, 0200, dp);
		break;
	case 1:
		q = (Qid){path|Qinw, c->qid.vers};
		devdir(c, q, "inw", 0, eve, 0200, dp);
		break;
	case 2:
		q = (Qid){path|Qinl, c->qid.vers};
		devdir(c, q, "inl", 0, eve, 0200, dp);
		break;
	case 3:
		q = (Qid){path|Qoutb, c->qid.vers};
		devdir(c, q, "outb", 0, eve, 0400, dp);
		break;
	case 4:
		q = (Qid){path|Qoutw, c->qid.vers};
		devdir(c, q, "outw", 0, eve, 0400, dp);
		break;
	case 5:
		q = (Qid){path|Qoutl, c->qid.vers};
		devdir(c, q, "outl", 0, eve, 0400, dp);
		break;
	default:
		return -1;
	}
	return 1;

}
	
static void
pcidevreset(void)
{
}

void
pcidevinit(void)
{

	devinit();

}

static Chan*
pcidevattach(char* spec)
{
	return devattach('Z', spec);
}

int
pcidevwalk(Chan* c, char* name)
{
	return devwalk(c, name, 0,0 , pcidevgen);
}

static void
pcidevstat(Chan* c, char* dp)
{
	devstat(c, dp, pcitopdir, nelem(pcitopdir), devgen);
}

static Chan*
pcidevopen(Chan* c, int omode)
{
	return devopen(c, omode, pcitopdir, nelem(pcitopdir), devgen);
}




static long
pcidevread(Chan* c, void* a, long n, vlong)
{
	char str[16];
	int size = 0;
	ulong o;
	Mypci *cl;




	if(c->qid.path & CHDIR)
		return devdirread(c, a, n, 0, 0, pcidevgen);
	cl = pcislot(c);

	qlock(cl);
	if(waserror()){
		qunlock(cl);
		nexterror();
	}

	/* assume some things about 'a' that we probably shouldn't */
	switch(QID(c->qid)){
	case Qinb:
		size = sprint(str, "0x%2.2ux", inb(cl->base) & 0xFF);
		break;
	case Qinw:
		size = sprint(str, "0x%4.4ux", ins(cl->base) & 0xFFFF);
		break;
	case Qinl:
		size = sprint(str, "0x%8.8lux", inl(cl->base) & 0xFFFFFFFF);
		break;
	}

	qunlock(cl);
	poperror();

	o = c->offset;
	if(o >= size)
		return 0;
	if(o+n > size)
		n = size-c->offset;
	memmove(a, str+o, n);

	return n;
}


static long
pcidevwrite(Chan* c, void* a, long n, vlong off)
{
	Mypci *cl;
	ulong offset = off;


	USED(offset, n);
	if(c->qid.path & CHDIR)
		error(Eisdir);

	if(QID(c->qid) == Qbase) {
		if(devpci.npci < Maxpcidev) {
			devpci.pci[devpci.npci] = (Mypci *)malloc(sizeof(Mypci));
			devpci.pci[devpci.npci]->base = strtol(a, nil, 0);
			devpci.npci++;
			return 1;
		} else {
			error(Etoomany);
			return 0;
		}			
	}

	cl = pcislot(c);
	qlock(cl);
	switch(QID(c->qid)){
	case Qoutb:
		outb(PADDR(cl->base), atol(a) & 0xff);
		break;
	case Qoutw:
		outs(PADDR(cl->base), atol(a) & 0xffff);
		break;
	case Qoutl:
		outl(PADDR(cl->base), atol(a));
		break;
	}
	qunlock(cl);
	return 1;

}

static void
pcidevcreate(Chan *, char*, int, ulong)
{
}

static Chan *
pcidevclone(Chan *c1, Chan *c2)
{
	return devclone(c1, c2);
}

static void
pcidevremove(Chan *c)
{
	int slot;
	Mypci *cl;
	

	slot = CLIENTPATH(c->qid.path);

	if(slot == 0)
		return;	

	slot--;	/* align with pci[] */

	cl = devpci.pci[slot];

	free(cl);
	devpci.npci--;

	while (slot < devpci.npci) {
		devpci.pci[slot] = devpci.pci[slot+1];
		slot++;
	}
}

static void
pcidevclose(Chan *c) 
{
	USED(c);
}

Dev pcidevdevtab = {
	'Z',
	"pcidev",
	pcidevreset,
	devinit,
	pcidevattach,
	pcidevclone,
	pcidevwalk,
	pcidevstat,
	pcidevopen,
	pcidevcreate,
	pcidevclose,
	pcidevread,
	devbread,
	pcidevwrite,
	devbwrite,
	pcidevremove,
	devwstat,

};

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2002-02-28  0:49 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-02-28  0:28 [9fans] devpcidev.c David Gordon Hogan
  -- strict thread matches above, loose matches on Subject: below --
2002-02-28  0:49 David Gordon Hogan
2002-02-28  0:35 andrey mirtchovski
2002-02-28  0:25 andrey mirtchovski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).