📄 krua.c
字号:
} return RM_OK;}RMstatus krua_register_sendcomplete_callback(void *pE, Alsa_callback callback){ struct em8xxxprivate *real_pE = (struct em8xxxprivate *) pE; real_pE->data_callback = callback; return RM_OK;}RMstatus krua_unregister_sendcomplete_callback(void *pE){ struct em8xxxprivate *real_pE = (struct em8xxxprivate *) pE; real_pE->data_callback = NULL; return RM_OK;}/* ran from tasklet */RMstatus EMhwlibSendBufferComplete (void *context, RMuint32 bus_address){ RMuint32 minor = ((RMuint32) context) >> 16; RMuint32 poolId = ((RMuint32) context) & 0xffff; struct em8xxxprivate *pE; int err; if (minor >= MAXLLAD) return -EINVAL; pE= &(Etable[minor]); if (pE->pllad == NULL) return -EINVAL; poolId --; if (poolId == MAXDMAPOOL) { if (pE->data_callback != NULL) { pE->data_callback(pE, bus_address); return RM_OK; } else return RM_ERROR; } /* make sure the dmapool is valid before accessing it */ err = kdmapool_check_opened(pE->pllad, poolId); if (err != 0) return RM_ERROR; PE_RMDBGLOG((LOCALDBG,"release bus address 0x%08x in pool ID %lu\n", bus_address, poolId)); err = kdmapool_release(pE->pllad, poolId, bus_address); if (err != 0) { RMDBGLOG((ENABLE, "ERROR: %d, EMhwlibSendBufferComplete() dmapool_release(pool = %lu, phys_addr = 0x%08lx)\n", err, poolId,bus_address)); return RM_ERROR; } return RM_OK;} /* ran from tasklet */RMstatus EMhwlibEventComplete(void *context, RMuint32 ModuleID, RMuint32 *Status){ RMuint32 i; struct em8xxxprivate *pE = (struct em8xxxprivate *) context; RMuint32 kernel_processed_interrupts=0; RMstatus err=RM_OK; for (i=0; i<MAX_EVENT_CALLBACKS ;i++) { struct em8xxx_event_callback_entry * entry = &(pE->event_callback_array[i]); if ((ModuleID==entry->ModuleID) && (entry->mask & *Status) && (entry->callback != NULL)) { RMDBGLOG((EVENTDBG,"Processing event callback for module %lu and mask 0x%08x\n",entry->ModuleID,entry->mask & *Status)); kernel_processed_interrupts |= entry->callback(pE,ModuleID,*Status & entry->mask); } } for (i=0; i<MAX_EVENT_TASKLETS ;i++) { struct em8xxx_event_tasklet_entry * entry = &(pE->event_tasklet_array[i]); if ((ModuleID==entry->module_id) && (entry->mask & *Status) && (entry->used)) { tasklet_schedule(&(entry->tasklet)); /* store interrupts processed in kernel space */ kernel_processed_interrupts |= *Status & entry->mask; } } /* The interrupts processed by registered kernel event * callbacks will be cleared by the waiter, otherwise the Hardware * librayr is reeentrant * Do not propagate those interrupts to user space */ *Status &= ~kernel_processed_interrupts; if (*Status == 0) return err; for (i=0 ; i<pE->event_count ; i++) { if (pE->event_array[i].module_id == ModuleID) { RMuint32 new_events, old_events; old_events = pE->event_array[i].event_mask; new_events = (old_events | *Status) ^ (old_events); kc_atomic_set_mask(&(pE->event_array[i].event_mask), new_events); *Status &= ~(new_events); if (new_events) kc_wake_up_interruptible(pE->wq); PE_RMDBGLOG((EVENTDBG, "Adding event 0x%lx to module %lu in array index (%lu)\n", new_events, ModuleID, i)); return RM_OK; } } if (i < MAX_WAITERS) { /* non atomicity is OK here since we validate the index only after event_count is incremented */ pE->event_array[i].module_id = ModuleID; pE->event_array[i].event_mask = *Status; PE_RMDBGLOG((EVENTDBG, "Adding event 0x%lx to module %lu in array index (%lu)\n", *Status, ModuleID, i)); *Status = 0; pE->event_count ++; kc_wake_up_interruptible(pE->wq); return RM_OK; } RMDBGLOG((ENABLE, "Not enough space to store all modules generating events (%lu)\n", i)); return RM_ERROR;}RMstatus EMhwlibRegisterCleanable(struct EMhwlib *pemhwlib, RMuint32 ModuleID, RMuint32 PropertyID, RMuint32 value){ RMuint32 i; RMuint32 em8xxx_id; struct em8xxxprivate *pE; for (i=0;i<MAXLLAD;i++) if (Etable[i].pemhwlib==pemhwlib) break; if (i==MAXLLAD) { RMDBGLOG((ENABLE, "Cannot find emhwlib 0x%p\n", pemhwlib)); return RM_ERROR; } pE=&Etable[i]; for (i=0;i<MAX_OPENERS;i++) if (pE->openers[i].em8xxx_id==CURRENT_EM8XXX_ID) break; em8xxx_id = (i==MAX_OPENERS) ? 0 : CURRENT_EM8XXX_ID; if (PropertyID == RMMMPropertyID_Free) { for (i=0 ; i<MAX_MEMORY_AREA ; i++) if (pE->mem_area[i].PropertyID==0) break; if (i==MAX_MEMORY_AREA) { PE_RMDBGLOG((ENABLE, "EMhwlibRegisterCleanable: no room left for address 0x%08lx in mem_area\n", value)); return RM_ERROR; } pE->mem_area[i].em8xxx_id=em8xxx_id; pE->mem_area[i].refcount = 0; pE->mem_area[i].ModuleID=ModuleID; pE->mem_area[i].PropertyID=PropertyID; pE->mem_area[i].address_start=value; pE->mem_area[i].address_end=0; pE->mem_area[i].id = 0; } else { // empty entries are found by PropertyID=0 for (i=0;i<MAX_CLEANABLE;i++) if (pE->cl[i].PropertyID==0) break; if (i==MAX_CLEANABLE) { PE_RMDBGLOG((ENABLE, "EMhwlibRegisterCleanable: no room left for ModuleID %lu PropertyID %lu.\n", ModuleID, PropertyID)); return RM_ERROR; } pE->cl[i].em8xxx_id=em8xxx_id; pE->cl[i].ModuleID=ModuleID; pE->cl[i].PropertyID=PropertyID; pE->cl[i].value=value; } PE_RMDBGLOG((CLEANDBG,"EMhwlibRegisterCleanable: #%d %d-%d-%d-0x%08lx\n", i, em8xxx_id, ModuleID, PropertyID, value)); return RM_OK;}RMstatus EMhwlibUnregisterCleanable(struct EMhwlib *pemhwlib, RMuint32 ModuleID, RMuint32 PropertyID, RMuint32 value){ RMuint32 i; struct em8xxxprivate *pE; for (i=0;i<MAXLLAD;i++) if (Etable[i].pemhwlib==pemhwlib) break; if (i==MAXLLAD) { RMDBGLOG((ENABLE, "Cannot find emhwlib 0x%p\n", pemhwlib)); return RM_ERROR; } pE=&Etable[i]; if (PropertyID == RMMMPropertyID_Free) { for (i=0 ; i<MAX_MEMORY_AREA ; i++) { if ((pE->mem_area[i].ModuleID == ModuleID) && (pE->mem_area[i].PropertyID == PropertyID) && (pE->mem_area[i].address_start == value) && ((pE->mem_area[i].em8xxx_id == 0) || (pE->mem_area[i].em8xxx_id == CURRENT_EM8XXX_ID))) break; } if (i==MAX_MEMORY_AREA) { PE_RMDBGLOG((ENABLE,"EMhwlibUnregisterCleanable mem_area (0x%08x) (from rmmod em8xxx_id %d): not found\n",value, CURRENT_EM8XXX_ID)); return RM_ERROR; } if (pE->mem_area[i].refcount > 0) { PE_RMDBGLOG((LOCALDBG,"EMhwlibUnregisterCleanable mem_area (0x%08x) (from rmmod em8xxx_id %d): refcount %d.\n",value, CURRENT_EM8XXX_ID, pE->mem_area[i].refcount)); return RM_ERROR; } else { pE->mem_area[i].PropertyID=0; // mark entry as empty pE->mem_area[i].id=0; // mark custom id entry as empty } } else { for (i=0;i<MAX_CLEANABLE;i++) { if ((pE->cl[i].ModuleID == ModuleID) && (pE->cl[i].PropertyID == PropertyID) && (pE->cl[i].value == value) && ((pE->cl[i].em8xxx_id == 0) || (pE->cl[i].em8xxx_id == CURRENT_EM8XXX_ID))) break; } if (i==MAX_CLEANABLE) { // hack should we really call cleanup_module -> Exit -> CRCExit -> _Close unconditionally? PE_RMDBGLOG((ENABLE,"EMhwlibUnregisterCleanable module %lu, prop %lu (from rmmod em8xxx_id %d): not found\n", ModuleID, PropertyID, CURRENT_EM8XXX_ID)); return RM_ERROR; } pE->cl[i].PropertyID=0; // mark entry as empty pE->mem_area[i].id=0; // mark custom id entry as empty } PE_RMDBGLOG((CLEANDBG,"EMhwlibUnregisterCleanable: #%d\n",i)); return RM_OK;}static int mem_area_add_refcount(struct em8xxxprivate *pE, RMuint32 address, int incr){ RMuint32 i; for (i=0 ; i<MAX_MEMORY_AREA ; i++) { if (pE->mem_area[i].PropertyID == 0) continue; if (pE->mem_area[i].address_end == 0) { struct MM_AreaSize_in_type valueIn; struct MM_AreaSize_out_type valueOut; RMstatus status; valueIn.Address = (void *) pE->mem_area[i].address_start; status = EMhwlibExchangeProperty(pE->pemhwlib, pE->mem_area[i].ModuleID, RMMMPropertyID_AreaSize, &valueIn, sizeof(valueIn), &valueOut, sizeof(valueOut)); if (status == RM_OK) pE->mem_area[i].address_end = pE->mem_area[i].address_start + valueOut.Size; } if ((address >= pE->mem_area[i].address_start) && (address < pE->mem_area[i].address_end)) { pE->mem_area[i].refcount += incr; if (pE->mem_area[i].refcount < 0) { PE_RMDBGLOG((ENABLE,"!!!! ERROR !!!!: mem_area_add_refcount address 0x%08x, is negative\n",address)); pE->mem_area[i].refcount = 0; } PE_RMDBGLOG((CLEANDBG,"mem_area_add_refcount address 0x%08x, incr %d, refcount %lu\n",address, incr, pE->mem_area[i].refcount)); break; } } if (i==MAX_MEMORY_AREA) { return -1; } return 0;}/* EMhwlib callback so do not spinlock */RMstatus EMhwlibAcquireAddress(struct EMhwlib *pEMhwlib, RMuint32 address){ RMuint32 i; struct em8xxxprivate *pE; for (i=0;i<MAXLLAD;i++) if (Etable[i].pemhwlib==pEMhwlib) break; if (i==MAXLLAD) { RMDBGLOG((ENABLE, "Cannot find emhwlib 0x%p\n", pEMhwlib)); return RM_ERROR; } pE=&Etable[i]; if (mem_area_add_refcount(pE, address, 1) < 0) { PE_RMDBGLOG((ENABLE,"EMhwlibAcquireAddress address 0x%08x not found\n",address)); return RM_ERROR; } PE_RMDBGLOG((CLEANDBG,"EMhwlibAcquireAddress address 0x%08x\n",address)); return RM_OK;}/* EMhwlib callback so do not spinlock */RMstatus EMhwlibReleaseAddress(struct EMhwlib *pEMhwlib, RMuint32 address){ RMuint32 i; struct em8xxxprivate *pE; for (i=0;i<MAXLLAD;i++) if (Etable[i].pemhwlib==pEMhwlib) break; if (i==MAXLLAD) { RMDBGLOG((ENABLE, "Cannot find emhwlib 0x%p\n", pEMhwlib)); return RM_ERROR; } pE=&Etable[i]; if (mem_area_add_refcount(pE, address, -1) < 0) { PE_RMDBGLOG((ENABLE,"EMhwlibReleaseAddress address 0x%08x not found\n",address)); return RM_ERROR; } return RM_OK;}struct file_operations em8xxx_fops = { // this replaces MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT pain owner: THIS_MODULE, ioctl:em8xxx_ioctl, open:em8xxx_open, release:em8xxx_release, poll: em8xxx_poll};/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// hack this must be related to smallapps/burnsflash/config-* and mambo_project/loader/config.h line 38static inline void patch_pci_config(RMascii *str){ RMascii a1[3], a2[3], a3[2], a4[7], a5[5], a6[5], a7[5], a8[5], a9[3]; sscanf(str, "%2s:%2s.%1s %6s %4s:%4s %4s:%4s %2s\n", a1, a2, a3, a4, a5, a6, a7, a8, a9); sprintf(str, "0%s:0%s.0%s 0%s 0%s:0%s 0%s:0%s 0%s\n", a1, a2, a3, a4, a5, a6, a7, a8, a9);}/* Differenciate between the signature of the serial flash (cannot be reread it at 0x40000000) and the MAMB signature coming shortly after */#define MAMBO_CONFIGSIGN_OFFSET 0xc#define MAMBO_CONFIGSIGN 0x424d414d#define MAMBO_FLASH_OFFSET 0x06000000static int identify(struct em8xxxprivate *pE){ RMuint32 device,subid; RMascii pci_config[256]; int tmp, ret, revid;#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2) // hack: no verification#else if (gbus_read_uint32(pE->pgbus,MEM_BASE_host_interface+MAMBO_CONFIGSIGN_OFFSET)!=MAMBO_CONFIGSIGN) { PE_RMDBGLOG((ENABLE,"identify: board has no valid serial flash signature. Skipping.\n")); if (gbus_read_uint32(pE->pgbus,MEM_BASE_host_interface+MAMBO_CONFIGSIGN_OFFSET + MAMBO_FLASH_OFFSET)!=MAMBO_CONFIGSIGN) { PE_RMDBGLOG((ENABLE,"identify: board has no valid parallel flash signature. Skipping.\n")); return -1; } }#endif llad_get_config(pE->pllad, pci_config, 256); /* some 2.4 kernels have a buggy sscanf, numbers have to start with a decimal digit :-( */ patch_pci_config(pci_config); ret = kc_sscanf(pci_config, "%x:%x.%x %x %x:%x %x:%x %x", &tmp, &tmp, &tmp, &tmp, &tmp, &device, &tmp, &subid, &revid); if (ret != 9) { PE_RMDBGLOG((ENABLE,"cannot parse llad pci configuration: %s on item %d\n", pci_config, ret)); return -1; } switch (subid) { case 0: PE_RMDBGLOG((ENABLE,"identify: board is design #711 (odyssey)\n")); break; case 1: PE_RMDBGLOG((ENABLE,"identify: board is design #706 (mstv)\n")); break; case 2: PE_RMDBGLOG((ENABLE,"identify: board is design #716 (no name) (ONLY ONE DRAM CHIP!!!)\n")); break; default: PE_RMDBGLOG((ENABLE,"identify: board as unknown subid\n")); break; } #if ( (EM86XX_CHIP==EM86XX_CHIPID_MAMBOLIGHT) || (EM86XX_CHIP==EM86XX_CHIPID_MAMBO) ) if ( ! ( ((device & 0xf0) == 0x00) || ((device & 0xf0) == 0x10) ) ) { RMDBGLOG((ENABLE,"identify: " S_EM86XX_CHIPID " software inserted on other hardware (0x%04x)\n",device)); return -1; } // e.m. do not weaken this to a warning#if (EM86XX_REVISION=='C') if (revid!=3) { RMDBGLOG((ENABLE,"identify: " S_EM86XX_CHIPID S_EM86XX_REVISION " software on older revid=0x%x\n",revid)); return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -