1/* Intel PRO/1000 Family Driver 2 * Copyright (C) 2004 Marcus Overhagen <marcus@overhagen.de>. All rights reserved. 3 * 4 * Permission to use, copy, modify and distribute this software and its 5 * documentation for any purpose and without fee is hereby granted, provided 6 * that the above copyright notice appear in all copies, and that both the 7 * copyright notice and this permission notice appear in supporting documentation. 8 * 9 * Marcus Overhagen makes no representations about the suitability of this software 10 * for any purpose. It is provided "as is" without express or implied warranty. 11 * 12 * MARCUS OVERHAGEN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 13 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL MARCUS 14 * OVERHAGEN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 15 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19#include <KernelExport.h> 20#include <Errors.h> 21#include <stdlib.h> 22#include <stdio.h> 23#include <string.h> 24 25#include "debug.h" 26#include "timer.h" 27#include "device.h" 28#include "driver.h" 29#include "mempool.h" 30 31int32 api_version = B_CUR_DRIVER_API_VERSION; 32 33pci_module_info *gPci; 34 35char* gDevNameList[MAX_CARDS + 1]; 36pci_info *gDevList[MAX_CARDS]; 37 38static const char * 39identify_device(const pci_info *info) 40{ 41 if (info->vendor_id != 0x8086) 42 return 0; 43 switch (info->device_id) { 44 case 0x1000: return "82542"; 45 case 0x1001: return "82543GC FIBER"; 46 case 0x1004: return "82543GC COPPER"; 47 case 0x1008: return "82544EI COPPER"; 48 case 0x1009: return "82544EI FIBER"; 49 case 0x100C: return "82544GC COPPER"; 50 case 0x100D: return "82544GC LOM"; 51 case 0x100E: return "82540EM"; 52 case 0x100F: return "82545EM COPPER"; 53 case 0x1010: return "82546EB COPPER"; 54 case 0x1011: return "82545EM FIBER"; 55 case 0x1012: return "82546EB FIBER"; 56 case 0x1013: return "82541EI"; 57 case 0x1014: return "unknown 1014"; 58 case 0x1015: return "82540EM LOM"; 59 case 0x1016: return "82540EP LOM"; 60 case 0x1017: return "82540EP"; 61 case 0x1018: return "82541EI MOBILE"; 62 case 0x1019: return "82547EI"; 63 case 0x101A: return "unknown 101A"; 64 case 0x101D: return "82546EB QUAD COPPER"; 65 case 0x101E: return "82540EP LP"; 66 case 0x1026: return "82545GM COPPER"; 67 case 0x1027: return "82545GM FIBER"; 68 case 0x1028: return "82545GM SERDES"; 69 case 0x1075: return "82547GI"; 70 case 0x1076: return "82541GI"; 71 case 0x1077: return "82541GI MOBILE"; 72 case 0x1078: return "82541ER"; 73 case 0x1079: return "82546GB COPPER"; 74 case 0x107A: return "82546GB FIBER"; 75 case 0x107B: return "82546GB SERDES"; 76 case 0x107C: return "82541PI"; 77 default: return 0; 78 } 79} 80 81status_t 82init_hardware(void) 83{ 84 pci_module_info *pci; 85 pci_info info; 86 status_t res; 87 int i; 88 89 INIT_DEBUGOUT("init_hardware()"); 90 91 if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci) < B_OK) 92 return B_ERROR; 93 for (res = B_ERROR, i = 0; pci->get_nth_pci_info(i, &info) == B_OK; i++) { 94 if (identify_device(&info)) { 95 res = B_OK; 96 break; 97 } 98 } 99 put_module(B_PCI_MODULE_NAME); 100 101 return res; 102} 103 104 105status_t 106init_driver(void) 107{ 108 struct pci_info *item; 109 int index; 110 int cards; 111 112#ifdef DEBUG 113 set_dprintf_enabled(true); 114 load_driver_symbols("ipro1000"); 115#endif 116 117 dprintf("ipro1000: " INFO "\n"); 118 119 item = (pci_info *)malloc(sizeof(pci_info)); 120 if (!item) 121 return B_NO_MEMORY; 122 123 if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPci) < B_OK) { 124 free(item); 125 return B_ERROR; 126 } 127 128 for (cards = 0, index = 0; gPci->get_nth_pci_info(index++, item) == B_OK; ) { 129 const char *info = identify_device(item); 130 if (info) { 131 char name[64]; 132 sprintf(name, "net/ipro1000/%d", cards); 133 dprintf("ipro1000: /dev/%s is a %s\n", name, info); 134 gDevList[cards] = item; 135 gDevNameList[cards] = strdup(name); 136 gDevNameList[cards + 1] = NULL; 137 cards++; 138 item = (pci_info *)malloc(sizeof(pci_info)); 139 if (!item) 140 goto err_outofmem; 141 if (cards == MAX_CARDS) 142 break; 143 } 144 } 145 146 free(item); 147 148 if (!cards) 149 goto err_cards; 150 151 if (initialize_timer() != B_OK) { 152 ERROROUT("timer init failed"); 153 goto err_timer; 154 } 155 156 if (mempool_init(cards * 768) != B_OK) { 157 ERROROUT("mempool init failed"); 158 goto err_mempool; 159 } 160 161 return B_OK; 162 163err_mempool: 164 terminate_timer(); 165err_timer: 166err_cards: 167err_outofmem: 168 for (index = 0; index < cards; index++) { 169 free(gDevList[index]); 170 free(gDevNameList[index]); 171 } 172 put_module(B_PCI_MODULE_NAME); 173 return B_ERROR; 174} 175 176 177void 178uninit_driver(void) 179{ 180 int32 i; 181 182 INIT_DEBUGOUT("uninit_driver()"); 183 184 terminate_timer(); 185 186 mempool_exit(); 187 188 for (i = 0; gDevNameList[i] != NULL; i++) { 189 free(gDevList[i]); 190 free(gDevNameList[i]); 191 } 192 193 put_module(B_PCI_MODULE_NAME); 194} 195 196 197device_hooks 198gDeviceHooks = { 199 ipro1000_open, 200 ipro1000_close, 201 ipro1000_free, 202 ipro1000_control, 203 ipro1000_read, 204 ipro1000_write, 205}; 206 207 208const char** 209publish_devices() 210{ 211 return (const char**)gDevNameList; 212} 213 214 215device_hooks* 216find_device(const char* name) 217{ 218 return &gDeviceHooks; 219} 220