/**************************************************************************** * sec2_io.c -- bus operations for SEC2 Driver **************************************************************************** * Copyright (c) Certicom Corp. 1996-2002. All rights reserved * Copyright (c) 2003, 2004 Freescale Semiconductor * All Rights Reserved. Proprietary and Confidential. * * NOTICE: The information contained in this file is proprietary * to Freescale Semiconductor, and is being made available to * Freescale's customers under strict license agreements. * Use or disclosure of this information is permissible only * under the terms of the existing license agreement. ***************************************************************************/ /* Revision History: * 1.0 Aug 24,2003 dgs adapted from the final version of mpc18x * May 12,2004 sec - switched core interrupt for 8555 configuration * 1.1.0 Dec 05,2004 sec - merge in linux support from prior versions * 1.1.1 Dec 16,2004 sec - remove lock variable, remove old diagnostics * 1.2 Jan 27,2005 */ #include "Sec2Driver.h" #ifdef __KERNEL__ extern void InterruptServiceRoutine(int irq, void *dev_id, struct pt_regs *pt_regs); #endif #ifdef VXWORKS #include "intLib.h" IO_STATUS IOInitQs() { /* set up ISR/ProcessingComplete message queue */ IsrMsgQId = msgQCreate(MAX_MESSAGES, sizeof(DEVICE_REGS), MSG_Q_FIFO); if (IsrMsgQId == NULL) return SEC2_VXWORKS_CANNOT_CREATE_QUEUE; return SEC2_SUCCESS; } IO_STATUS IORegisterDriver() { /* start ProcessComplete task, with high priority */ if (taskSpawn ("tSEC2_pc", PROCESSING_COMPLETE_PRIORITY, 0, PROCESSING_COMPLETE_STACKSIZE, (FUNCPTR)ProcessingComplete, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == TASK_ID_ERROR) return (SEC2_UNKNOWN_ERROR); /* add the driver to the driver table */ driverNum = iosDrvInstall(SEC2Open, NULL, SEC2Open, SEC2Close, NULL, NULL, SEC2_ioctl); if (driverNum < 0) return (SEC2_IO_VXWORKS_DRIVER_TABLE_ADD_ERROR); (void) iosDevAdd(&vxworksDrvDev, vxworksDrvName, driverNum); return (SEC2_SUCCESS); } #endif void IOInitSemaphores() { /* initialize semaphores */ #ifdef VXWORKS ChannelAssignSemId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); QueueSemId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); #endif #ifdef __KERNEL__ spin_lock_init(&ChannelAssignLock); spin_lock_init(&QueueLock); #endif } /* * IOConnectInterrupt() */ #ifdef VXWORKS /* the Interrupt connect should be moved to sysLib.c since it is board dependent */ IO_STATUS IOConnectInterrupt() { /* Interpeak begin */ int inum_sec2; extern int ipfreescale_sec_inum(void); inum_sec2 = ipfreescale_sec_inum(); /* Install our IRQ handler */ if (intConnect(INUM_TO_IVEC(inum_sec2), (VOIDFUNCPTR)InterruptServiceRoutine, (int)NULL) == ERROR) return(ERROR); /* Enable the handler at the controller level */ intEnable(inum_sec2); /* Interpeak end */ SEC2Dump(DBGTXT_INITDEV, ("IOConnectInterrupt ISR connected\n")); return(SEC2_SUCCESS); } #endif #ifdef __KERNEL__ IO_STATUS IOConnectInterrupt() { if ((request_irq(MPC85xx_IRQ_SEC, InterruptServiceRoutine, 0, "mpc-sec", NULL)) != 0) return -1; return (SEC2_SUCCESS); } #endif #ifdef __KERNEL__ #include #include #include unsigned long irq_flag; /* here for spin locks to use */ static inline int __sem_update_count(struct semaphore *sem, int incr) { int old_count, tmp; __asm__ __volatile__("\n" "1: lwarx %0,0,%3\n" " srawi %0,%0,31\n" " andc %1,%0,%1\n" " add %1,%1,%4\n" PPC405_ERR77(0,%3) " stwcx. %1,0,%3\n" " bne 1b" : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) : "r" (&sem->count), "r" (incr), "m" (sem->count) : "cc"); return old_count; } long __down_interruptible_timeout(struct semaphore *sem, long timeout) { int retval = 0; struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); tsk->state = TASK_INTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); smp_wmb(); while (__sem_update_count(sem, -1) <= 0) { if (signal_pending(current)) { __sem_update_count(sem, 0); retval = -EINTR; break; } timeout = schedule_timeout(timeout); tsk->state = TASK_INTERRUPTIBLE; } tsk->state = TASK_RUNNING; remove_wait_queue(&sem->wait, &wait); wake_up(&sem->wait); return timeout >= 0 ? 0 : -1; } #endif