~kris/9p

9hist

ref: 7bb4c06a28547f9aaed057eab1cd86d6b15cc0c6 9hist/pc/ns16552.h -rw-r--r-- 3.2 KiB
7bb4c06a — David du Colombier Plan 9 from Bell Labs 1996-01-11 30 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
/*
 *  PC specific code for the ns16552.  It includes support for the 2 built
 *  in uarts plus up to 5 MP-008 8 uart ISA cards.
 */
enum
{
	Maxcard= 5,		/* max serial cards */
	UartFREQ= 1843200,

	Serial=	0,
	Modem=	1,
};

#define uartwrreg(u,r,v)	outb((u)->port + r, (u)->sticky[r] | (v))
#define uartrdreg(u,r)		inb((u)->port + r)

void	ns16552setup(ulong, ulong, char*);

/*
 *  definition of an optional serial card
 */
typedef struct Scard
{
	ISAConf;	/* card configuration */
	int	first;	/* number of first port */
} Scard;
static Scard *scard[Maxcard]; 	/* configs for the serial card */

/* power management currently only makes sense on the AT&T safari */
static void
uartpower(int dev, int onoff)
{
	switch(dev){
	case Modem:
		if(modem(onoff) < 0)
			print("can't turn %s modem speaker\n", onoff?"on":"off");
		break;
	case Serial:
		if(serial(onoff) < 0)
			print("can't turn %s serial port power\n", onoff?"on":"off");
		break;
	}
}

/*
 *  handle an interrupt to a single uart
 */
static void
ns16552intrx(Ureg *ur, void *arg)
{
	USED(ur);

	ns16552intr((ulong)arg);
}

/*
 *  interrupts from the multiport card, MP-008.  A polling port
 *  tells which of 8 devices interrupted.
 */
static void
mp008intr(Ureg *ur, void *arg)
{
	int i, loops;
	uchar n;
	Scard *mp;

	USED(ur);
	mp = arg;
	for(loops = 0; loops < 1024; loops++){
		n = ~inb(mp->mem);
		if(n == 0)
			return;
		for(i = 0; n; i++){
			if(n & 1)
				ns16552intrx(ur, (void*)(mp->first+i));
			n >>= 1;
		}
	}
}

/*
 *  install the uarts (called by reset)
 */
void
ns16552install(void)
{
	int i, j, port, nscard;
	char *p;
	Scard *sc;
	char name[NAMELEN];
	static int already;

	if(already)
		return;
	already = 1;

	/* first two ports are always there and always the normal frequency */
	ns16552setup(0x3F8, UartFREQ, "eia0");
	setvec(Uart0vec, ns16552intrx, (void*)0);
	ns16552setup(0x2F8, UartFREQ, "eia1");
	setvec(Uart1vec, ns16552intrx, (void*)1);

	/* set up a serial console */
	p = getconf("console");
	if(p)
		ns16552special(atoi(p), 9600, &kbdq, &printq, kbdcr2nl);

	/* the rest come out of plan9.ini */
	nscard = 0;
	for(i = 0; i < Maxcard; i++){
		sc = scard[nscard] = xalloc(sizeof(Scard));
		if(isaconfig("serial", i, sc) == 0){
			xfree(sc);
			scard[nscard] = 0;
			continue;
		}

		if(cistrcmp(sc->type, "MP008") == 0){
			/*
			 *  port gives base port address for uarts
			 *  irq is interrupt
			 *  mem is the polling port
			 *  size is the number of serial ports on the same polling port
			 *  freq is the baud rate generator frequency
			 */
			if(sc->size == 0)
				sc->size = 8;
			if(sc->freq == 0)
				sc->freq = UartFREQ;
			sc->first = nuart;
			setvec(Int0vec+sc->irq, mp008intr, sc);
			port = sc->port;
			for(j=0; j < sc->size; j++){
				sprint(name, "eia%d%2.2d", nscard, j);
				ns16552setup(port, sc->freq, name);
				port += 8;
			}
		} else if(cistrcmp(sc->type, "com") == 0){
			/*
			 *  port gives base port address for the uart
			 *  irq is interrupt
			 *  freq is the baud rate generator frequency
			 */
			if(sc->freq == 0)
				sc->freq = UartFREQ;
			sprint(name, "eia%d00", nscard);
			ns16552setup(sc->port, sc->freq, name);
			setvec(Int0vec+sc->irq, ns16552intrx, (void*)(nuart-1));
		}
		nscard++;
	}
}