|
|
1.1 ! root 1: /****************************************************************************** ! 2: * Copyright (c) 2011 IBM Corporation ! 3: * All rights reserved. ! 4: * This program and the accompanying materials ! 5: * are made available under the terms of the BSD License ! 6: * which accompanies this distribution, and is available at ! 7: * http://www.opensource.org/licenses/bsd-license.php ! 8: * ! 9: * Contributors: ! 10: * IBM Corporation - initial implementation ! 11: *****************************************************************************/ ! 12: ! 13: #include <stdarg.h> ! 14: #include <string.h> ! 15: #include <cache.h> ! 16: #include <byteorder.h> ! 17: #include <netdriver_int.h> ! 18: #include <libhvcall.h> ! 19: #include <virtio.h> ! 20: #include "virtio-net.h" ! 21: ! 22: ! 23: #define VIRTIOHDR_DEVICE_FEATURES 0 ! 24: #define VIRTIOHDR_GUEST_FEATURES 4 ! 25: #define VIRTIOHDR_QUEUE_ADDRESS 8 ! 26: #define VIRTIOHDR_QUEUE_SIZE 12 ! 27: #define VIRTIOHDR_QUEUE_SELECT 14 ! 28: #define VIRTIOHDR_QUEUE_NOTIFY 16 ! 29: #define VIRTIOHDR_DEVICE_STATUS 18 ! 30: #define VIRTIOHDR_ISR_STATUS 19 ! 31: #define VIRTIOHDR_MAC_ADDRESS 20 ! 32: ! 33: ! 34: /** ! 35: * Module init for virtio via PCI. ! 36: * Checks whether we're reponsible for the given device and set up ! 37: * the virtqueue configuration. ! 38: */ ! 39: int ! 40: vn_module_init_pci(snk_kernel_t *snk_kernel_int, pci_config_t *conf) ! 41: { ! 42: uint64_t bar; ! 43: int i; ! 44: ! 45: dprintk("virtionet: doing virtionet_module_init_pci!\n"); ! 46: ! 47: virtiodev.type = VIRTIO_TYPE_PCI; ! 48: ! 49: /* Check whether the driver can handle this device by verifying vendor, ! 50: * device id and class code. */ ! 51: if (conf->vendor_id != 0x1af4) { ! 52: dprintk("virtionet: unsupported vendor id\n"); ! 53: return -1; ! 54: } ! 55: if (conf->device_id < 0x1000 || conf->device_id > 0x103f) { ! 56: dprintk("virtionet: unsupported device id\n"); ! 57: return -1; ! 58: } ! 59: if (conf->class_code != 0x20000) { ! 60: dprintk("virtionet: unsupported class code\n"); ! 61: return -1; ! 62: } ! 63: ! 64: bar = snk_kernel_interface->pci_config_read(conf->puid, 4, conf->bus, ! 65: conf->devfn, 0x10); ! 66: ! 67: if (!(bar & 1)) { ! 68: printk("First BAR is not an I/O BAR!\n"); ! 69: return -1; ! 70: } ! 71: bar &= ~3ULL; ! 72: ! 73: dprintk("untranslated bar = %llx\n", bar); ! 74: ! 75: snk_kernel_interface->translate_addr((void *)&bar); ! 76: ! 77: dprintk("translated bar = %llx\n", bar); ! 78: virtiodev.base = (void*)bar; ! 79: ! 80: /* Reset device */ ! 81: virtio_reset_device(&virtiodev); ! 82: ! 83: /* The queue information can be retrieved via the virtio header that ! 84: * can be found in the I/O BAR. First queue is the receive queue, ! 85: * second the transmit queue, and the forth is the control queue for ! 86: * networking options. ! 87: * We are only interested in the receive and transmit queue here. */ ! 88: ! 89: for (i=VQ_RX; i<=VQ_TX; i++) { ! 90: /* Select ring (0=RX, 1=TX): */ ! 91: vq[i].id = i-VQ_RX; ! 92: ci_write_16(virtiodev.base+VIRTIOHDR_QUEUE_SELECT, ! 93: cpu_to_le16(vq[i].id)); ! 94: ! 95: vq[i].size = le16_to_cpu(ci_read_16(virtiodev.base+VIRTIOHDR_QUEUE_SIZE)); ! 96: vq[i].desc = malloc_aligned(virtio_vring_size(vq[i].size), 4096); ! 97: if (!vq[i].desc) { ! 98: printk("malloc failed!\n"); ! 99: return -1; ! 100: } ! 101: memset(vq[i].desc, 0, virtio_vring_size(vq[i].size)); ! 102: ci_write_32(virtiodev.base+VIRTIOHDR_QUEUE_ADDRESS, ! 103: cpu_to_le32((long)vq[i].desc / 4096)); ! 104: vq[i].avail = (void*)vq[i].desc ! 105: + vq[i].size * sizeof(struct vring_desc); ! 106: vq[i].used = (void*)VQ_ALIGN((long)vq[i].avail ! 107: + vq[i].size * sizeof(struct vring_avail)); ! 108: ! 109: dprintk("%i: vq.id = %lx\nvq.size =%lx\n vq.avail =%lx\nvq.used=%lx\n", ! 110: i, vq[i].id, vq[i].size, vq[i].avail, vq[i].used); ! 111: } ! 112: ! 113: /* Copy MAC address */ ! 114: for (i = 0; i < 6; i++) { ! 115: virtionet_interface.mac_addr[i] ! 116: = ci_read_8(virtiodev.base+VIRTIOHDR_MAC_ADDRESS+i); ! 117: } ! 118: ! 119: /* Acknowledge device. */ ! 120: virtio_set_status(&virtiodev, VIRTIO_STAT_ACKNOWLEDGE); ! 121: ! 122: return 0; ! 123: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.