11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: timer.c,v 1.3.6.1 2001/09/23 22:24:59 kai Exp $
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1996  SpellCaster Telecommunications Inc.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software may be used and distributed according to the terms
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the GNU General Public License, incorporated herein by reference.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For more information, please contact gpl-info@spellcast.com or write:
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     SpellCaster Telecommunications Inc.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     5621 Finch Avenue East, Unit #3
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     Scarborough, Ontario  Canada
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     M1B 2T9
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     +1 (416) 297-8565
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     +1 (416) 297-6433 Facsimile
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "includes.h"
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hardware.h"
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "message.h"
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "card.h"
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Write the proper values into the I/O ports following a reset
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
27e3ca5e762c2aca373f1762cbc622ebe20fd20869Adrian Bunkstatic void setup_ports(int card)
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb((sc_adapter[card]->rambase >> 12), sc_adapter[card]->ioport[EXP_BASE]);
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* And the IRQ */
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb((sc_adapter[card]->interrupt | 0x80),
34475be4d85a274d0961593db41cf85689db1d583cJoe Perches	     sc_adapter[card]->ioport[IRQ_SELECT]);
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Timed function to check the status of a previous reset
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be very fast as this function runs in the context of
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * an interrupt handler.
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Setup the ioports for the board that were cleared by the reset.
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Then, check to see if the signate has been set. Next, set the
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * signature to a known value and issue a startproc if needed.
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
46e3aded3cc289113c7bc729ef4cb75e56d9aa71beAlexey Dobriyanvoid sc_check_reset(unsigned long data)
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long sig;
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int card = (unsigned int) data;
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pr_debug("%s: check_timer timer called\n",
53475be4d85a274d0961593db41cf85689db1d583cJoe Perches		 sc_adapter[card]->devicename);
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Setup the io ports */
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	setup_ports(card);
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&sc_adapter[card]->lock, flags);
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport],
60475be4d85a274d0961593db41cf85689db1d583cJoe Perches	     (sc_adapter[card]->shmem_magic >> 14) | 0x80);
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sig = (unsigned long) *((unsigned long *)(sc_adapter[card]->rambase + SIG_OFFSET));
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check the signature */
64475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if (sig == SIGNATURE) {
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flushreadfifo(card);
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* See if we need to do a startproc */
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (sc_adapter[card]->StartOnReset)
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			startproc(card);
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else  {
713879b6b6a8ee39b50559b2c2dd083c557d39e0f8Andrew Morton		pr_debug("%s: No signature yet, waiting another %lu jiffies.\n",
72475be4d85a274d0961593db41cf85689db1d583cJoe Perches			 sc_adapter[card]->devicename, CHECKRESET_TIME);
73475be4d85a274d0961593db41cf85689db1d583cJoe Perches		mod_timer(&sc_adapter[card]->reset_timer, jiffies + CHECKRESET_TIME);
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Timed function to check the status of a previous reset
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be very fast as this function runs in the context of
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * an interrupt handler.
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send check sc_adapter->phystat to see if the channels are up
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If they are, tell ISDN4Linux that the board is up. If not,
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tell IADN4Linux that it is up. Always reset the timer to
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fire again (endless loop).
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid check_phystat(unsigned long data)
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int card = (unsigned int) data;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pr_debug("%s: Checking status...\n", sc_adapter[card]->devicename);
94475be4d85a274d0961593db41cf85689db1d583cJoe Perches	/*
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * check the results of the last PhyStat and change only if
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * has changed drastically
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sc_adapter[card]->nphystat && !sc_adapter[card]->phystat) {   /* All is well */
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pr_debug("PhyStat transition to RUN\n");
100475be4d85a274d0961593db41cf85689db1d583cJoe Perches		pr_info("%s: Switch contacted, transmitter enabled\n",
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sc_adapter[card]->devicename);
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		indicate_status(card, ISDN_STAT_RUN, 0, NULL);
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (!sc_adapter[card]->nphystat && sc_adapter[card]->phystat) {   /* All is not well */
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pr_debug("PhyStat transition to STOP\n");
106475be4d85a274d0961593db41cf85689db1d583cJoe Perches		pr_info("%s: Switch connection lost, transmitter disabled\n",
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sc_adapter[card]->devicename);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		indicate_status(card, ISDN_STAT_STOP, 0, NULL);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sc_adapter[card]->phystat = sc_adapter[card]->nphystat;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Reinitialize the timer */
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&sc_adapter[card]->lock, flags);
116475be4d85a274d0961593db41cf85689db1d583cJoe Perches	mod_timer(&sc_adapter[card]->stat_timer, jiffies + CHECKSTAT_TIME);
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Send a new cePhyStatus message */
120475be4d85a274d0961593db41cf85689db1d583cJoe Perches	sendmessage(card, CEPID, ceReqTypePhy, ceReqClass2,
121475be4d85a274d0961593db41cf85689db1d583cJoe Perches		    ceReqPhyStatus, 0, 0, NULL);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
123