~kris/9p

9hist

ref: 5188277e2c1a4e93d97e323f8347315ca5747fc2 9hist/pc/ether.h -rw-r--r-- 4.1 KiB
5188277e — David du Colombier Plan 9 from Bell Labs 1993-09-01 33 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
 * All the goo for PC ethernet cards.
 */
typedef struct Card Card;
typedef struct RingBuf RingBuf;
typedef struct Type Type;
typedef struct Ctlr Ctlr;

/*
 * Hardware interface.
 */
struct Card {
	char	id[NAMELEN];		/* type of card */

	int	(*reset)(Ctlr*);
	void	(*init)(Ctlr*);
	void	(*attach)(Ctlr*);
	void	(*mode)(Ctlr*, int);

	void	*(*read)(Ctlr*, void*, ulong, ulong);
	void	*(*write)(Ctlr*, ulong, void*, ulong);

	void	(*receive)(Ctlr*);
	void	(*transmit)(Ctlr*);
	void	(*intr)(Ctlr*);
	void	(*watch)(Ctlr*);
	void	(*overflow)(Ctlr*);

	ulong	io;			/* card I/O base address */
	uchar	irq;			/* interrupt level */
	uchar	bit16;			/* true if a 16 bit interface */

	uchar	ram;			/* true if card has shared memory */
	ulong	ramstart;		/* card shared memory address start */
	ulong	ramstop;		/* card shared memory address end */

	ulong	dp8390;			/* I/O address of 8390 (if any) */
	ulong	data;			/* I/O data port if no shared memory */
	uchar	nxtpkt;			/* software bndry */
	uchar	tstart;			/* 8390 ring addresses */
	uchar	pstart;
	uchar	pstop;
};

/*
 * Software ring buffer.
 */
struct RingBuf {
	uchar	owner;
	uchar	busy;			/* unused */
	ushort	len;
	uchar	pkt[sizeof(Etherpkt)];
};

enum {
	Host		= 0,		/* buffer owned by host */
	Interface	= 1,		/* buffer owned by card */

	Nrb		= 16,		/* default number of receive buffers */
	Ntb		= 4,		/* default number of transmit buffers */
};

/*
 * One per ethernet packet type.
 */
struct Type {
	QLock;
	Netprot;			/* stat info */
	int	type;			/* ethernet type */
	int	prom;			/* promiscuous mode */
	Queue	*q;
	int	inuse;
	Ctlr	*ctlr;

	Rendez	cr;			/* rendezvous for close */
	Type	*clist;			/* close list */
};

enum {
	NType		= 9,		/* types/card */
};

/*
 * Software controller.
 */
struct Ctlr {
	QLock;

	Card	card;			/* hardware info */
	int	present;
	int	debug;

	ushort	nrb;			/* number of software receive buffers */
	ushort	ntb;			/* number of software transmit buffers */
	RingBuf *rb;			/* software receive buffers */
	RingBuf *tb;			/* software transmit buffers */

	uchar	ea[6];			/* ethernet address */
	uchar	ba[6];			/* broadcast address */

	Rendez	rr;			/* rendezvous for a receive buffer */
	ushort	rh;			/* first receive buffer belonging to host */
	ushort	ri;			/* first receive buffer belonging to card */	

	Rendez	tr;			/* rendezvous for a transmit buffer */
	QLock	tlock;			/* semaphore on th */
	ushort	th;			/* first transmit buffer belonging to host */	
	ushort	ti;			/* first transmit buffer belonging to card */
	int	tbusy;			/* transmitter is busy */	

	Type	type[NType];
	int	all;			/* number of channels listening to all packets */
	Type	*clist;			/* channels waiting to close */
	Lock	clock;			/* lock for clist */
	int	prom;			/* number of promiscuous channels */
	int	kproc;			/* true if kproc started */
	char	name[NAMELEN];		/* name of kproc */
	Network	net;

	Queue	lbq;			/* software loopback packet queue */

	int	inpackets;
	int	outpackets;
	int	crcs;			/* input crc errors */
	int	oerrs;			/* output errors */
	int	frames;			/* framing errors */
	int	overflows;		/* packet overflows */
	int	buffs;			/* buffering errors */
};

#define NEXT(x, l)	(((x)+1)%(l))
#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))

/*
 * The Western Digital 8003 and 8013 series, the NE2000
 * and the 3Com 503 all use the DP8390 Network Interface
 * Chip.
 */
extern void dp8390reset(Ctlr*);
extern void dp8390attach(Ctlr*);
extern void dp8390mode(Ctlr*, int);
extern void dp8390setea(Ctlr*);
extern void *dp8390read(Ctlr*, void*, ulong, ulong);
extern void *dp8390write(Ctlr*, ulong, void*, ulong);
extern void dp8390receive(Ctlr*);
extern void dp8390transmit(Ctlr*);
extern void dp8390intr(Ctlr*);
extern void dp8390watch(Ctlr*);
extern void dp8390overflow(Ctlr*);

extern void dp8390debug(Ctlr*);

/*
 * The DP8390 needs some time between successive 
 * chip selects, so we need special I/O routines.
 * See l.s.
 * These routines only need to be used for accessing
 * the chip registers. Data I/O, either through
 * remote DMA or shared memory, can use the normal
 * routines.
 */
extern int dp8390inb(ulong);
extern void dp8390outb(ulong, uchar);

enum {
	Dp8390BufSz	= 256,		/* hardware ring buffer size */
};