1 /* 2 * Copyright (C) 2007 JiSheng Zhang <jszhang3@gmail.com>. All rights reserved 3 * Distributed under the terms of the MIT license. 4 * 5 * Kernel driver for firewire 6 */ 7 8 #include <OS.h> 9 #include <KernelExport.h> 10 #include <SupportDefs.h> 11 #include <PCI.h> 12 13 #include <stdlib.h> 14 #include <stdio.h> 15 #include <string.h> 16 #include <malloc.h> 17 #include <dpc.h> 18 19 #include "fwdebug.h" 20 #include "queue.h" 21 #include "fwglue.h" 22 #include "firewire.h" 23 #include "iec13213.h" 24 #include "firewirereg.h" 25 #include "fwdma.h" 26 #include "fwohcireg.h" 27 #include "fwohcivar.h" 28 #include "firewire_module.h" 29 30 status_t fwohci_pci_attach(int index); 31 status_t fwohci_pci_detach(int index); 32 pci_info *pciInfo[MAX_CARDS]; 33 fwohci_softc_t *gFwohci_softc[MAX_CARDS]; 34 struct firewire_softc *gFirewire_softc[MAX_CARDS]; 35 pci_module_info *gPci; 36 dpc_module_info *gDpc; 37 38 struct supported_device{ 39 uint16 vendor_id; 40 uint32 device_id; 41 const char *name; 42 }; 43 44 struct supported_device supported_devices[] = { 45 {FW_VENDORID_NATSEMI, FW_DEVICE_CS4210, "National Semiconductor CS4210"}, 46 {FW_VENDORID_NEC, FW_DEVICE_UPD861, "NEC uPD72861"}, 47 {FW_VENDORID_NEC, FW_DEVICE_UPD871, "NEC uPD72871/2"}, 48 {FW_VENDORID_NEC, FW_DEVICE_UPD72870, "NEC uPD72870"}, 49 {FW_VENDORID_NEC, FW_DEVICE_UPD72873, "NEC uPD72873"}, 50 {FW_VENDORID_NEC, FW_DEVICE_UPD72874, "NEC uPD72874"}, 51 {FW_VENDORID_SIS, FW_DEVICE_7007, "SiS 7007"}, 52 {FW_VENDORID_TI, FW_DEVICE_TITSB22, "Texas Instruments TSB12LV22"}, 53 {FW_VENDORID_TI, FW_DEVICE_TITSB23, "Texas Instruments TSB12LV23"}, 54 {FW_VENDORID_TI, FW_DEVICE_TITSB26, "Texas Instruments TSB12LV26"}, 55 {FW_VENDORID_TI, FW_DEVICE_TITSB43, "Texas Instruments TSB43AA22"}, 56 {FW_VENDORID_TI, FW_DEVICE_TITSB43A, "Texas Instruments TSB43AB22/A"}, 57 {FW_VENDORID_TI, FW_DEVICE_TITSB43AB21, "Texas Instruments TSB43AB21/A/AI/A-EP"}, 58 {FW_VENDORID_TI, FW_DEVICE_TITSB43AB23, "Texas Instruments TSB43AB23"}, 59 {FW_VENDORID_TI, FW_DEVICE_TITSB82AA2, "Texas Instruments TSB82AA2"}, 60 {FW_VENDORID_TI, FW_DEVICE_TIPCI4450, "Texas Instruments PCI4450"}, 61 {FW_VENDORID_TI, FW_DEVICE_TIPCI4410A, "Texas Instruments PCI4410A"}, 62 {FW_VENDORID_TI, FW_DEVICE_TIPCI4451, "Texas Instruments PCI4451"}, 63 {FW_VENDORID_VIA, FW_DEVICE_VT6306, "VIA Fire II (VT6306)"}, 64 {FW_VENDORID_RICOH, FW_DEVICE_R5C551, "Ricoh R5C551"}, 65 {FW_VENDORID_RICOH, FW_DEVICE_R5C552, "Ricoh R5C552"}, 66 {FW_VENDORID_APPLE, FW_DEVICE_PANGEA, "Apple Pangea"}, 67 {FW_VENDORID_APPLE, FW_DEVICE_UNINORTH, "Apple UniNorth"}, 68 {FW_VENDORID_LUCENT, FW_DEVICE_FW322, "Lucent FW322/323"}, 69 {FW_VENDORID_INTEL, FW_DEVICE_82372FB, "Intel 82372FB"}, 70 {FW_VENDORID_ADAPTEC, FW_DEVICE_AIC5800, "Adaptec AHA-894x/AIC-5800"}, 71 {FW_VENDORID_SUN, FW_DEVICE_PCIO2FW, "Sun PCIO-2"}, 72 {FW_VENDORID_SONY, FW_DEVICE_CXD3222, "Sony i.LINK (CXD3222)"}, 73 {0, 0, NULL} 74 }; 75 76 77 static int 78 find_device_name(pci_info *info) 79 { 80 struct supported_device *device; 81 for (device = supported_devices; device->name; device++) { 82 if (info->vendor_id == device->vendor_id 83 && info->device_id == device->device_id >> 16) { 84 dprintf("%s\n", device->name); 85 return 1; 86 } 87 } 88 return 0; 89 } 90 91 92 #if 0 93 static status_t 94 fw_add_child(const char *childname, 95 const struct firewire_notify_hooks *hooks) 96 { 97 status_t status; 98 int i; 99 TRACE("add child %s\n", childname); 100 for (i = 0; gFirewire_softc[i] != NULL; i++) { 101 status = firewire_add_child(gFirewire_softc[i], childname, hooks); 102 if (status != B_OK) 103 return status; 104 } 105 106 return B_OK; 107 } 108 109 110 static status_t 111 fw_remove_child(const char *childname) 112 { 113 status_t status; 114 int i; 115 TRACE("remove child %s\n", childname); 116 for (i = 0; gFirewire_softc[i] != NULL; i++) { 117 status = firewire_remove_child(gFirewire_softc[i], childname); 118 if (status != B_OK) 119 return status; 120 } 121 122 return B_OK; 123 } 124 #endif 125 126 127 static int 128 fw_get_handle(int socket, struct firewire_softc **handle) 129 { 130 if (handle == NULL) 131 return B_BAD_VALUE; 132 if (socket >= 0 && socket < MAX_CARDS && gFirewire_softc[socket]) { 133 *handle = gFirewire_softc[socket]; 134 return B_OK; 135 } 136 *handle = NULL; 137 return ENODEV; 138 } 139 140 141 static status_t 142 fw_module_init(void) 143 { 144 status_t status; 145 int i, found; 146 fwohci_softc_t *fwohci_sc; 147 struct firewire_softc *fw_sc; 148 149 pci_info *info = (pci_info*)malloc(sizeof(pci_info)); 150 if (!info) 151 return B_NO_MEMORY; 152 153 if ((status = get_module(B_PCI_MODULE_NAME,(module_info **)&gPci)) != B_OK) { 154 TRACE("pci module unavailable\n"); 155 free(info); 156 return status; 157 } 158 159 if ((status = get_module(B_DPC_MODULE_NAME,(module_info **)&gDpc)) != B_OK) { 160 TRACE("pci module unavailable\n"); 161 free(info); 162 put_module(B_PCI_MODULE_NAME); 163 return status; 164 } 165 166 memset(gFwohci_softc, 0, sizeof(gFwohci_softc)); 167 168 // find devices 169 for (i = 0, found = 0; (status = gPci->get_nth_pci_info(i, info)) == B_OK; i++) { 170 if (find_device_name(info) 171 || ((info->class_base == PCI_serial_bus) 172 && (info->class_sub == PCI_firewire) 173 && (info->class_api == PCI_INTERFACE_OHCI))) { 174 dprintf( "vendor=%x, device=%x, revision = %x\n", info->vendor_id, info->device_id, info->revision); 175 pciInfo[found] = info; 176 177 fwohci_sc = (fwohci_softc_t*)malloc(sizeof(fwohci_softc_t)); 178 if (!fwohci_sc) { 179 free(info); 180 goto err_outofmem; 181 } 182 memset(fwohci_sc, 0, sizeof(fwohci_softc_t)); 183 gFwohci_softc[found] = fwohci_sc; 184 185 fw_sc = (firewire_softc*)malloc(sizeof(struct firewire_softc)); 186 if (!fw_sc) { 187 free(info); 188 free(fwohci_sc); 189 goto err_outofmem; 190 } 191 memset(fw_sc, 0, sizeof(struct firewire_softc)); 192 gFirewire_softc[found] = fw_sc; 193 gFirewire_softc[found+1] = NULL; 194 195 found++; 196 info = (pci_info*)malloc(sizeof(pci_info)); 197 if (!info) 198 goto err_outofmem; 199 200 if (found == MAX_CARDS) 201 break; 202 203 } 204 } 205 TRACE("found %d cards\n", found); 206 free(info); 207 208 if ((status = initialize_timer()) != B_OK) { 209 ERROR("timer init failed\n"); 210 goto err_timer; 211 } 212 213 for (i = 0; i < found; i++) { 214 if (fwohci_pci_attach(i) != B_OK) { 215 ERROR("fwohci_pci_attach failed\n"); 216 goto err_pci; 217 } 218 } 219 return B_OK; 220 221 err_pci: 222 terminate_timer(); 223 err_timer: 224 err_outofmem: 225 for (i = 0; i < found; i++) { 226 free(gFirewire_softc[i]); 227 free(gFwohci_softc[i]); 228 free(pciInfo[i]); 229 } 230 put_module(B_PCI_MODULE_NAME); 231 put_module(B_DPC_MODULE_NAME); 232 return B_ERROR; 233 234 } 235 236 static status_t 237 fw_module_uninit(void) 238 { 239 int i; 240 241 terminate_timer(); 242 243 for (i = 0; gFirewire_softc[i] != NULL; i++) { 244 fwohci_pci_detach(i); 245 free(gFirewire_softc[i]); 246 free(gFwohci_softc[i]); 247 free(pciInfo[i]); 248 } 249 250 put_module(B_PCI_MODULE_NAME); 251 put_module(B_DPC_MODULE_NAME); 252 253 return B_OK; 254 } 255 256 257 static status_t 258 fw_module_std_ops(int32 op, ...) 259 { 260 switch (op) { 261 case B_MODULE_INIT: 262 TRACE("fw_module_init\n"); 263 return fw_module_init(); 264 265 case B_MODULE_UNINIT: 266 TRACE("fw_module_uninit\n"); 267 return fw_module_uninit(); 268 } 269 return B_BAD_VALUE; 270 } 271 272 static struct fw_module_info gModuleInfo = { 273 { 274 { 275 FIREWIRE_MODULE_NAME, 276 0, 277 fw_module_std_ops 278 }, 279 NULL 280 }, 281 fw_noderesolve_nodeid, 282 fw_noderesolve_eui64, 283 fw_asyreq, 284 fw_xferwake, 285 fw_xferwait, 286 fw_bindlookup, 287 fw_bindadd, 288 fw_bindremove, 289 fw_xferlist_add, 290 fw_xferlist_remove, 291 fw_xfer_alloc, 292 fw_xfer_alloc_buf, 293 fw_xfer_done, 294 fw_xfer_unload, 295 fw_xfer_free_buf, 296 fw_xfer_free, 297 fw_asy_callback_free, 298 fw_open_isodma, 299 fw_get_handle, 300 fwdma_malloc_multiseg, 301 fwdma_free_multiseg 302 }; 303 304 module_info *modules[] = { 305 (module_info *)&gModuleInfo, 306 NULL 307 }; 308