/* * Cleanup - unregister the appropriate file from /proc */ void ip860_intr_cleanup (void) { int irq; debugk ("Cleanup IP860 Interrupt Support\n"); /* make sure all interrupts are disabled */ /* VME Interrupts first */ for (irq=0; irq < NR_VME_INTERRUPTS; ++irq) { if (vme_intr_hdlr[irq].handler) { debugk ("Cleanup VME Interrupt handler vector 0x%02x\n", irq); free_ip860_irq (irq); } } /* the Onboard Interrupts */ for ( ; irq < NR_VME_INTERRUPTS+NR_ONBOARD_INTERRUPTS; ++irq) { int index = irq - NR_VME_INTERRUPTS; if (onbd_intr_hdlr[index].int_hand.handler) { debugk ("Cleanup Onboard Interrupt handler vector 0x%02x\n", irq); free_ip860_irq (irq); } } debugk ("Cleanup completed\n"); }
/*********************************************************************** F* Function: static ssize_t wd_write(struct file *filp, const char *buffer, size_t length, loff_t *offset) P*A*Z* * P* Parameters: struct file *file P* - Passed by the kernel, pointer to the file structure P* for the device file P* char *buf P* - Pointer to buffer in userspace P* size_t count P* - Number of bytes to write P* loff_t *ppos P* - Offset for the write - ignored. P* P* Returnvalue: int P* - >0 number of bytes actually written, i.e. 4 P* <0 Errorcondition, which can be P* -EINVAL When trying to write more or less than 4 P* bytes, i.e. sizeof(unsigned) P* -EFAULT A user-provided pointer is invalid * Z* Intention: Set the rest counter to the value provided by the user Z* process interpreted as a number of seconds. * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ static ssize_t wd_write(struct file *filp, const char *buffer, size_t length, loff_t *offset) { int error; unsigned int new_count; debugk("ENTER %s (%p, %p, %d, %p)\n", __FUNCTION__, filp, buffer, length, offset); if (length != sizeof(new_count)) { debugk("%s: invalid length (%d instead of %d)\n", __FUNCTION__, length, sizeof(new_count)); return -EINVAL; } /* copy count value into kernel space */ if ((error = get_user(new_count, (int *) buffer)) != 0) { debugk("%s: get_user failed: rc=%d\n", __FUNCTION__, error); return error; } /* * The external interface is in seconds, but internal all calculations * is done in jiffies. */ timer_count = HZ * new_count; return sizeof(new_count); }
/*********************************************************************** F* Function: static ssize_t wdt_mpc8xx_write (struct file *filp, const char *buffer, size_t length, loff_t *offset) P*A*Z* * P* Parameters: struct file *file P* - Passed by the kernel, pointer to the file structure P* for the device file P* char *buf P* - Pointer to buffer in userspace P* size_t count P* - Number of bytes to write P* loff_t *ppos P* - Offset for the write - ignored. P* P* Returnvalue: int P* - >0 number of bytes actually written, i.e. 4 P* <0 Errorcondition, which can be P* -EINVAL When trying to write more or less than 4 P* bytes, i.e. sizeof(unsigned) P* -EFAULT A user-provided pointer is invalid * Z* Intention: Set the rest counter to the value provided by the user Z* process interpreted as a number of seconds. * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ static ssize_t wdt_mpc8xx_write (struct file *filp, const char *buffer, size_t length, loff_t *offset) { int error; unsigned int new_count; debugk ("ENTER %s (%p, %p, %d, %p)\n", __FUNCTION__, filp, buffer, length, offset); if (length != sizeof(new_count)) { debugk ("%s: invalid length (%d instead of %d)\n", __FUNCTION__, length, sizeof(new_count)); return -EINVAL; } /* copy count value into kernel space */ if ((error = get_user (new_count, (int *) buffer)) != 0) { debugk ("%s: get_user failed: rc=%d\n", __FUNCTION__, error); return (error); } timer_count = HZ * new_count; return (sizeof(new_count)); }
void soc_internal_init_hash_state(pcid_info_t *pcid_info) { int t, s, b; uint32 rval, banks; soc_block_t blk; uint8 at; /* Assign everything to ESM to begin with */ for (b = 0; b < _SOC_ISM_MAX_BANKS; b++) { _soc_ism_bank_avail[pcid_info->unit][b] = SOC_ISM_MEM_ESM_L2; } for (t = 0; t < _SOC_ISM_MAX_TABLES; t++) { soc_internal_extended_read_reg(pcid_info, blk, at, soc_reg_addr_get(pcid_info->unit, _ism_table_bank_cfg_reg[t], REG_PORT_ANY, 0, &blk, &at), &rval); debugk(DK_VERBOSE, "Table: %d = %x\n", t, rval); for (s = 0; s < _SOC_ISM_MAX_STAGES; s++) { banks = soc_reg_field_get(pcid_info->unit, _ism_table_bank_cfg_reg[t], rval, _ism_table_bank_cfg_fld[s]); for (b = 0; b < _SOC_ISM_BANKS_PER_STAGE; b++) { if (banks & (1 << b)) { debugk(DK_VERBOSE, "Bank[%d] = mem[%d]\n", (s * _SOC_ISM_BANKS_PER_STAGE) + b, t+1); _soc_ism_bank_avail[pcid_info->unit][(s * _SOC_ISM_BANKS_PER_STAGE) + b] = t+1; } } } } }
int soc_internal_generic_hash_lookup(pcid_info_t *pcid_info, soc_mem_t mem, int banks, void *entry, uint32 *result) { int rc; uint32 index; schan_genresp_v2_t *genresp = (schan_genresp_v2_t *) result; uint32 opres; debugk(DK_VERBOSE, "Mem: %d\n", mem); rc = soc_internal_generic_hash(pcid_info, mem, entry, banks, TABLE_LOOKUP_CMD_MSG, &index, &opres); genresp->err_info = 0; if (rc) { genresp->type = SCHAN_GEN_RESP_TYPE_ERROR; genresp->index = -1; } else if (opres == SCHAN_GEN_RESP_TYPE_NOT_FOUND) { genresp->type = opres; genresp->index = -1; debugk(DK_VERBOSE, "Not found\n"); } else { genresp->type = opres; genresp->index = index; debugk(DK_VERBOSE, "Found Index: %d\n", index); } return SOC_E_NONE; }
uint32 pci_config_getw(pci_dev_t *dev, uint32 addr) { UINT32 inWord = 0; STATUS requestStatus; assert(! (addr & 3)); debugk(DK_PCI, "PCI(%d,%d,%d) configR(0x%x)=", dev->busNo, dev->devNo, dev->funcNo, addr); requestStatus = pciConfigInLong(dev->busNo, dev->devNo, dev->funcNo, addr, (UINT32*) &inWord); if (requestStatus != OK) { printk("ERROR: PCI configuration read bus=%d dev=%d func=%d " "(0x%x=0x%x) -READ ERROR(%d)\n", dev->busNo, dev->devNo, dev->funcNo, addr, inWord, requestStatus); return -1; } else { debugk(DK_PCI, "0x%x\n", inWord); return inWord; } }
/*********************************************************************** F* Function: static int wd_release(struct inode *inode, F* struct file *filp) P*A*Z* * P* Parameters: struct inode *inode P* - Inode of the device file being closed P* struct file *file P* - Passed by the kernel, but not used P* P* Returnvalue: int P* - 0 is always returned * Z* Intention: This function is called by the kernel when a device file Z* of the driver is closed with close(2). * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ static int wd_release(struct inode *inode, struct file *filp) { debugk("ENTER %s (%p, %p)\n", __FUNCTION__, inode, filp); device_open--; /* decrement usage counter */ debugk("%s: /dev/watchdog closed\n", __FUNCTION__); return 0; }
/*********************************************************************** F* Function: static int wdt_mpc8xx_release (struct inode *inode, F* struct file *filp) P*A*Z* * P* Parameters: struct inode *inode P* - Inode of the device file being closed P* struct file *file P* - Passed by the kernel, but not used P* P* Returnvalue: int P* - 0 is always returned * Z* Intention: This function is called by the kernel when a device file Z* of the driver is closed with close(2). * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ static int wdt_mpc8xx_release (struct inode *inode, struct file *filp) { debugk ("ENTER %s (%p, %p)\n", __FUNCTION__, inode, filp); device_open--; /* decrement usage counter */ MOD_DEC_USE_COUNT; debugk ("%s: WDT is closed\n", __FUNCTION__); return 0; }
/*********************************************************************** F* Function: static int wd_open(struct inode *inode, F* struct file *filp) P*A*Z* * P* Parameters: struct inode *inode P* - Inode of the device file being opened P* struct file *file P* - Passed by the kernel, but not used P* P* Returnvalue: int - 0 success P* <0 Errorcondition, which can be P* -ENXIO Watchdog is not enabled * Z* Intention: This function is called by the kernel when a device file Z* for the driver is opened by open(2). * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ static int wd_open(struct inode *inode, struct file *filp) { debugk("ENTER %s (%p, %p)\n", __FUNCTION__, inode, filp); if (!enabled) { /* user interface disabled */ return -ENXIO; } device_open++; /* increment usage counter */ opened = 1; debugk("%s: /dev/watchdog opened\n", __FUNCTION__); return 0; }
/*********************************************************************** F* Function: static int wdt_mpc8xx_open (struct inode *inode, F* struct file *filp) P*A*Z* * P* Parameters: struct inode *inode P* - Inode of the device file being opened P* struct file *file P* - Passed by the kernel, but not used P* P* Returnvalue: int - 0 success P* <0 Errorcondition, which can be P* -ENXIO Watchdog is not enabled * Z* Intention: This function is called by the kernel when a device file Z* for the driver is opened by open(2). * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ static int wdt_mpc8xx_open (struct inode *inode, struct file *filp) { debugk ("ENTER %s (%p, %p)\n", __FUNCTION__, inode, filp); if (!enabled) { /* user interface disabled */ return -ENXIO; } device_open++; /* increment usage counter */ MOD_INC_USE_COUNT; debugk ("%s: WDT is open\n", __FUNCTION__); return 0; }
int soc_internal_generic_hash_delete(pcid_info_t *pcid_info, soc_mem_t mem, int banks, void *entry, uint32 *result) { int rc, blk; soc_block_t sblk; uint8 at; uint32 index, opres, tmp[SOC_MAX_MEM_WORDS]; int unit = pcid_info->unit; schan_genresp_v2_t *genresp = (schan_genresp_v2_t *) result; debugk(DK_VERBOSE, "Mem: %d\n", mem); rc = soc_internal_generic_hash(pcid_info, mem, entry, banks, TABLE_DELETE_CMD_MSG, &index, &opres); genresp->err_info = 0; if (rc) { genresp->type = SCHAN_GEN_RESP_TYPE_ERROR; genresp->index = -1; } else if (opres == SCHAN_GEN_RESP_TYPE_NOT_FOUND) { genresp->type = opres; genresp->index = -1; debugk(DK_VERBOSE, "Not found\n"); } else { genresp->type = opres; genresp->index = index; blk = SOC_MEM_BLOCK_ANY(unit, mem); sblk = SOC_BLOCK2SCH(unit, blk); soc_internal_extended_read_mem(pcid_info, sblk, at, soc_mem_addr_get(unit, mem, 0, blk, index, &at), (uint32 *)entry); if (soc_mem_field_valid(unit, mem, VALIDf)) { soc_mem_field32_set(unit, mem, tmp, VALIDf, 0); } else { soc_mem_field32_set(unit, mem, tmp, VALID_0f, 0); if (soc_mem_field_valid(unit, mem, VALID_1f)) { soc_mem_field32_set(unit, mem, tmp, VALID_1f, 0); } if (soc_mem_field_valid(unit, mem, VALID_2f)) { soc_mem_field32_set(unit, mem, tmp, VALID_2f, 0); } if (soc_mem_field_valid(unit, mem, VALID_3f)) { soc_mem_field32_set(unit, mem, tmp, VALID_3f, 0); } } soc_internal_extended_write_mem(pcid_info, sblk, at, soc_mem_addr_get(unit, mem, 0, blk, index, &at), (uint32 *)tmp); debugk(DK_VERBOSE, "Deleted Index: %d\n", index); } return SOC_E_NONE; }
/*********************************************************************** F* Function: void wdt_mpc8xx_reset (void) P*A*Z* * P* Parameters: none P* P* Returnvalue: none * Z* Intention: Reset the hardware watchdog. Z* This function is callable from other kernel functions, Z* too. * D* Design: [email protected] C* Coding: [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ void wdt_mpc8xx_reset (void) { volatile immap_t *imap = (immap_t *) IMAP_ADDR; #if defined(CONFIG_LWMON) /* * The LWMON board uses a MAX706TESA Watchdog * with the trigger pin connected to port PA.7 * * The port has already been set up in the firmware, * so we just have to toggle it. */ imap->im_ioport.iop_padat ^= 0x0100; /* * Do NOT add a call to "debugk()" here; * it would be called TOO often. */ #else /* * All other boards use the MPC8xx Internal Watchdog */ imap->im_siu_conf.sc_swsr = 0x556C; imap->im_siu_conf.sc_swsr = 0xAA39; debugk ("%s: WDT serviced\n", __FUNCTION__); #endif /* CONFIG_LWMON */ }
uint32 pcid_dcb_fetch(pcid_info_t *pcid_info, uint32 addr, dcb_t *dcb) { int size, i; uint32 *temp; debugk(DK_DMA, "Reading descriptor at 0x%08x\n", addr); size = SOC_DCB_SIZE(pcid_info->unit); soc_internal_bytes_fetch(pcid_info, addr, (uint8 *)dcb, size); /* Convert to chip(same as host for sim mode) endian-ness */ temp = (uint32 *)dcb; for (i=0; i < (size/sizeof(uint32)); i++) { *(temp + i) = soc_internal_endian_swap(pcid_info, *(temp + i), MF_ES_DMA_OTHER); } #ifdef BROADCOM_DEBUG if (debugk_check(DK_DMA)) { SOC_DCB_DUMP(pcid_info->unit, dcb, "PCID Fetch", 0); } #endif /* BROADCOM_DEBUG */ return addr + size; }
int replayfs_fs_init(void) { int err; perftimer_init(); debugk("Sizeof pgoff_t is %u, loff_t %u\n", sizeof(pgoff_t), sizeof(loff_t)); if (PAGE_SIZE != sizeof(struct replayfs_dir_page)) { printk("REPLAYFS ERROR: PAGE_SIZE == %lu, replayfs_dir_page size == %d\n", PAGE_SIZE, sizeof(struct replayfs_dir_page)); return 1; } /* Init memory management */ if (replayfs_init_allocators()) { return 1; } /* All is going well so far, setup our super block */ err = register_filesystem(&replayfs_type); if (err) { replayfs_destroy_allocators(); return 1; } return 0; }
/*********************************************************************** F* Function: void cleanup_module (void) P*A*Z* * P* Parameters: none P* P* Returnvalue: none * Z* Intention: Cleanup and shutdown the driver to allow unloading Z* of the module. * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ void cleanup_module (void) { debugk ("%s: cleanup WDT8xx\n", __FUNCTION__); del_timer (&wd_timer); free_mon_list(); misc_deregister (&wdt_miscdev); }
static int replayfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) { struct inode *inode; int err; inode = replayfs_new_inode(dir->i_sb, mode); err = PTR_ERR(inode); debugk("%s %d: Creating a new inode, parent has mode %o\n", __func__, __LINE__, dir->i_mode); if (!IS_ERR(inode)) { replayfs_log_t log; replayfs_log_inode_t log_inode; inode->i_op = &replayfs_file_iops; inode->i_mapping->a_ops = &replayfs_aops; inode->i_fop = &replayfs_fops; replayfs_begin_log_operation(&log); replayfs_log_add_inode(&log, &log_inode, dentry->d_parent->d_inode); mark_inode_dirty(inode); err = replayfs_dir_add_nondir(dentry, inode, &log, &log_inode); replayfs_log_inode_done(&log, &log_inode, dentry->d_parent->d_inode->i_size); /* Save the metadata modification to the new inode */ replayfs_log_add_inode(&log, &log_inode, inode); replayfs_inode_modified_metadata(inode, &log, &log_inode); replayfs_log_inode_done(&log, &log_inode, inode->i_size); replayfs_end_log_operation(&log); } debugk("%s %d: Done creating a new inode\n", __func__, __LINE__); return err; }
/*********************************************************************** F* Function: void wd_cleanup(void) P*A*Z* * P* Parameters: none P* P* Returnvalue: none * Z* Intention: Cleanup and shutdown the driver to allow unloading Z* of the module. * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ void wd_cleanup(void) { debugk("%s: cleanup WD\n", __FUNCTION__); misc_deregister(&wd_miscdev); BUG_ON(wd_hw_functions.wd_delete == NULL); wd_hw_functions.wd_delete(); del_timer(&wd_timer); free_mon_list(); }
int soc_internal_generic_hash_insert(pcid_info_t *pcid_info, soc_mem_t mem, int32 banks, void *entry, uint32 *result) { int rc, blk; soc_block_t sblk; uint8 at; uint32 index, opres; int unit = pcid_info->unit; schan_genresp_v2_t *genresp = (schan_genresp_v2_t *) result; debugk(DK_VERBOSE, "Mem: %d\n", mem); rc = soc_internal_generic_hash(pcid_info, mem, entry, banks, TABLE_INSERT_CMD_MSG, &index, &opres); genresp->err_info = 0; if (rc) { genresp->type = SCHAN_GEN_RESP_TYPE_ERROR; genresp->index = -1; } else { genresp->type = opres; if (opres == SCHAN_GEN_RESP_TYPE_FULL) { genresp->index = -1; debugk(DK_VERBOSE, "Full\n"); } else { blk = SOC_MEM_BLOCK_ANY(unit, mem); sblk = SOC_BLOCK2SCH(unit, blk); genresp->index = index; soc_internal_extended_write_mem(pcid_info, sblk, at, soc_mem_addr_get(unit, mem, 0, blk, index, &at), (uint32 *)entry); if (opres == SCHAN_GEN_RESP_TYPE_REPLACED) { debugk(DK_VERBOSE, "Replace "); } else { debugk(DK_VERBOSE, "Insert "); } debugk(DK_VERBOSE, "Index: %d\n", index); } } return SOC_E_NONE; }
/*********************************************************************** F* Function: static ssize_t wdt_mpc8xx_read (struct file *filp, char *buffer, size_t length, loff_t *offset) P*A*Z* * P* Parameters: struct file *file P* - Passed by the kernel, pointer to the file structure P* for the device file P* char *buf P* - Pointer to buffer in userspace P* size_t count P* - Number of bytes to read P* loff_t *ppos P* - Offset for the read - ignored. P* P* Returnvalue: int P* - >0 number of bytes read, i.e. 4 P* <0 Errorcondition, which can be P* -EINVAL When trying to read fewer bytes than the P* rest counter occupies, i.e. sizeof(unsigned) P* -EFAULT A user-provided pointer is invalid * Z* Intention: Read the rest counter from the device. * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ static ssize_t wdt_mpc8xx_read (struct file *filp, char *buffer, size_t length, loff_t *offset) { unsigned int rest_count = timer_count / HZ; int rc; debugk ("ENTER %s (%p, %p, %d, %p)\n", __FUNCTION__, filp, buffer, length, offset); if (length < sizeof(rest_count)) { debugk ("wdt_mpc8xx_release/kernel: invalid argument\n"); return -EINVAL; } /* copy value into userspace */ if ((rc=put_user (rest_count, (int *) buffer))) return(rc); debugk ("%s: rest_count=%i\n", __FUNCTION__, rest_count); return (sizeof(rest_count)); /* read always exactly 4 bytes */ }
/*********************************************************************** F* Function: void wd_handler(unsigned long ptr) P*A*Z* * P* Parameters: unsigned long ptr P* - Parameter passed in from the timer invocation, ignored P* P* Returnvalue: none * Z* Intention: This is the core functionality of the watchdog. It is Z* called from the timer wd_timer and handles the necessary Z* processing, including resetting the hardware watchdog. Z* When chains are registered, they override the Z* default behaviour and are processed in process_mon_chains(). * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ void wd_handler(unsigned long ptr) { debugk("%s: timer_count=%ld jiffies\n", __FUNCTION__, timer_count); if ((timer_count == 0) && enabled) { printk("WD: Reseting system...\n"); BUG_ON(wd_hw_functions.wd_machine_restart == NULL); wd_hw_functions.wd_machine_restart(); } else if ((timer_count > 0) || (!enabled)) { /* execute WD service sequence */ BUG_ON(wd_hw_functions.wd_kick == NULL); wd_hw_functions.wd_kick(); wd_timer.expires = jiffies + timer_period; add_timer(&wd_timer); /* ...re-activate timer */ /* * process the monitor list */ process_mon_chains(); /* * don't timeout if disabled */ if (!enabled) return; /* don't timeout if interface was never opened */ if (!opened) return; /* * don't timeout if new interface is used or if device * is not opened */ if (((timeout_open_only && (!device_open)) || mon_chains)) return; /* decrement variable for timer-control */ if (timer_count > timer_period) timer_count -= timer_period; else timer_count = 0; if (timer_count == 0) printk("WD: watchdog about to expire\n"); } return; }
/*********************************************************************** F* Function: static void free_mon_list(void) P*A*Z* * P* Parameters: none P* P* Returnvalue: none * Z* Intention: This function frees the entire kmalloc'ed list of Z* monitored chains in case the module is unloaded. * D* Design: [email protected] C* Coding: [email protected] V* Verification: [email protected] ***********************************************************************/ static void free_mon_list(void) { struct list_head *ptr, *n; monitored_chain_t *entry; debugk("%s: WDT8xx freeing monitor list\n", __FUNCTION__); spin_lock(&mon_lock); for (ptr=mon_list.next, n=ptr->next; ptr!=&mon_list; ptr=n) { entry=list_entry(ptr, monitored_chain_t, list); kfree(entry); } spin_unlock(&mon_lock); }
int pci_config_putw(pci_dev_t *dev, uint32 addr, uint32 data) { STATUS requestStatus; debugk(DK_PCI, "PCI(%d,%d,%d) configW(0x%x)=0x%x\n", dev->busNo, dev->devNo, dev->funcNo, addr, data); assert(! (addr & 3)); requestStatus = pciConfigOutLong(dev->busNo, dev->devNo, dev->funcNo, (int) addr, (UINT32) data); return requestStatus; }
/*********************************************************************** F* Function: int wdt_mpc8xx_unregister_mon_chain(unsigned int chainid) P*A*Z* * P* Parameters: unsigned int chainid P* - The id of the chain to unregister P* P* Returnvalue: int P* - 0 The chain was unregistered successfully P* -EINVAL The chainid is unknown * Z* Intention: When the watchdog functionality is no longer needed, Z* chains can be unregistered through this call. Z* The function is called through the ioctl() mechanism Z* or directly from other kernel proper, as it is exported. * D* Design: [email protected] C* Coding: [email protected] V* Verification: [email protected] ***********************************************************************/ int wdt_mpc8xx_unregister_mon_chain(unsigned int chainid) { monitored_chain_t *entry; if ((entry=find_mon_chain_by_chainid(chainid))==NULL) return(-EINVAL); debugk("%s: WDT8xx unregistering monitor for id %d\n", __FUNCTION__, entry->chainid); spin_lock(&mon_lock); list_del(&entry->list); kfree(entry); spin_unlock(&mon_lock); return(0); }
/*********************************************************************** F* Function: int wd_reset_mon_chain(int chainid) P*A*Z* * P* Parameters: int chainid P* - The id of the chain to reset P* P* Returnvalue: int P* - 0 The chain was reset suiccessfully P* <0 Errorcondition, which can be P* -EINVAL The supplied id is unknown. * Z* Intention: This function resets a chain to its initial state. Z* The function is called through the ioctl() mechanism Z* to reset or trigger a chain or directly from other Z* kernel proper, as it is exported. * D* Design: [email protected] C* Coding: [email protected] V* Verification: [email protected] ***********************************************************************/ int wd_reset_mon_chain(int chainid) { monitored_chain_t *entry; int result = 0; debugk("%s: WD monitor reset for id %d\n", __FUNCTION__, chainid); spin_lock(&mon_lock); if ((entry = find_mon_chain_by_chainid(chainid)) == NULL) { result = -EINVAL; goto out; } entry->escalation = 0; entry->expires = jiffies + HZ * entry->timer_count[0]; list_del(&entry->list); insert_mon_chain(entry); out: spin_unlock(&mon_lock); return result; }
/*************************************************************************** * * Initialize the module */ static int __init ip860_intr_init (void) { vme_mem_t *p; printk (KERN_INFO "IP860 Extended Interrupt Support version " IP860_INTR_VERSION "\n" ); if ((p = vme_mem_dev(VME_MEM_BCSR)) == NULL) return (-ENODEV); bcsr = (ip860_bcsr_t *)(p->addr); if ((p = vme_mem_dev(VME_MEM_IPMOD)) == NULL) return (-ENODEV); ip_mod = (vu_short *)(p->addr); debugk ("IP860 Interrupt Support installed\n"); return 0; }
/* * main: Sets up the socket and handles client requests with a child * process per socket. */ void dmac_listener(void *v_void) { verinet_t *v = (verinet_t *)v_void; int sockfd, newsockfd, one = 1; socklen_t clilen; struct sockaddr_in cli_addr, serv_addr; /* Initialize socket ... */ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("server: can't open stream socket"); exit(1); } if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof (one)) < 0) { perror("setsockopt"); } /* * Setup server address... */ memset((void *) &serv_addr,0x0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(0); /* Pick any port */ /* * Bind our local address */ if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { perror("dmac: unable to bind address"); sal_thread_exit(0); } v->dmaPort = getsockport(sockfd); /* Get port that was picked */ /* listen for inbound connections ... */ listen(sockfd, 5); /* Notify dmac_init that socket is listening */ sal_sem_give(v->dmacListening); printk("DMA Controller listening on port[%d]\n", v->dmaPort); while (!v->dmacWorkerExit) { clilen = sizeof(cli_addr); newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if (newsockfd < 0 && errno == EINTR) { continue; } if (newsockfd < 0) { perror("server: accept error"); } else { v->dmacFd = newsockfd; v->dmacHandler = sal_thread_create("DMA-controller", SAL_THREAD_STKSZ, 100, dmac_handler, v); if (SAL_THREAD_ERROR == v->dmacHandler) { printk("Thread creation error!\n"); } else { debugk(DK_VERINET, "DMAC request thread dispatched.\n"); } } } debugk(DK_VERINET, "DMA listener shutdown.\n"); sal_thread_exit(0); }
/* * Main thread of control. This worker thread will service requests * on a socket, read or writing to memory based on the command * dispatched from the main execution thread. */ void dmac_handler(void *v_void) { verinet_t *v = (verinet_t *)v_void; volatile int finished = 0; volatile uint32 dmaAddr, dmaData; rpc_cmd_t cmd; int sockfd = v->dmacFd; uint8 *byte_ptr; uint32 i; while (!finished){ debugk(DK_VERINET, "dmac_handler: wait...\n"); if (wait_command(sockfd, &cmd) < 0) { break; /* Error message already printed */ } debugk(DK_VERINET, "dmac_handler: request opcode 0x%x\n", cmd.opcode); switch(cmd.opcode){ case RPC_DMAC_READ_REQ: /* Read DMA memory ... */ dmaAddr = cmd.args[0]; /* Read data from shared memory at Addr */ dmaData = _dma_getw(dmaAddr); debugk(DK_VERINET, "**DMA_RD: 0x%x = 0x%x\n", dmaAddr, dmaData); /* Send back a response */ make_rpc_getmem_resp(&cmd, dmaData); write_command(sockfd, &cmd); break; case RPC_DMAC_WRITE_REQ: /* Write DMA memory ... */ dmaAddr = cmd.args[0]; /* Address */ dmaData = cmd.args[1]; /* Data */ /* Write the data to shared memory */ _dma_putw(dmaAddr, dmaData); debugk(DK_VERINET, "**DMA_WR: 0x%x = 0x%x\n", dmaAddr, dmaData); /* Send back a response */ make_rpc_setmem_resp(&cmd,dmaData); write_command(sockfd, &cmd); break; case RPC_DMAC_READ_BYTES_REQ: /* Read DMA memory as a string. Would be nice to use memcpy */ dmaAddr = cmd.args[0]; byte_ptr = (uint8 *)&cmd.args[1]; debugk(DK_VERINET, "**DMA_RD_B: 0x%x, %d bytes\n", dmaAddr, cmd.argcount); for (i = 0; i < cmd.argcount; i++) { byte_ptr[i] = _dma_getb(dmaAddr++); } /* Send back a response */ cmd.status = RPC_OK; cmd.opcode = RPC_DMAC_READ_BYTES_RESP; write_command(sockfd, &cmd); break; case RPC_DMAC_WRITE_BYTES_REQ: /* Write DMA memory as a string. Would be nice to use memcpy */ dmaAddr = cmd.args[0]; /* Address */ byte_ptr = (uint8 *)&cmd.args[1]; /* Data */ /* Write the data to shared memory */ debugk(DK_VERINET, "**DMA_WR_B: 0x%x, %d bytes\n", dmaAddr, cmd.argcount); for (i = 0; i < cmd.argcount; i++) { _dma_putb(dmaAddr++, byte_ptr[i]); } /* Send back a response */ cmd.status = RPC_OK; cmd.opcode = RPC_DMAC_WRITE_BYTES_RESP; write_command(sockfd, &cmd); break; case RPC_DISCONNECT: finished = 1; v->dmacWorkerExit++; printk("dma thread received disconnect\n"); exit(0); break; default: /* Unknown opcode */ break; } } printk("DMA controller shutdown.\n"); close(sockfd); sal_thread_exit(0); }
/*********************************************************************** F* Function: static int register_mon_chain(wdt_mpc8xx_param_t *param, F* int userproc) P*A*Z* * P* Parameters: wdt_mpc8xx_param_t *param P* - The parameters for the chain to be registered. P* Unused stages should be cleared with 0's. P* int userproc P* - Flag whether we are called from user or kernel space P* P* Returnvalue: int P* - 0 success P* -EINVAL invalid parameters P* -ENOMEM out of memory * Z* Intention: This is the main interface to register a watchdog chain Z* either from userspace throught ioctl() or from kernel Z* space through the wrapper function Z* wdt_mpc8x_register_mon_chain(). Z* Re-registering an existing chain is explicitely ok, as Z* a restarted process has to go through this. This Z* effectively resets the corresponding chain. Z* For a detailed description of the parameters, see the Z* wdt_mpc8xx(4) manpage. * D* Design: [email protected] C* Coding: [email protected] V* Verification: [email protected] ***********************************************************************/ static int register_mon_chain(wdt_mpc8xx_param_t *param, int userproc) { monitored_chain_t *entry; int result=0, i; /* Before kmallocing storage we first check the parameters */ for (i=0; (i<3)&&(param->timer_count[i]); i++) if ((param->action[i]<WDT_MPC8XX_ACTION_SIGNAL)|| (param->action[i]>WDT_MPC8XX_ACTION_RESET)) return(-EINVAL); debugk("%s: registering WDT8xx monitor\n", __FUNCTION__); spin_lock(&mon_lock); if ((entry=find_mon_chain_by_chainid(param->chainid))==NULL) { /* New chain-id so allocate list entry */ entry=(monitored_chain_t *)kmalloc(sizeof(monitored_chain_t), GFP_KERNEL); if (entry==NULL) { result=-ENOMEM; goto out; } /* Copy request data to internal format */ if (userproc) entry->pid=current->pid; else entry->pid=0; entry->chainid=param->chainid; entry->signal=param->signal; for (i=0; i<2 ; i++) { if (entry->action[i]!=0) { entry->timer_count[i]=param->timer_count[i]; entry->action[i]=param->action[i]; } else { /* Fill with stop entries */ entry->timer_count[i]=2; entry->action[i]=WDT_MPC8XX_ACTION_RESET; } } /* This is a final stop entry */ entry->timer_count[3]=2; entry->action[3]=WDT_MPC8XX_ACTION_RESET; /* Initialize internal data */ entry->escalation=0; entry->expires=jiffies + HZ * entry->timer_count[0]; insert_mon_chain(entry); mon_chains++; } else { /* Re-registering of active monitor */ entry->pid=current->pid; entry->escalation=0; entry->expires=jiffies + HZ * entry->timer_count[0]; entry->escalation=0; list_del(&entry->list); insert_mon_chain(entry); } out: spin_unlock(&mon_lock); return(result); }
/*********************************************************************** F* Function: void wdt_mpc8xx_handler (unsigned long ptr) P*A*Z* * P* Parameters: unsigned long ptr P* - Parameter passed in from the timer invocation, ignored P* P* Returnvalue: none * Z* Intention: This is the core functionality of the watchdog. It is Z* called from the timer wd_timer and handles the necessary Z* processing, including resetting the hardware watchdog. Z* When chains are registered, they override the Z* default behaviour and are processed in process_mon_chains(). * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ void wdt_mpc8xx_handler (unsigned long ptr) { #ifndef CONFIG_LWMON /* This produces too much output on the LWMON */ debugk ("%s: timer_count=%d jiffies\n", __FUNCTION__, timer_count); #endif /* * Signal arch/ppc/kernel/time.c that this driver has taken * over the responsibility to trigger the watchdog */ wdt_mpc8xx_is_ready = 1; if ((timer_count == 0) && enabled) { /* try "graceful" shutdown */ printk ("WDT_8xx: Reset system...\n"); #ifdef CONFIG_8xx m8xx_restart (NULL); #else machine_restart (NULL); #endif } if ((timer_count > 0) || (!enabled)) { /* execute WDT service sequence */ wdt_mpc8xx_reset (); wd_timer.expires = jiffies + timer_period; add_timer (&wd_timer); /* ...re-activate timer */ /* * process the monitor list */ process_mon_chains(); /* * don't timeout if disabled */ if (!enabled) return; /* * don't timeout if new interface is used or if device * is not opened */ if ((timeout_open_only && (!device_open)) || mon_chains) return; /* decrement variable for timer-control */ if (timer_count > timer_period) timer_count -= timer_period; else timer_count = 0; if (timer_count == 0) { printk ("WDT_8xx: watchdog about to expire\n"); } } return; }
/*********************************************************************** F* Function: int init_module (void) P*A*Z* * P* Parameters: none P* P* Returnvalue: int P* - see wdt_mpc8xx_init() * Z* Intention: This is a wrapper function for the module initialization Z* simply calling wdt_mpc8xx_init(). * D* Design: Haider / [email protected] C* Coding: Haider / [email protected] V* Verification: [email protected] / [email protected] ***********************************************************************/ int init_module (void) { debugk ("%s: initialize WDT8xx\n", __FUNCTION__); return wdt_mpc8xx_init (); }