1996-10-16 23:32:08 +04:00
|
|
|
What to Look for when Porting the IPKDB Interface
|
1996-10-08 20:39:55 +04:00
|
|
|
===============================================
|
|
|
|
|
|
|
|
Try to avoid calling any routine from the rest of the kernel.
|
|
|
|
(It's OK to call these routines during initialization).
|
|
|
|
You wouldn't be able to set breakpoints within these routines
|
|
|
|
during debugging, since this would hang the debugging interface.
|
|
|
|
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
Interface between IPKDB and Ethernet Board (sys/dev/yy/if_xx.c)
|
1996-10-08 20:39:55 +04:00
|
|
|
--------------------------------------------------------------
|
|
|
|
|
|
|
|
General Considerations
|
|
|
|
|
|
|
|
|
|
|
|
There is a problem when the debugger uses the same ethernet board as
|
|
|
|
does the rest of the kernel. For one thing there might arrive packets
|
|
|
|
destined for the kernel during debugging sessions. Since the debugger
|
|
|
|
receives all available packets for the time being it has to deliver
|
|
|
|
back to the driver those packets it has no use for. This implies that
|
|
|
|
the debugging driver must leave the interrupt pending conditions alone
|
|
|
|
so that the kernel driver gets the interrupt at the next time its
|
|
|
|
interrupt is enabled (whether this is when the debugger is left or
|
|
|
|
later with an spl*()). The same holds for the transmit interrupt
|
1996-10-16 23:32:08 +04:00
|
|
|
pending, at least when ipkdbinit determines that there is some packet
|
1996-10-08 20:39:55 +04:00
|
|
|
on its way out.
|
|
|
|
|
|
|
|
|
|
|
|
Configuration Files
|
|
|
|
|
|
|
|
|
|
|
|
The interface that is used for debugging has to have a unique
|
|
|
|
attribute with the option "disable", and must allow the attachment
|
1996-10-16 23:32:08 +04:00
|
|
|
of a ipkdbif. The relevant part of the "files" file for interface
|
1996-10-08 20:39:55 +04:00
|
|
|
"xx" would look like this:
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
define ipkdbxx { [ disable = 0 ] }
|
|
|
|
device xx: ether, ifnet, ipkdbxx
|
1996-10-08 20:39:55 +04:00
|
|
|
attach xx at yy
|
1996-10-16 23:32:08 +04:00
|
|
|
file dev/zz/if_xx.c xx | ipkdb_xx needs-flag
|
|
|
|
attach ipkdbif at ipkdbxx with ipkdb_xx
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
with proper values for yy and zz. The file dev/zz/if_xx.c contains
|
1996-10-16 23:32:08 +04:00
|
|
|
both the code of the kernel driver and the IPKDB driver for this
|
1996-10-08 20:39:55 +04:00
|
|
|
interface. You might want to #include "xx.h" in there and
|
1996-10-16 23:32:08 +04:00
|
|
|
conditionalize the compilation of the IPKDB driver with
|
|
|
|
#if NIPKDB_XX > 0.
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
The appropriate part of the machine configuration would read like
|
|
|
|
this:
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
xx* at yy
|
|
|
|
ipkdbif0 at xx?
|
1996-10-08 20:39:55 +04:00
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
Note that the unit for ipkdbif in the configuration file must be
|
1996-10-08 20:39:55 +04:00
|
|
|
given explicitly! It's used to distinguish the interface used
|
|
|
|
for debugging from the one you want to debug a new interface
|
|
|
|
driver for (see below).
|
|
|
|
|
|
|
|
Driver Code
|
|
|
|
|
|
|
|
|
|
|
|
The interface is "probed" by calling the parent probe routine with
|
|
|
|
a first argument of NULL. The last argument to the probe routine
|
1996-10-16 23:32:08 +04:00
|
|
|
is a struct ipkdb_if pointer that needs to be (partly) initialized by
|
1996-10-08 20:39:55 +04:00
|
|
|
the probe code. Fields to be set by the probe routine are:
|
|
|
|
|
|
|
|
myenetaddr fill this with the own ethernet address of
|
|
|
|
the device/machine.
|
1996-10-16 23:32:08 +04:00
|
|
|
flags mark at least IPKDB_MYHW here.
|
1996-10-08 20:39:55 +04:00
|
|
|
name Name of the device, only used for a message.
|
|
|
|
port Port number, only used for a message by
|
|
|
|
machine/device independent code.
|
1996-10-16 23:32:08 +04:00
|
|
|
start routine called everytime IPKDB is entered.
|
|
|
|
leave routine called everytime IPKDB is left.
|
1996-10-08 20:39:55 +04:00
|
|
|
receive routine called to receive a packet.
|
|
|
|
send routine called to send a packet.
|
|
|
|
|
|
|
|
Additional fields that may be set are:
|
|
|
|
|
|
|
|
myinetaddr fill this with the own internet address,
|
1996-10-16 23:32:08 +04:00
|
|
|
and mark IPKDB_MYIP in flags.
|
1996-10-08 20:39:55 +04:00
|
|
|
unit These remaining fields are solely for
|
|
|
|
speed use by the driver.
|
|
|
|
fill
|
|
|
|
drvflags
|
|
|
|
|
|
|
|
The routine should check for existance of the ethernet board.
|
|
|
|
This routine should also try to find the system driver for the
|
|
|
|
same board and note its unit and device structure for later use.
|
|
|
|
|
|
|
|
The routine should return 0 on success and -1 on failure.
|
|
|
|
|
|
|
|
The remainder of the routines are called via function pointers
|
1996-10-16 23:32:08 +04:00
|
|
|
in the ipkdb_if structure. The probe routine needs to fill in
|
1996-10-08 20:39:55 +04:00
|
|
|
these function pointers with proper values.
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
void start(struct ipkdb_if *kip)
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
This routine gets called every time the debugger is entered.
|
1996-10-16 23:32:08 +04:00
|
|
|
kip is a pointer to the ipkdb_if structure used for debugging.
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
It should initialize the hardware and software interface.
|
|
|
|
|
|
|
|
This routine should also note the current state of the ethernet board
|
|
|
|
(as far as it can) so a later call to leave can reinstantiate this
|
|
|
|
state.
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
void leave(struct ipkdb_if *kip)
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
This routine is called whenever the debugger is left. It should
|
|
|
|
restore the ethernet hardware to the state prior to the last call to
|
|
|
|
start.
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
int receive(struct ipkdb_if *kip, u_char *buf, int poll)
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
This routine should return an ethernet packet to the buffer pointed to
|
|
|
|
by buf and return its length. The packet should be complete with the
|
|
|
|
ethernet header, i.e. it starts with the recipient address, but does not
|
|
|
|
contain the ethernet checksum.
|
|
|
|
|
|
|
|
If poll is set, it should return immediately, if no packet is available.
|
|
|
|
Otherwise it should wait for the next packet.
|
|
|
|
|
|
|
|
This routine should return the number of bytes transferred to buf.
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
void send(struct ipkdb_if *kip, u_char *buf, int l)
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
This routine should send an ethernet packet out of the debugging
|
|
|
|
interface. The packet is already complete with the ethernet header,
|
|
|
|
but does not contain the ethernet checksum.
|
|
|
|
|
|
|
|
|
|
|
|
Debugging
|
|
|
|
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
If you have a working IPKDB, you can test new interface code for a
|
|
|
|
different interface by supplying "option IPKDBTEST" and attaching
|
|
|
|
a ipkdbif1 to the new interface in your configuration file. When
|
1996-10-08 20:39:55 +04:00
|
|
|
you boot the resulting kernel with the "-d" option, this will
|
1996-10-16 23:32:08 +04:00
|
|
|
initialize the new interface right after starting IPKDB on the
|
1996-10-08 20:39:55 +04:00
|
|
|
working one. Thereafter, the code will continue to send and
|
|
|
|
receive packets on the new interface until you set the variable
|
1996-10-16 23:32:08 +04:00
|
|
|
"ipkdb_test" to 0.
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
Note that during debugging interface code this way you are using
|
|
|
|
most of the code that comprises the debugger code itself. So you
|
|
|
|
have to be extremely careful with setting breakpoints and the like.
|
|
|
|
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
Interface between IPKDB and Machine (sys/arch/xxx/xxx/ipkdb_glue.c)
|
1996-10-08 20:39:55 +04:00
|
|
|
-----------------------------------------------------------------
|
|
|
|
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
void ipkdbcopy(s,d,n) void *s, *d; int n;
|
|
|
|
void ipkdbzero(d,n) void *d; int n;
|
|
|
|
void ipkdbcmp(s,d,n) char *s, *d; int n;
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
These routines are the same as bcopy, bzero and bcmp resp. They are
|
|
|
|
here with other names to allow setting breakpoints into the normal
|
|
|
|
routines during debugging. This implies that you shouldn't use
|
|
|
|
things like structure assignement in the code that gets used by
|
|
|
|
the debugger.
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
void ipkdbinit(void)
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
This routine gets called when the debugger should be entered for the
|
|
|
|
first time.
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
int ipkdb_poll(void)
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
This routine gets called after a panic to check for a keypress by the user.
|
|
|
|
If implemented it allows the user to press any key on the console to do
|
|
|
|
the automatic reboot after a panic. Otherwise the debugging interface
|
|
|
|
will wait forever for some remote debugger to attach in case of a panic.
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
int ipkdbcmds(void)
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
There should be call to this routine from somewhere in locore when the
|
|
|
|
trap mechanism determines that the debugger should be entered, i.e. on
|
|
|
|
a single step or breakpoint interrupt from kernel code. The trapping
|
|
|
|
mechanism should already have stored the registers into the global area
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbregs. The layout of this area must be the same as that expected
|
1996-10-08 20:39:55 +04:00
|
|
|
by GDB. The return value of this routine is 0, if the user wants to
|
|
|
|
continue, 1 if the user wants to do single stepping, and 2 if the user
|
|
|
|
has detached from debugging.
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
int ipkdbfbyte(u_char *p)
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
This routine should fetch a byte from address p. It must not enter any
|
|
|
|
trap handling code, but instead return -1 on inability to access the data.
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
void ipkdbsbyte(u_char *p,u_char c)
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
This routine should set the byte pointed to by p to the value given as c.
|
|
|
|
The routine must not enter any trap handling code. Furthermore it should
|
|
|
|
reset the modification bit in the relevant page table entry to the value
|
|
|
|
before the store.
|
|
|
|
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
sys/arch/xxx/include/ipkdb.h
|
1996-10-08 20:39:55 +04:00
|
|
|
|
|
|
|
|
|
|
|
Machine dependent definitions and protoypes should be in
|
1996-10-16 23:32:08 +04:00
|
|
|
sys/arch/xxx/include/ipkdb.h, i.e. in <machine/ipkdb.h>. This includes
|
|
|
|
the size of the array ipkdbregs, that holds the contents of the registers
|
|
|
|
of the debuggee at the time IPKDB is entered.
|