~kris/9p

9hist

ref: d4d2e52a599c4150a753ae6dc6fc9e803e48eae8 9hist/pc/ns16552.h -rw-r--r-- 4.0 KiB
d4d2e52a — David du Colombier Plan 9 from Bell Labs 1999-06-20 27 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
169
170
171
172
173
/*
 *  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*, int);
void	ns16552special(int, int, Queue**, Queue**, int (*)(Queue*, int));
void	uartclock(void);
/*
 *  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((*arch->modempower)(onoff) < 0)
			print("can't turn %s modem speaker\n", onoff?"on":"off");
		break;
	case Serial:
		if((*arch->serialpower)(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*, void* arg)
{
	ns16552intr((ulong)arg);
}

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

	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(ureg, (void*)(mp->first+i));
			n >>= 1;
		}
	}
}

/*
 *  install the uarts (called by reset)
 */
void
ns16552install(void)
{
	int i, j, port, nscard;
	char *p, *q;
	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", Ns550);
	intrenable(IrqUART0, ns16552intrx, (void*)0, BUSUNKNOWN);
	ns16552setup(0x2F8, UartFREQ, "eia1", Ns550);
	intrenable(IrqUART1, ns16552intrx, (void*)1, BUSUNKNOWN);
	addclock0link(uartclock);

	/* set up a serial console */
	if(p = getconf("console")){
		port = strtol(p, &q, 0);
		if(p != q && (port == 0 || port == 1))
			ns16552special(port, 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;
			intrenable(sc->irq, mp008intr, sc, BUSUNKNOWN);
			port = sc->port;
			for(j=0; j < sc->size; j++){
				sprint(name, "eia%d%2.2d", nscard, j);
				ns16552setup(port, sc->freq, name, Ns550);
				port += 8;
			}
		} else if(cistrcmp(sc->type, "turbo650") == 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*4;
			sprint(name, "eia%d00", nscard);
			ns16552setup(sc->port, sc->freq, name, Ns650);

			/*
			 *  multiply clock speed by 4
			 */
			if(sc->mem == 0)
				outb(0x2c8, 0);
			else
				outb(sc->mem, 0);

			intrenable(sc->irq, ns16552intrx, (void*)(nuart-1), BUSUNKNOWN);
		} else if(cistrcmp(sc->type, "com") == 0 && sc->port != 0x3F8 && sc->port != 0x2F8){
			/*
			 *  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, Ns550);
			intrenable(sc->irq, ns16552intrx, (void*)(nuart-1), BUSUNKNOWN);
		}
		nscard++;
	}
}