ohci-mem.c
来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 247 行
C
247 行
/* * OHCI HCD (Host Controller Driver) for USB. * * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> * * This file is licenced under the GPL. * $Id: ohci-mem.c,v 1.3 2002/03/22 16:04:54 dbrownell Exp $ *//*-------------------------------------------------------------------------*//* * There's basically three types of memory: * - data used only by the HCD ... kmalloc is fine * - async and periodic schedules, shared by HC and HCD ... these * need to use pci_pool or pci_alloc_consistent * - driver buffers, read/written by HC ... single shot DMA mapped * * There's also PCI "register" data, which is memory mapped. * No memory seen by this driver is pagable. *//*-------------------------------------------------------------------------*/static struct usb_hcd *ohci_hcd_alloc (void){ struct ohci_hcd *ohci; ohci = (struct ohci_hcd *) kmalloc (sizeof *ohci, GFP_KERNEL); if (ohci != 0) { memset (ohci, 0, sizeof (struct ohci_hcd)); return &ohci->hcd; } return 0;}static void ohci_hcd_free (struct usb_hcd *hcd){ kfree (hcd_to_ohci (hcd));}/*-------------------------------------------------------------------------*/#ifndef CONFIG_PCI# error "usb-ohci currently requires PCI-based controllers" /* to support non-PCI OHCIs, you need custom bus/mem/... glue */#endif/* Recover a TD/ED using its collision chain */static inline void *dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma){ struct hash_t * scan = entry->head; while (scan && scan->dma != dma) scan = scan->next; return scan->virt;}static struct ed *dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma){ return (struct ed *) dma_to_ed_td(&(hc->ed_hash [ED_HASH_FUNC(ed_dma)]), ed_dma);}static struct td *dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma){ td_dma &= TD_MASK; return (struct td *) dma_to_ed_td(&(hc->td_hash [TD_HASH_FUNC(td_dma)]), td_dma);}// FIXME: when updating the hashtables this way, mem_flags is unusable.../* Add a hash entry for a TD/ED; return true on success */static inthash_add_ed_td ( struct hash_list_t *entry, void *virt, dma_addr_t dma, int mem_flags){ struct hash_t * scan; scan = (struct hash_t *) kmalloc (sizeof *scan, mem_flags); if (!scan) return 0; if (!entry->tail) { entry->head = entry->tail = scan; } else { entry->tail->next = scan; entry->tail = scan; } scan->virt = virt; scan->dma = dma; scan->next = NULL; return 1;}static inline inthash_add_ed (struct ohci_hcd *hc, struct ed *ed, int mem_flags){ return hash_add_ed_td (&(hc->ed_hash [ED_HASH_FUNC (ed->dma)]), ed, ed->dma, mem_flags);}static inline inthash_add_td (struct ohci_hcd *hc, struct td *td, int mem_flags){ return hash_add_ed_td (&(hc->td_hash [TD_HASH_FUNC (td->td_dma)]), td, td->td_dma, mem_flags);}static voidhash_free_ed_td (struct hash_list_t *entry, void *virt){ struct hash_t *scan, *prev; scan = prev = entry->head; // Find and unlink hash entry while (scan && scan->virt != virt) { prev = scan; scan = scan->next; } if (scan) { if (scan == entry->head) { if (entry->head == entry->tail) entry->head = entry->tail = NULL; else entry->head = scan->next; } else if (scan == entry->tail) { entry->tail = prev; prev->next = NULL; } else prev->next = scan->next; kfree(scan); }}static inline voidhash_free_ed (struct ohci_hcd *hc, struct ed * ed){ hash_free_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), ed);}static inline voidhash_free_td (struct ohci_hcd *hc, struct td * td){ hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td);}static int ohci_mem_init (struct ohci_hcd *ohci){ ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev, sizeof (struct td), 32 /* byte alignment */, 0 /* no page-crossing issues */, GFP_KERNEL); if (!ohci->td_cache) return -ENOMEM; ohci->ed_cache = pci_pool_create ("ohci_ed", ohci->hcd.pdev, sizeof (struct ed), 16 /* byte alignment */, 0 /* no page-crossing issues */, GFP_KERNEL); if (!ohci->ed_cache) { pci_pool_destroy (ohci->td_cache); return -ENOMEM; } return 0;}static void ohci_mem_cleanup (struct ohci_hcd *ohci){ if (ohci->td_cache) { pci_pool_destroy (ohci->td_cache); ohci->td_cache = 0; } if (ohci->ed_cache) { pci_pool_destroy (ohci->ed_cache); ohci->ed_cache = 0; }}/* TDs ... */static struct td *td_alloc (struct ohci_hcd *hc, int mem_flags){ dma_addr_t dma; struct td *td; td = pci_pool_alloc (hc->td_cache, mem_flags, &dma); if (td) { td->td_dma = dma; /* hash it for later reverse mapping */ if (!hash_add_td (hc, td, mem_flags)) { pci_pool_free (hc->td_cache, td, dma); return NULL; } } return td;}static voidtd_free (struct ohci_hcd *hc, struct td *td){ hash_free_td (hc, td); pci_pool_free (hc->td_cache, td, td->td_dma);}/* EDs ... */static struct ed *ed_alloc (struct ohci_hcd *hc, int mem_flags){ dma_addr_t dma; struct ed *ed; ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma); if (ed) { memset (ed, 0, sizeof (*ed)); ed->dma = dma; /* hash it for later reverse mapping */ if (!hash_add_ed (hc, ed, mem_flags)) { pci_pool_free (hc->ed_cache, ed, dma); return NULL; } } return ed;}static voided_free (struct ohci_hcd *hc, struct ed *ed){ hash_free_ed (hc, ed); pci_pool_free (hc->ed_cache, ed, ed->dma);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?