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