int mvme_open(MVME_INTERFACE **vme, int index) { BT617_TABLE *ptab; bt_devdata_t flag; int status; *vme = (MVME_INTERFACE *)malloc(sizeof(MVME_INTERFACE)); if (*vme == NULL) return MVME_NO_MEM; (*vme)->am = MVME_AM_DEFAULT; (*vme)->dmode = MVME_DMODE_DEFAULT; (*vme)->blt_mode = MVME_BLT_NONE; (*vme)->handle = 0; /* use first entry in BT617_TABLE by default */ (*vme)->table = (void *)malloc(sizeof(BT617_TABLE)*MAX_BT617_TABLES); if ((*vme)->table == NULL) return MVME_NO_MEM; memset((*vme)->table, 0, sizeof(BT617_TABLE)*MAX_BT617_TABLES); ptab = (BT617_TABLE *) (*vme)->table; ptab->am = MVME_AM_DEFAULT; bt_gen_name(index, BT_DEV_A32, ptab->devname, BT_MAX_DEV_NAME); status = bt_open(&ptab->btd, ptab->devname, BT_RDWR); if (status != BT_SUCCESS) { bt_perror(ptab->btd, status, "bt_open error"); return MVME_NO_INTERFACE; } bt_init(ptab->btd); bt_clrerr(ptab->btd); /* select swapping mode */ flag = BT_SWAP_NONE; bt_set_info(ptab->btd, BT_INFO_SWAP, flag); /* set data mode */ flag = BT_WIDTH_D32; bt_set_info(ptab->btd, BT_INFO_DATAWIDTH, flag); /* switch off block transfer */ flag = FALSE; bt_set_info(ptab->btd, BT_INFO_BLOCK, flag); return MVME_SUCCESS; }
/**************************************************************************//** * \fn CAENComm_ErrorCode STDCALL CAENComm_OpenDevice(CAENComm_DeviceDescr dd, int *handle); * \brief Open the device * * \param [IN] LinkType: the link used by the device(CAENComm_USB|CAENComm_PCI_OpticalLink|CAENComm_PCIE_OpticalLink|CAENComm_PCIE) * \param [IN] LinkNum: The link number * \param [IN] ConetNode: The board number in the link. * \param [IN] VMEBaseAddress: The VME base address of the board * \param [OUT] handle: device handler * \return 0 = Success; negative numbers are error codes * \note We ignore the link type -- it's always going to be SBS * \note The LinkNum will be the SBS interface board. * \note The ConetNode will be ignored,. * \note We are always going to open BT_DEV_A32 * \note SBS errors are converted to a generic error. * ******************************************************************************/ CAENComm_ErrorCode STDCALL CAENComm_OpenDevice(CAENComm_ConnectionType LinkType, int LinkNum, int ConetNode, uint32_t VMEBaseAddress, int *handle) { CAENComm_ErrorCode status =CAENComm_Success; // optimistic completion code. try { char deviceName[PATH_MAX+1]; bt_desc_t* btHandle = new bt_desc_t;; void* pMap; // Generate our device name and attempt to open it: const char* pName = bt_gen_name(LinkNum, BT_DEV_A32, deviceName, sizeof(deviceName)); if (pName != deviceName) throw CAENComm_GenericError; bt_error_t ok = bt_open(btHandle, pName, BT_RDWR); if (ok != BT_SUCCESS) throw CAENComm_GenericError; // Attempt to map the address space: ok = bt_mmap(*btHandle, &pMap, VMEBaseAddress, gWindowSize, BT_RDWR, BT_SWAP_NONE); if(ok != BT_SUCCESS) throw CAENComm_GenericError; // Create the handle, fill it in, validate it and return its index to the caller. int iHandle = newHandle(); pNSCLHandle pHandle = &(gHandles[iHandle]); pHandle->s_pSbsHandle = btHandle; pHandle->s_nBaseAddress = VMEBaseAddress; pHandle->s_pMappedMemory = pMap; pHandle->s_fValid = true; *handle = iHandle; } catch(CAENComm_ErrorCode code) { status = code; } return status; }
int vme_open() { /* Open SBS VME-PCI */ status = bt_open(&btd, bt_gen_name(unit, type, &devname[0], BT_MAX_DEV_NAME), BT_RD | BT_WR); if (BT_SUCCESS != status) { bt_perror(btd, status, "Engine ERROR: Could not open SBS VME-PCI"); remove("/Applications/sirius/system/engine.lock"); return -1; } /* Clear any outstanding errors */ status = bt_clrerr(btd); if (BT_SUCCESS != status) { bt_perror(btd, status, "Engine ERROR: Could not clear errors from SBS VME-PCI"); remove("/Applications/sirius/system/engine.lock"); (void) bt_close(btd); return -1; } return 0; }
int bt617_set_am(MVME_INTERFACE *vme, int am) { int i; BT617_TABLE *ptab; bt_error_t status; bt_devdata_t flag; for (i=0 ; i<MAX_BT617_TABLES ; i++) if (((BT617_TABLE *)vme->table)[i].am == am) break; if (((BT617_TABLE *)vme->table)[i].am == am) { vme->handle = i; ptab = ((BT617_TABLE *)vme->table)+i; bt_set_info(ptab->btd, BT_INFO_DMA_AMOD, am); bt_set_info(ptab->btd, BT_INFO_PIO_AMOD, am); bt_set_info(ptab->btd, BT_INFO_MMAP_AMOD, am); return MVME_SUCCESS; } /* search free slot */ for (i=0 ; i<MAX_BT617_TABLES ; i++) if (((BT617_TABLE *)vme->table)[i].am == 0) break; if (i==MAX_BT617_TABLES) return MVME_NO_MEM; /* mode not yet open, open it */ vme->handle = i; ptab = ((BT617_TABLE *)vme->table)+i; ptab->am = am; if (am == MVME_AM_A16_SD || am == MVME_AM_A16_ND) bt_gen_name(vme->index, BT_DEV_A16, ptab->devname, BT_MAX_DEV_NAME); else if (am == MVME_AM_A24_SB || am == MVME_AM_A24_SP || am == MVME_AM_A24_SD || am == MVME_AM_A24_NB || am == MVME_AM_A24_NP || am == MVME_AM_A24_ND || am == MVME_AM_A24_SMBLT || am == MVME_AM_A24_NMBLT || am == MVME_AM_A24 || am == MVME_AM_A24_D64) bt_gen_name(vme->index, BT_DEV_A24, ptab->devname, BT_MAX_DEV_NAME); else bt_gen_name(vme->index, BT_DEV_A32, ptab->devname, BT_MAX_DEV_NAME); status = bt_open(&ptab->btd, ptab->devname, BT_RDWR); if (status != BT_SUCCESS) { bt_perror(ptab->btd, status, "bt_open error"); return MVME_NO_INTERFACE; } bt_init(ptab->btd); bt_clrerr(ptab->btd); /* select swapping mode */ flag = BT_SWAP_NONE; bt_set_info(ptab->btd, BT_INFO_SWAP, flag); /* set data mode */ flag = BT_WIDTH_D16; bt_set_info(ptab->btd, BT_INFO_DATAWIDTH, flag); /* switch off block transfer */ flag = FALSE; bt_set_info(ptab->btd, BT_INFO_BLOCK, flag); /* set amod */ bt_set_info(ptab->btd, BT_INFO_DMA_AMOD, am); bt_set_info(ptab->btd, BT_INFO_PIO_AMOD, am); bt_set_info(ptab->btd, BT_INFO_MMAP_AMOD, am); return MVME_SUCCESS; }
/***************************************************************************** ** ** Function: bt_icbr_thread() ** ** Purpose: This thread waits for an interrupt, then call all the ** the registered ICBRs. ** ** Args: param_p Descriptor to call through ** ** Modifies: ** ** Returns: ** void ** ** Note: ** *****************************************************************************/ static void *bt_icbr_thread( void *param_p) { bt_error_t api_ret; bt_desc_t btd = param_p; bt_thread_wait_t thread_wait_data; bt_thread_reg_t thread_reg_data; bt_data8_t *irq_mmap_p; bt_irq_q_t *error_irq_p; bt_irq_q_t *prog_irq_p; bt_irq_q_t *vme_irq_p; bt_data64_t error_tail, prog_tail, vme_tail; bt_devdata_t q_size; char devname[BT_MAX_DEV_NAME]; char *devname_p = &(devname[0]); #if defined (BT951) void *map_addr = NULL; #endif /* ** Grab the descriptor mutex */ pthread_mutex_lock(&btd->mutex); /* ** Register with the driver */ api_ret = bt_ctrl(btd, BIOC_THREAD_REG, &thread_reg_data); btd->thread_id = thread_reg_data.thread_id; if (api_ret != BT_SUCCESS) { DBG_STR("Thread registration failed"); pthread_cond_signal(&btd->icbr_started); pthread_mutex_unlock(&btd->mutex); pthread_exit(NULL); } /* ** Get the interrupt queue length */ (void) bt_get_info(btd, BT_INFO_ICBR_Q_SIZE, &q_size); /* ** Open the diagnostic device for mmapping the irq queues */ devname_p = bt_gen_name(thread_reg_data.unit, BT_DEV_DIAG, devname_p, BT_MAX_DEV_NAME); btd->fd_diag = open((char *) devname_p, O_RDONLY, 0); if (btd->fd_diag == -1) { DBG_STR("Open of diag device failed"); (void) bt_ctrl(btd, BIOC_THREAD_UNREG, &thread_reg_data); pthread_cond_signal(&btd->icbr_started); pthread_mutex_unlock(&btd->mutex); pthread_exit(NULL); } /* ** Memory map the interrupt queues */ irq_mmap_p = (bt_data8_t *) mmap(NULL, BTK_Q_NUM * BTK_Q_SIZE(q_size), PROT_READ, MAP_SHARED, btd->fd_diag, BT_DIAG_ISR_Q_OFFSET); /* Handle the error condition */ #if defined (BT951) if (irq_mmap_p == MAP_FAILED) #else if (irq_mmap_p == NULL) #endif { DBG_STR("Irq queue mmap failed"); (void) close(btd->fd_diag); (void) bt_ctrl(btd, BIOC_THREAD_UNREG, &thread_reg_data); pthread_cond_signal(&btd->icbr_started); pthread_mutex_unlock(&btd->mutex); pthread_exit(NULL); } #if defined (BT951) else { /* We have an address the driver wants us to use, but first it needs to * be mapped into this virtual user space. */ /* * Open the memory device */ btd->dev_mem_fd = open("/dev/mem", O_RDWR); if (btd->dev_mem_fd < 0) { DBG_MSG ((stderr, "Unable to open /dev/mem device. fd = %d errno = %d\n", btd->dev_mem_fd, errno)); /* Failure: cleanup the thread and close the device. */ (void) close(btd->fd_diag); (void) bt_ctrl(btd, BIOC_THREAD_UNREG, &thread_reg_data); pthread_cond_signal(&btd->icbr_started); pthread_mutex_unlock(&btd->mutex); pthread_exit(NULL); } /* Map the resource */ map_addr = (bt_data32_t*)mmap(0, BTK_Q_NUM * BTK_Q_SIZE(q_size), (PROT_READ | PROT_WRITE | PROT_UNCACHE), (MAP_SHARED), btd->dev_mem_fd, (off_t)irq_mmap_p); if (map_addr == MAP_FAILED) { DBG_MSG ((stderr, "Unable to map fd (%d) with the address (%08Xh), errno = %d\n", btd->dev_mem_fd, (unsigned int)irq_mmap_p, errno)); /* Unmap the address and close the device*/ close(btd->dev_mem_fd); (void) close(btd->fd_diag); (void) bt_ctrl(btd, BIOC_THREAD_UNREG, &thread_reg_data); pthread_cond_signal(&btd->icbr_started); pthread_mutex_unlock(&btd->mutex); pthread_exit(NULL); } #if 0 map_addr = (bt_data8_t *) map_addr + (map_off % size_of_page); *mmap_p = (void *) map_addr; #endif /* Save the address from the driver and the kernel virtual address */ /* We will use the driver address to free the resources I think */ btd->driver_phys_addr = (unsigned int)irq_mmap_p; btd->map_virt_addr = (unsigned int)map_addr; } btd->icbr_mmap_p = map_addr; #else /* defined BT951 */ btd->icbr_mmap_p = irq_mmap_p; #endif /* defined BT951 */ btd->icbr_running = TRUE; btd->icbr_mmap_len = BTK_Q_NUM * BTK_Q_SIZE(q_size); /* ** Register a cleanup function to release mmap, unregister with ** driver, and clear running flag */ pthread_cleanup_push(bt_thread_cancel, (void *) btd); /* ** Setup the interrupt queue pointers and set the tails equal to ** the heads */ BTK_Q_ASSIGN(btd->icbr_mmap_p, error_irq_p, prog_irq_p, vme_irq_p, q_size); error_tail = error_irq_p->head; prog_tail = prog_irq_p->head; vme_tail = vme_irq_p->head; /* ** Signal bt_icbr_install() to continue, must do this after we have ** sampled the queue heads, otherwise main program may start and begin ** receiving interrupts before we have a valid head pointer, thus ** missing the first couple of interrupts */ pthread_cond_signal(&btd->icbr_started); pthread_mutex_unlock(&btd->mutex); /* ** Wait for some interrupts to occur */ thread_wait_data.thread_id = btd->thread_id; thread_wait_data.wait_msec = BT_FOREVER; while (1) { api_ret = bt_ctrl(btd, BIOC_THREAD_WAIT, &thread_wait_data); pthread_testcancel(); if (api_ret != BT_SUCCESS) { DBG_STR("Thread wait ioctl failed"); pthread_exit(NULL); } /* ** Parse the error, programmed & vme irq queues */ if (btd->icbr_head_p != NULL) { bt_irq_parse(btd, error_irq_p, &error_tail, BT_IRQ_ERROR); bt_irq_parse(btd, prog_irq_p, &prog_tail, BT_IRQ_PRG); bt_irq_parse(btd, vme_irq_p, &vme_tail, BT_IRQ_IACK); } else { error_tail = error_irq_p->head; prog_tail = prog_irq_p->head; vme_tail = vme_irq_p->head; } } /* ** Don't know how we would get here, but call the ** cleanup routine ** ** Note the pop() routine must exist otherwise it will not compile */ pthread_cleanup_pop(1); }
int fb_init() { bt_error_t status; /* Bit 3 library error return type */ char devname[BT_MAX_DEV_NAME]; /* Device to open */ bt_devdata_t flag; /* Open the device in A24 space */ bt_gen_name(0, BT_DEV_A24, devname, BT_MAX_DEV_NAME); status = bt_open(&btd, devname, BT_RDWR); if (status != BT_SUCCESS) { cm_msg(MERROR, "fb_init", "Cannot open Bit3 device driver"); return FALSE; } bt_init(btd); bt_clrerr(btd); /* map SFI memory */ status = bt_mmap(btd, &_sfi, SFI_ADDRESS, SFI_SIZE, BT_RDWR, BT_SWAP_DEFAULT); if (status != BT_SUCCESS) { cm_msg(MERROR, "fb_init", "Cannot map VME memory"); bt_close(btd); return FALSE; } /* Open the device in local memory */ bt_gen_name(0, BT_DEV_LM, devname, BT_MAX_DEV_NAME); status = bt_open(&btd_lm, devname, BT_RDWR); if (status != BT_SUCCESS) { cm_msg(MERROR, "fb_init", "Cannot open Bit3 device for local memory"); return FALSE; } bt_clrerr(btd_lm); /* map local memory */ status = bt_mmap(btd_lm, &remote_ram_buffer, 0, REMOTE_RAM_SIZE, BT_RDWR, BT_SWAP_DEFAULT); if (status != BT_SUCCESS) { cm_msg(MERROR, "fb_init", "Cannot map local memory"); bt_close(btd); return FALSE; } /* clear local memory */ memset(remote_ram_buffer, 0, REMOTE_RAM_SIZE); /* force D32 mode */ bt_get_info(btd, BT_INFO_MMAP_AMOD, &flag); flag = BT_AMOD_A24_SD; bt_set_info(btd, BT_INFO_MMAP_AMOD, flag); /* sequencer reset */ SFI_OUT(SFI_SEQUENCER_RESET, 0); /* arbitration level */ // SFI_OUT(SFI_FASTBUS_ARBITRATION_LEVEL_REGISTER, 0x15); SFI_OUT(SFI_FASTBUS_ARBITRATION_LEVEL_REGISTER, 0xBF); /* timeout */ SFI_OUT(SFI_FASTBUS_TIMEOUT_REGISTER, 0x73); /* sequencer enable */ SFI_OUT(SFI_SEQUENCER_ENABLE, 0); /* switch off all output */ SFI_OUT(SFI_CLEAR_BOTH_LCA1_TEST_REGISTER, 0); /* clear registers */ SFI_OUT(SFI_RESET_REGISTER_GROUP_LCA2, 0); return SUCCESS; }