xref: /minix3/minix/lib/libnetdriver/portio.c (revision 7c48de6cc4c6d56f2277d378dba01dbac8a8c3b9)
1dbcce9ddSDavid van Moolenbroek /*
2dbcce9ddSDavid van Moolenbroek  * Port-based I/O routines.  These are in a separate module because most
3dbcce9ddSDavid van Moolenbroek  * drivers will not use them, and system services are statically linked.
4dbcce9ddSDavid van Moolenbroek  */
5dbcce9ddSDavid van Moolenbroek #include <minix/drivers.h>
6dbcce9ddSDavid van Moolenbroek #include <minix/netdriver.h>
7dbcce9ddSDavid van Moolenbroek #include <assert.h>
8dbcce9ddSDavid van Moolenbroek 
9dbcce9ddSDavid van Moolenbroek #include "netdriver.h"
10dbcce9ddSDavid van Moolenbroek 
11dbcce9ddSDavid van Moolenbroek /*
12dbcce9ddSDavid van Moolenbroek  * Port-based I/O byte sequence copy routine.
13dbcce9ddSDavid van Moolenbroek  */
14dbcce9ddSDavid van Moolenbroek static void
netdriver_portb(struct netdriver_data * data,size_t off,long port,size_t size,int portin)15dbcce9ddSDavid van Moolenbroek netdriver_portb(struct netdriver_data * data, size_t off, long port,
16dbcce9ddSDavid van Moolenbroek 	size_t size, int portin)
17dbcce9ddSDavid van Moolenbroek {
18dbcce9ddSDavid van Moolenbroek 	size_t chunk;
19dbcce9ddSDavid van Moolenbroek 	unsigned int i;
20dbcce9ddSDavid van Moolenbroek 	int r, req;
21dbcce9ddSDavid van Moolenbroek 
22dbcce9ddSDavid van Moolenbroek 	off = netdriver_prepare_copy(data, off, size, &i);
23dbcce9ddSDavid van Moolenbroek 
24dbcce9ddSDavid van Moolenbroek 	req = portin ? DIO_SAFE_INPUT_BYTE : DIO_SAFE_OUTPUT_BYTE;
25dbcce9ddSDavid van Moolenbroek 
26dbcce9ddSDavid van Moolenbroek 	while (size > 0) {
27dbcce9ddSDavid van Moolenbroek 		chunk = data->iovec[i].iov_size - off;
28dbcce9ddSDavid van Moolenbroek 		if (chunk > size)
29dbcce9ddSDavid van Moolenbroek 			chunk = size;
30dbcce9ddSDavid van Moolenbroek 		assert(chunk > 0);
31dbcce9ddSDavid van Moolenbroek 
32dbcce9ddSDavid van Moolenbroek 		if ((r = sys_sdevio(req, port, data->endpt,
33dbcce9ddSDavid van Moolenbroek 		    (void *)data->iovec[i].iov_grant, chunk, off)) != OK)
34dbcce9ddSDavid van Moolenbroek 			panic("netdriver: port I/O failed: %d", r);
35dbcce9ddSDavid van Moolenbroek 
36dbcce9ddSDavid van Moolenbroek 		i++;
37dbcce9ddSDavid van Moolenbroek 		off = 0;
38dbcce9ddSDavid van Moolenbroek 		size -= chunk;
39dbcce9ddSDavid van Moolenbroek 	}
40dbcce9ddSDavid van Moolenbroek }
41dbcce9ddSDavid van Moolenbroek 
42dbcce9ddSDavid van Moolenbroek /*
43dbcce9ddSDavid van Moolenbroek  * Transfer bytes from hardware to a destination buffer using port-based I/O.
44dbcce9ddSDavid van Moolenbroek  */
45dbcce9ddSDavid van Moolenbroek void
netdriver_portinb(struct netdriver_data * data,size_t off,long port,size_t size)46dbcce9ddSDavid van Moolenbroek netdriver_portinb(struct netdriver_data * data, size_t off, long port,
47dbcce9ddSDavid van Moolenbroek 	size_t size)
48dbcce9ddSDavid van Moolenbroek {
49dbcce9ddSDavid van Moolenbroek 
50dbcce9ddSDavid van Moolenbroek 	return netdriver_portb(data, off, port, size, TRUE /*portin*/);
51dbcce9ddSDavid van Moolenbroek }
52dbcce9ddSDavid van Moolenbroek 
53dbcce9ddSDavid van Moolenbroek /*
54dbcce9ddSDavid van Moolenbroek  * Transfer bytes from a source buffer to hardware using port-based I/O.
55dbcce9ddSDavid van Moolenbroek  */
56dbcce9ddSDavid van Moolenbroek void
netdriver_portoutb(struct netdriver_data * data,size_t off,long port,size_t size)57dbcce9ddSDavid van Moolenbroek netdriver_portoutb(struct netdriver_data * data, size_t off, long port,
58dbcce9ddSDavid van Moolenbroek 	size_t size)
59dbcce9ddSDavid van Moolenbroek {
60dbcce9ddSDavid van Moolenbroek 
61dbcce9ddSDavid van Moolenbroek 	return netdriver_portb(data, off, port, size, FALSE /*portin*/);
62dbcce9ddSDavid van Moolenbroek }
63dbcce9ddSDavid van Moolenbroek 
64dbcce9ddSDavid van Moolenbroek /*
65dbcce9ddSDavid van Moolenbroek  * Transfer words from hardware to a destination buffer using port-based I/O.
66dbcce9ddSDavid van Moolenbroek  */
67dbcce9ddSDavid van Moolenbroek void
netdriver_portinw(struct netdriver_data * data,size_t off,long port,size_t size)68dbcce9ddSDavid van Moolenbroek netdriver_portinw(struct netdriver_data * data, size_t off, long port,
69dbcce9ddSDavid van Moolenbroek 	size_t size)
70dbcce9ddSDavid van Moolenbroek {
71*7c48de6cSDavid van Moolenbroek 	uint16_t buf;
72dbcce9ddSDavid van Moolenbroek 	uint32_t value;
73dbcce9ddSDavid van Moolenbroek 	size_t chunk;
74dbcce9ddSDavid van Moolenbroek 	unsigned int i;
75dbcce9ddSDavid van Moolenbroek 	int r, odd_byte;
76dbcce9ddSDavid van Moolenbroek 
77dbcce9ddSDavid van Moolenbroek 	off = netdriver_prepare_copy(data, off, size, &i);
78dbcce9ddSDavid van Moolenbroek 
79dbcce9ddSDavid van Moolenbroek 	odd_byte = 0;
80dbcce9ddSDavid van Moolenbroek 	while (size > 0) {
81dbcce9ddSDavid van Moolenbroek 		chunk = data->iovec[i].iov_size - off;
82dbcce9ddSDavid van Moolenbroek 		if (chunk > size)
83dbcce9ddSDavid van Moolenbroek 			chunk = size;
84dbcce9ddSDavid van Moolenbroek 		assert(chunk > 0);
85dbcce9ddSDavid van Moolenbroek 
86dbcce9ddSDavid van Moolenbroek 		if (odd_byte) {
87dbcce9ddSDavid van Moolenbroek 			if ((r = sys_safecopyto(data->endpt,
88*7c48de6cSDavid van Moolenbroek 			    data->iovec[i].iov_grant, off,
89*7c48de6cSDavid van Moolenbroek 			    (vir_bytes)&((char *)&buf)[1], 1)) != OK)
90dbcce9ddSDavid van Moolenbroek 				panic("netdriver: unable to copy data: %d", r);
91dbcce9ddSDavid van Moolenbroek 
92dbcce9ddSDavid van Moolenbroek 			off++;
93dbcce9ddSDavid van Moolenbroek 			size--;
94dbcce9ddSDavid van Moolenbroek 			chunk--;
95dbcce9ddSDavid van Moolenbroek 		}
96dbcce9ddSDavid van Moolenbroek 
97dbcce9ddSDavid van Moolenbroek 		odd_byte = chunk & 1;
98dbcce9ddSDavid van Moolenbroek 		chunk -= odd_byte;
99dbcce9ddSDavid van Moolenbroek 
100dbcce9ddSDavid van Moolenbroek 		if (chunk > 0) {
101dbcce9ddSDavid van Moolenbroek 			if ((r = sys_safe_insw(port, data->endpt,
102dbcce9ddSDavid van Moolenbroek 			    data->iovec[i].iov_grant, off, chunk)) != OK)
103dbcce9ddSDavid van Moolenbroek 				panic("netdriver: port input failed: %d", r);
104dbcce9ddSDavid van Moolenbroek 
105dbcce9ddSDavid van Moolenbroek 			off += chunk;
106dbcce9ddSDavid van Moolenbroek 			size -= chunk;
107dbcce9ddSDavid van Moolenbroek 		}
108dbcce9ddSDavid van Moolenbroek 
109dbcce9ddSDavid van Moolenbroek 		if (odd_byte) {
110dbcce9ddSDavid van Moolenbroek 			if ((r = sys_inw(port, &value)) != OK)
111dbcce9ddSDavid van Moolenbroek 				panic("netdriver: port input failed: %d", r);
112*7c48de6cSDavid van Moolenbroek 			buf = (uint16_t)value;
113dbcce9ddSDavid van Moolenbroek 
114dbcce9ddSDavid van Moolenbroek 			if ((r = sys_safecopyto(data->endpt,
115*7c48de6cSDavid van Moolenbroek 			    data->iovec[i].iov_grant, off,
116*7c48de6cSDavid van Moolenbroek 			    (vir_bytes)&((char *)&buf)[0], 1)) != OK)
117dbcce9ddSDavid van Moolenbroek 				panic("netdriver: unable to copy data: %d", r);
118dbcce9ddSDavid van Moolenbroek 
119dbcce9ddSDavid van Moolenbroek 			size--;
120dbcce9ddSDavid van Moolenbroek 		}
121dbcce9ddSDavid van Moolenbroek 
122dbcce9ddSDavid van Moolenbroek 		i++;
123dbcce9ddSDavid van Moolenbroek 		off = 0;
124dbcce9ddSDavid van Moolenbroek 	}
125dbcce9ddSDavid van Moolenbroek }
126dbcce9ddSDavid van Moolenbroek 
127dbcce9ddSDavid van Moolenbroek /*
128dbcce9ddSDavid van Moolenbroek  * Transfer words from a source buffer to hardware using port-based I/O.
129dbcce9ddSDavid van Moolenbroek  */
130dbcce9ddSDavid van Moolenbroek void
netdriver_portoutw(struct netdriver_data * data,size_t off,long port,size_t size)131dbcce9ddSDavid van Moolenbroek netdriver_portoutw(struct netdriver_data * data, size_t off, long port,
132dbcce9ddSDavid van Moolenbroek 	size_t size)
133dbcce9ddSDavid van Moolenbroek {
134*7c48de6cSDavid van Moolenbroek 	uint16_t buf;
135dbcce9ddSDavid van Moolenbroek 	size_t chunk;
136dbcce9ddSDavid van Moolenbroek 	unsigned int i;
137dbcce9ddSDavid van Moolenbroek 	int r, odd_byte;
138dbcce9ddSDavid van Moolenbroek 
139dbcce9ddSDavid van Moolenbroek 	off = netdriver_prepare_copy(data, off, size, &i);
140dbcce9ddSDavid van Moolenbroek 
141dbcce9ddSDavid van Moolenbroek 	odd_byte = 0;
142dbcce9ddSDavid van Moolenbroek 	while (size > 0) {
143dbcce9ddSDavid van Moolenbroek 		chunk = data->iovec[i].iov_size - off;
144dbcce9ddSDavid van Moolenbroek 		if (chunk > size)
145dbcce9ddSDavid van Moolenbroek 			chunk = size;
146dbcce9ddSDavid van Moolenbroek 		assert(chunk > 0);
147dbcce9ddSDavid van Moolenbroek 
148dbcce9ddSDavid van Moolenbroek 		if (odd_byte) {
149dbcce9ddSDavid van Moolenbroek 			if ((r = sys_safecopyfrom(data->endpt,
150*7c48de6cSDavid van Moolenbroek 			    data->iovec[i].iov_grant, off,
151*7c48de6cSDavid van Moolenbroek 			    (vir_bytes)&((char *)&buf)[1], 1)) != OK)
152dbcce9ddSDavid van Moolenbroek 				panic("netdriver: unable to copy data: %d", r);
153dbcce9ddSDavid van Moolenbroek 
154*7c48de6cSDavid van Moolenbroek 			if ((r = sys_outw(port, buf)) != OK)
155dbcce9ddSDavid van Moolenbroek 				panic("netdriver: port output failed: %d", r);
156dbcce9ddSDavid van Moolenbroek 
157dbcce9ddSDavid van Moolenbroek 			off++;
158dbcce9ddSDavid van Moolenbroek 			size--;
159dbcce9ddSDavid van Moolenbroek 			chunk--;
160dbcce9ddSDavid van Moolenbroek 		}
161dbcce9ddSDavid van Moolenbroek 
162dbcce9ddSDavid van Moolenbroek 		odd_byte = chunk & 1;
163dbcce9ddSDavid van Moolenbroek 		chunk -= odd_byte;
164dbcce9ddSDavid van Moolenbroek 
165dbcce9ddSDavid van Moolenbroek 		if (chunk > 0) {
166dbcce9ddSDavid van Moolenbroek 			if ((r = sys_safe_outsw(port, data->endpt,
167dbcce9ddSDavid van Moolenbroek 			    data->iovec[i].iov_grant, off, chunk)) != OK)
168dbcce9ddSDavid van Moolenbroek 				panic("netdriver: port output failed: %d", r);
169dbcce9ddSDavid van Moolenbroek 
170dbcce9ddSDavid van Moolenbroek 			off += chunk;
171dbcce9ddSDavid van Moolenbroek 			size -= chunk;
172dbcce9ddSDavid van Moolenbroek 		}
173dbcce9ddSDavid van Moolenbroek 
174dbcce9ddSDavid van Moolenbroek 		if (odd_byte) {
175dbcce9ddSDavid van Moolenbroek 			if ((r = sys_safecopyfrom(data->endpt,
176*7c48de6cSDavid van Moolenbroek 			    data->iovec[i].iov_grant, off,
177*7c48de6cSDavid van Moolenbroek 			    (vir_bytes)&((char *)&buf)[0], 1)) != OK)
178dbcce9ddSDavid van Moolenbroek 				panic("netdriver: unable to copy data: %d", r);
179dbcce9ddSDavid van Moolenbroek 
180dbcce9ddSDavid van Moolenbroek 			size--;
181dbcce9ddSDavid van Moolenbroek 		}
182dbcce9ddSDavid van Moolenbroek 
183dbcce9ddSDavid van Moolenbroek 		i++;
184dbcce9ddSDavid van Moolenbroek 		off = 0;
185dbcce9ddSDavid van Moolenbroek 	}
186dbcce9ddSDavid van Moolenbroek 
187dbcce9ddSDavid van Moolenbroek 	if (odd_byte) {
188*7c48de6cSDavid van Moolenbroek 		((char *)&buf)[1] = 0;
189dbcce9ddSDavid van Moolenbroek 
190*7c48de6cSDavid van Moolenbroek 		if ((r = sys_outw(port, buf)) != OK)
191dbcce9ddSDavid van Moolenbroek 			panic("netdriver: port output failed: %d", r);
192dbcce9ddSDavid van Moolenbroek 	}
193dbcce9ddSDavid van Moolenbroek }
194