|
|
1.1 ! root 1: #include "ds_oskit.h" ! 2: ! 3: #include <device/net_io.h> ! 4: #include <device/if_ether.h> ! 5: ! 6: #include <stddef.h> ! 7: #include <string.h> ! 8: #include <oskit/dev/net.h> ! 9: #include <oskit/dev/ethernet.h> ! 10: ! 11: ! 12: io_return_t ! 13: ds_net_get_status (device_t dev, dev_flavor_t flavor, dev_status_t status, ! 14: mach_msg_type_number_t *status_count) ! 15: { ! 16: oskit_error_t rc; ! 17: oskit_etherdev_t *eth; ! 18: ! 19: rc = oskit_device_query (dev->com_device, &oskit_etherdev_iid, ! 20: (void **) ð); ! 21: if (OSKIT_FAILED (rc)) ! 22: return D_INVALID_OPERATION; /* XXX we only support ethernet devices */ ! 23: ! 24: switch (flavor) ! 25: { ! 26: case NET_ADDRESS: ! 27: { ! 28: #define WORDS ((OSKIT_ETHERDEV_ADDR_SIZE + sizeof (int) - 1) / sizeof (int)) ! 29: ! 30: if (*status_count < WORDS) ! 31: { ! 32: oskit_etherdev_release (eth); ! 33: return D_INVALID_OPERATION; ! 34: } ! 35: *status_count = WORDS; ! 36: ! 37: bzero (status, OSKIT_ETHERDEV_ADDR_SIZE); ! 38: oskit_etherdev_getaddr (eth, (void *) status); ! 39: oskit_etherdev_release (eth); ! 40: ! 41: status[0] = ntohl (status[0]); ! 42: status[1] = ntohl (status[1]); ! 43: ! 44: return D_SUCCESS; ! 45: } ! 46: ! 47: case NET_STATUS: ! 48: { ! 49: struct net_status *ns = (void *) status; ! 50: ! 51: oskit_etherdev_release (eth); ! 52: ! 53: if (*status_count < NET_STATUS_COUNT) ! 54: return D_INVALID_OPERATION; ! 55: *status_count = NET_STATUS_COUNT; ! 56: ! 57: ns->header_format = HDR_ETHERNET; ! 58: ns->min_packet_size = ns->header_size = sizeof (struct ether_header); ! 59: ns->max_packet_size = sizeof (struct ether_header) + ETHERMTU; ! 60: ns->address_size = OSKIT_ETHERDEV_ADDR_SIZE; ! 61: ns->flags = IFF_UP|IFF_RUNNING|IFF_BROADCAST; ! 62: ns->mapped_size = 0; ! 63: ! 64: return D_SUCCESS; ! 65: } ! 66: } ! 67: ! 68: oskit_etherdev_release (eth); ! 69: return D_INVALID_OPERATION; ! 70: } ! 71: ! 72: io_return_t ! 73: ds_net_set_filter (device_t dev, ipc_port_t port, int priority, ! 74: filter_t *filter, unsigned filter_count) ! 75: { ! 76: return net_set_filter (&dev->com.net.ifnet, ! 77: port, priority, filter, filter_count); ! 78: } ! 79: ! 80: ! 81: #if 0 ! 82: io_return_t ! 83: ds_net_write (device_t dev, ipc_port_t reply_port, ! 84: mach_msg_type_name_t reply_port_type, dev_mode_t mode, ! 85: recnum_t recnum, io_buf_ptr_t data, unsigned int count, ! 86: int *bytes_written) ! 87: { ! 88: oskit_error_t rc; ! 89: io_return_t err; ! 90: oskit_u32_t wrote; ! 91: vm_offset_t addr; ! 92: oskit_bufio_t *bio; ! 93: ! 94: if (count < sizeof (struct ether_header) || ! 95: count > sizeof (struct ether_header) + ETHERMTU) ! 96: return D_INVALID_SIZE; ! 97: ! 98: err = vm_map_copyout (device_io_map, &addr, (vm_map_copy_t) data); ! 99: if (err != KERN_SUCCESS) ! 100: return err; ! 101: ! 102: ! 103: } ! 104: #endif ! 105: ! 106: /* XXX ! 107: The oskit network drivers want to call our bufio object from interrupt ! 108: handlers. This makes it impractical for us to do anything fancy in ! 109: there, like map the VM on demand--we can't do that from interrupt level! ! 110: So we rely on the outbound netio_push to see bufio_map fail and copy out ! 111: the data without attempting to save a reference to the bufio COM object. */ ! 112: ! 113: struct bufio_impl ! 114: { ! 115: oskit_bufio_t ioi; ! 116: char *buf; ! 117: oskit_size_t size; ! 118: }; ! 119: ! 120: static OSKIT_COMDECL ! 121: bufio_query(oskit_bufio_t *io, const oskit_iid_t *iid, void **out_ihandle) ! 122: { panic(__FUNCTION__); } ! 123: ! 124: static OSKIT_COMDECL_U ! 125: bufio_addref(oskit_bufio_t *io) ! 126: { panic(__FUNCTION__); } ! 127: ! 128: static OSKIT_COMDECL_U ! 129: bufio_release(oskit_bufio_t *io) ! 130: { panic(__FUNCTION__); } ! 131: ! 132: static OSKIT_COMDECL_U ! 133: bufio_getblocksize(oskit_bufio_t *io) ! 134: { ! 135: return 1; ! 136: } ! 137: ! 138: static OSKIT_COMDECL ! 139: bufio_read(oskit_bufio_t *io, void *dest, oskit_off_t offset, ! 140: oskit_size_t count, oskit_size_t *out_actual) ! 141: { ! 142: struct bufio_impl *b = (struct bufio_impl *) io; ! 143: ! 144: if (offset >= b->size) ! 145: return OSKIT_EINVAL; ! 146: if (offset + count > b->size) ! 147: count = b->size - offset; ! 148: ! 149: memcpy (dest, b->buf + offset, count); ! 150: *out_actual = count; ! 151: return 0; ! 152: } ! 153: ! 154: static OSKIT_COMDECL ! 155: bufio_write(oskit_bufio_t *io, const void *src, oskit_off_t offset, ! 156: oskit_size_t count, oskit_size_t *out_actual) ! 157: { panic(__FUNCTION__); } ! 158: ! 159: static OSKIT_COMDECL ! 160: bufio_getsize(oskit_bufio_t *io, oskit_off_t *out_size) ! 161: { ! 162: struct bufio_impl *b = (struct bufio_impl *) io; ! 163: ! 164: *out_size = b->size; ! 165: return 0; ! 166: } ! 167: ! 168: static OSKIT_COMDECL ! 169: bufio_setsize(oskit_bufio_t *io, oskit_off_t size) ! 170: { return OSKIT_E_NOTIMPL; } ! 171: ! 172: ! 173: static OSKIT_COMDECL ! 174: bufio_map(oskit_bufio_t *io, void **out_addr, ! 175: oskit_off_t offset, oskit_size_t count) ! 176: { return OSKIT_E_NOTIMPL; } ! 177: ! 178: static OSKIT_COMDECL ! 179: bufio_unmap(oskit_bufio_t *io, void *addr, oskit_off_t offset, oskit_size_t count) ! 180: { return OSKIT_E_NOTIMPL; } ! 181: ! 182: static OSKIT_COMDECL ! 183: bufio_wire(oskit_bufio_t *io, oskit_addr_t *out_physaddr, ! 184: oskit_off_t offset, oskit_size_t count) ! 185: { ! 186: return OSKIT_E_NOTIMPL; ! 187: } ! 188: ! 189: static OSKIT_COMDECL ! 190: bufio_unwire(oskit_bufio_t *io, oskit_addr_t phys_addr, ! 191: oskit_off_t offset, oskit_size_t count) ! 192: { ! 193: return OSKIT_E_NOTIMPL; ! 194: } ! 195: ! 196: static OSKIT_COMDECL ! 197: bufio_copy(oskit_bufio_t *io, oskit_off_t offset, oskit_size_t count, ! 198: oskit_bufio_t **out_io) ! 199: { ! 200: return OSKIT_E_NOTIMPL; ! 201: } ! 202: ! 203: ! 204: static struct oskit_bufio_ops bio_ops = { ! 205: bufio_query, bufio_addref, bufio_release, ! 206: bufio_getblocksize, ! 207: bufio_read, bufio_write, ! 208: bufio_getsize, bufio_setsize, ! 209: bufio_map, bufio_unmap, ! 210: bufio_wire, bufio_unwire, ! 211: bufio_copy ! 212: }; ! 213: ! 214: ! 215: io_return_t ! 216: ds_net_write_inband (device_t dev, ipc_port_t reply_port, ! 217: mach_msg_type_name_t reply_port_type, dev_mode_t mode, ! 218: recnum_t recnum, io_buf_ptr_t data, unsigned int count, ! 219: int *bytes_written) ! 220: { ! 221: oskit_error_t rc; ! 222: struct bufio_impl bio = { { &bio_ops }, data, count }; ! 223: ! 224: if (count < sizeof (struct ether_header) || ! 225: count > sizeof (struct ether_header) + ETHERMTU) ! 226: return D_INVALID_SIZE; ! 227: ! 228: rc = oskit_netio_push (dev->com.net.sendi, &bio.ioi, count); ! 229: *bytes_written = count; ! 230: ! 231: return oskit_to_mach_error (rc); ! 232: } ! 233: ! 234: ! 235: const struct device_ops net_device_ops = ! 236: { ! 237: write_inband: ds_net_write_inband, ! 238: set_filter: ds_net_set_filter, ! 239: get_status: ds_net_get_status, ! 240: }; ! 241: ! 242: ! 243: static device_t ! 244: recv_netio_device (oskit_netio_t *recvi) ! 245: { ! 246: return (device_t) ((char *) recvi - offsetof (struct device, com.net.recvi)); ! 247: } ! 248: ! 249: static OSKIT_COMDECL ! 250: net_query(oskit_netio_t *io, const oskit_iid_t *iid, void **out_ihandle) ! 251: { ! 252: device_t dev = recv_netio_device (io); ! 253: ! 254: if (memcmp(iid, &oskit_iunknown_iid, sizeof(*iid)) == 0 || ! 255: memcmp(iid, &oskit_netio_iid, sizeof(*iid)) == 0) { ! 256: *out_ihandle = &dev->com.net.recvi; ! 257: device_reference (dev); ! 258: return 0; ! 259: } ! 260: ! 261: *out_ihandle = 0; ! 262: return OSKIT_E_NOINTERFACE; ! 263: } ! 264: ! 265: static OSKIT_COMDECL_U ! 266: net_addref(oskit_netio_t *io) ! 267: { ! 268: device_t dev = recv_netio_device (io); ! 269: device_reference (dev); ! 270: return dev->ref_count; ! 271: } ! 272: ! 273: static OSKIT_COMDECL_U ! 274: net_release(oskit_netio_t *io) ! 275: { ! 276: device_t dev = recv_netio_device (io); ! 277: oskit_u32_t n = dev->ref_count - 1; ! 278: device_deallocate (dev); ! 279: return n; ! 280: } ! 281: ! 282: static OSKIT_COMDECL ! 283: net_push(oskit_netio_t *ioi, oskit_bufio_t *b, oskit_size_t pkt_size) ! 284: { ! 285: device_t dev = recv_netio_device (ioi); ! 286: ipc_kmsg_t kmsg; ! 287: struct ether_header *eh; ! 288: struct packet_header *ph; ! 289: oskit_error_t rc; ! 290: oskit_size_t n; ! 291: ! 292: /* Allocate a kernel message buffer. */ ! 293: kmsg = net_kmsg_get (); ! 294: if (!kmsg) ! 295: /* No buffer, drop packet. */ ! 296: return 0; ! 297: ! 298: /* Copy packet into message buffer. */ ! 299: eh = (struct ether_header *) (net_kmsg (kmsg)->header); ! 300: ph = (struct packet_header *) (net_kmsg (kmsg)->packet); ! 301: ! 302: rc = oskit_bufio_read (b, eh, 0, sizeof (struct ether_header), &n); ! 303: if (rc || n != sizeof (struct ether_header)) ! 304: panic("oskit_bufio_read: %x\n", rc); ! 305: rc = oskit_bufio_read (b, ph + 1, sizeof (struct ether_header), ! 306: pkt_size - sizeof (struct ether_header), &n); ! 307: if (rc || n != pkt_size - sizeof (struct ether_header)) ! 308: panic("oskit_bufio_read: %x\n", rc); ! 309: ! 310: ph->type = eh->ether_type; ! 311: ph->length = (sizeof (struct packet_header) ! 312: + pkt_size - sizeof (struct ether_header)); ! 313: ! 314: /* Pass packet up to the microkernel. */ ! 315: net_packet (&dev->com.net.ifnet, kmsg, ph->length, ethernet_priority (kmsg)); ! 316: ! 317: return 0; ! 318: } ! 319: ! 320: static struct oskit_netio_ops recv_netio_ops = ! 321: { net_query, net_addref, net_release, net_push }; ! 322: ! 323: ! 324: oskit_error_t ! 325: ds_netdev_open (device_t dev, oskit_netdev_t *netdev) ! 326: { ! 327: oskit_error_t rc; ! 328: struct ifnet *const ifp = &dev->com.net.ifnet; ! 329: ! 330: if_init_queues (ifp); ! 331: ! 332: dev->com.net.recvi.ops = &recv_netio_ops; ! 333: ! 334: rc = oskit_netdev_open (netdev, 0, &dev->com.net.recvi, &dev->com.net.sendi); ! 335: ! 336: return rc; ! 337: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.