Factor out ADB spin-wait timeout loop, and use it for synchronous
operations to access the PRAM RTC, etc. in the IIsi and Cuda cases. Thanks to Martin Husemann for pointing out the flaw. This is a slightly more thorough workaround for the issue Martin found in PR 37611, as it affected more than just adb_read_date_time().
This commit is contained in:
parent
012e0e0132
commit
776597a46f
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: adb.c,v 1.51 2007/12/03 15:33:51 ad Exp $ */
|
||||
/* $NetBSD: adb.c,v 1.52 2008/04/03 05:03:23 scottr Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1994 Bradley A. Grantham
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: adb.c,v 1.51 2007/12/03 15:33:51 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: adb.c,v 1.52 2008/04/03 05:03:23 scottr Exp $");
|
||||
|
||||
#include "opt_adb.h"
|
||||
|
||||
|
@ -271,34 +271,13 @@ adbprint(void *args, const char *name)
|
|||
int
|
||||
adb_op_sync(Ptr buffer, Ptr compRout, Ptr data, short command)
|
||||
{
|
||||
int tmout;
|
||||
int result;
|
||||
volatile int flag = 0;
|
||||
|
||||
result = ADBOp(buffer, (void *)adb_op_comprout, __UNVOLATILE(&flag),
|
||||
command); /* send command */
|
||||
if (result == 0) { /* send ok? */
|
||||
/*
|
||||
* Total time to wait is calculated as follows:
|
||||
* - Tlt (stop to start time): 260 usec
|
||||
* - start bit: 100 usec
|
||||
* - up to 8 data bytes: 64 * 100 usec = 6400 usec
|
||||
* - stop bit (with SRQ): 140 usec
|
||||
* Total: 6900 usec
|
||||
*
|
||||
* This is the total time allowed by the specification. Any
|
||||
* device that doesn't conform to this will fail to operate
|
||||
* properly on some Apple systems. In spite of this we
|
||||
* double the time to wait; some Cuda-based apparently
|
||||
* queues some commands and allows the main CPU to continue
|
||||
* processing (radical concept, eh?). To be safe, allow
|
||||
* time for two complete ADB transactions to occur.
|
||||
*/
|
||||
for (tmout = 13800; !flag && tmout >= 10; tmout -= 10)
|
||||
delay(10);
|
||||
if (!flag && tmout > 0)
|
||||
delay(tmout);
|
||||
|
||||
adb_spin(&flag);
|
||||
if (!flag)
|
||||
result = -2;
|
||||
}
|
||||
|
@ -306,6 +285,37 @@ adb_op_sync(Ptr buffer, Ptr compRout, Ptr data, short command)
|
|||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* adb_spin
|
||||
*
|
||||
* Implements a spin-wait with timeout to be used for synchronous
|
||||
* operations on the ADB bus.
|
||||
*
|
||||
* Total time to wait is calculated as follows:
|
||||
* - Tlt (stop to start time): 260 usec
|
||||
* - start bit: 100 usec
|
||||
* - up to 8 data bytes: 64 * 100 usec = 6400 usec
|
||||
* - stop bit (with SRQ): 140 usec
|
||||
* Total: 6900 usec
|
||||
*
|
||||
* This is the total time allowed by the specification. Any device that
|
||||
* doesn't conform to this will fail to operate properly on some Apple
|
||||
* systems. In spite of this we double the time to wait; Cuda-based
|
||||
* systems apparently queue commands and allow the main CPU to continue
|
||||
* processing (how radical!). To be safe, allow time for two complete
|
||||
* ADB transactions to occur.
|
||||
*/
|
||||
void
|
||||
adb_spin(volatile int *fp)
|
||||
{
|
||||
int tmout;
|
||||
|
||||
for (tmout = 13800; *fp == 0 && tmout >= 10; tmout -= 10)
|
||||
delay(10);
|
||||
if (*fp == 0 && tmout > 0)
|
||||
delay(tmout);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* adb_op_comprout
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: adb_direct.c,v 1.61 2008/04/01 12:02:52 martin Exp $ */
|
||||
/* $NetBSD: adb_direct.c,v 1.62 2008/04/03 05:03:23 scottr Exp $ */
|
||||
|
||||
/* From: adb_direct.c 2.02 4/18/97 jpw */
|
||||
|
||||
|
@ -62,7 +62,7 @@
|
|||
#ifdef __NetBSD__
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: adb_direct.c,v 1.61 2008/04/01 12:02:52 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: adb_direct.c,v 1.62 2008/04/03 05:03:23 scottr Exp $");
|
||||
|
||||
#include "opt_adb.h"
|
||||
|
||||
|
@ -2737,15 +2737,9 @@ adb_read_date_time(unsigned long *curtime)
|
|||
if (result != 0) /* exit if not sent */
|
||||
return -1;
|
||||
|
||||
for (tmout = 13800; !flag && tmout >= 10; tmout -= 10)
|
||||
delay(10);
|
||||
if (!flag && tmout > 0)
|
||||
delay(tmout);
|
||||
|
||||
if (!flag) {
|
||||
printf("WARNING: ADB command did not complete\n");
|
||||
adb_spin(&flag); /* wait for result */
|
||||
if (flag == 0) /* exit it timeout */
|
||||
return -1;
|
||||
}
|
||||
|
||||
*curtime = (long)(*(long *)(output + 1));
|
||||
return 0;
|
||||
|
@ -2762,15 +2756,9 @@ adb_read_date_time(unsigned long *curtime)
|
|||
if (result != 0) /* exit if not sent */
|
||||
return -1;
|
||||
|
||||
for (tmout = 138000; !flag && tmout >= 10; tmout -= 10)
|
||||
delay(10);
|
||||
if (!flag && tmout > 0)
|
||||
delay(tmout);
|
||||
|
||||
if (!flag) {
|
||||
printf("WARNING: ADB command did not complete\n");
|
||||
adb_spin(&flag); /* wait for result */
|
||||
if (flag == 0) /* exit it timeout */
|
||||
return -1;
|
||||
}
|
||||
|
||||
*curtime = (long)(*(long *)(output + 1));
|
||||
return 0;
|
||||
|
@ -2810,8 +2798,9 @@ adb_set_date_time(unsigned long curtime)
|
|||
if (result != 0) /* exit if not sent */
|
||||
return -1;
|
||||
|
||||
while (0 == flag) /* wait for send to finish */
|
||||
;
|
||||
adb_spin(&flag); /* wait for result */
|
||||
if (flag == 0) /* exit it timeout */
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -2831,8 +2820,9 @@ adb_set_date_time(unsigned long curtime)
|
|||
if (result != 0) /* exit if not sent */
|
||||
return -1;
|
||||
|
||||
while (0 == flag) /* wait for send to finish */
|
||||
;
|
||||
adb_spin(&flag); /* wait for result */
|
||||
if (flag == 0) /* exit it timeout */
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -2910,8 +2900,9 @@ adb_prog_switch_enable(void)
|
|||
if (result != 0) /* exit if not sent */
|
||||
return -1;
|
||||
|
||||
while (0 == flag) /* wait for send to finish */
|
||||
;
|
||||
adb_spin(&flag); /* wait for result */
|
||||
if (flag == 0) /* exit it timeout */
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -2945,8 +2936,9 @@ adb_prog_switch_disable(void)
|
|||
if (result != 0) /* exit if not sent */
|
||||
return -1;
|
||||
|
||||
while (0 == flag) /* wait for send to finish */
|
||||
;
|
||||
adb_spin(&flag); /* wait for result */
|
||||
if (flag == 0) /* exit it timeout */
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: adbvar.h,v 1.24 2007/03/08 02:24:39 tsutsui Exp $ */
|
||||
/* $NetBSD: adbvar.h,v 1.25 2008/04/03 05:03:23 scottr Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1994 Bradley A. Grantham
|
||||
|
@ -66,6 +66,7 @@ extern int adb_debug;
|
|||
void adb_enqevent(adb_event_t *);
|
||||
|
||||
int adb_op_sync(Ptr, Ptr, Ptr, short);
|
||||
void adb_spin(volatile int *);
|
||||
void adb_op_comprout(void);
|
||||
|
||||
/* adbsysasm.s */
|
||||
|
|
Loading…
Reference in New Issue