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