Hi Norm,
I would suggest an alternate approach using a method I
learned from "Stupid Pointer Tricks 101". You can address
absolutely located hardware as structures using this method
as long as the address space is linear. I'm assuming you are
talking about RTLinux modules running in kernel space and
kernel space is linear.
Here is a snippet of code that employs this method. I hope it
gives you the general idea.
/*##########################################################################
#*\
* Hardware Structure Definitions
\*##########################################################################
#*/
/* system configuration pointer */
typedef struct
{
UINT16 xx1;
UINT8 xx2;
UINT8 sysbus;
UINT32 xx3;
UINT16 iscp_addr_lo;
UINT16 iscp_addr_hi;
}
SCP_TYPE;
/* intermediate system configuration pointer */
typedef struct
{
UINT8 xx1;
UINT8 busy;
UINT16 scb_offset;
UINT16 scb_addr_lo;
UINT16 scb_addr_hi;
}
ISCP_TYPE;
/* transmit command block .. can be used in simplified mode with data
* in the tcb or flexible mode using tbds */
typedef struct
{
UINT16 status;
UINT16 cmd;
UINT16 link_addr_lo;
UINT16 link_addr_hi;
UINT16 tbd_addr_lo; /* set to all 1s for simplified mode */
UINT16 tbd_addr_hi;
UINT16 eof_tcb_bcnt; /* always set eof in simplified mode */
UINT16 xx1;
UINT8 dst_ena[6];
UINT16 type_fld; /* 24 bytes to this point */
union
{
UINT8 byte[1500];
UINT16 hword[750];
UINT32 lword[375];
}
tx_data;
unsigned long time_tag;
unsigned long xmit_no;
unsigned long free_addr;
unsigned long unused_pad[3];
}
TCB_TYPE; /* 1552 (610h) bytes each */
/*##########################################################################
#*\
* Hardware Address Definitions
\*##########################################################################
#*/
/* 0xA0000000 and up is non-cached view of memory - MIPS processors */
#define ETH_BASE 0xA00C8000
/* define all Ethernet structures based on ETH_BASE base address */
#define SCB_ADDR (ETH_BASE)
#define GEN_CB_ADDR (ETH_BASE + sizeof(SCB_TYPE))
/* 128 tcbs @ 1552 bytes each => 0x30800 bytes */
#define TCB_ADDR (GEN_CB_ADDR + sizeof(CB_TYPE))
/* TCB to be used in Ethernet interrupt handler */
#define INT_TCB_ADDR (TCB_ADDR + (sizeof(TCB_TYPE) * NO_OF_TCBS))
.
.
.
/* force 16 byte alignment on SCP */
#define SCP_ADDR ((CMDTASK_TCB_ADDR + \
((sizeof(UDPIP_HDR_TYPE)*NO_OF_TCBS) + 15)) & \
0xFFFFFFF0)
#define ISCP_ADDR (SCP_ADDR+sizeof(SCP_TYPE))
/*##########################################################################
#*\
* "Fake" Structure Definitions (stupid pointer tricks)
\*##########################################################################
#*/
/* "fake" structs for absolute location -- ONLY works for linear addressing
*/
#define scp (*((SCP_TYPE*)(SCP_ADDR)))
#define iscp (*((ISCP_TYPE*)(ISCP_ADDR)))
/* for arrays use this syntax */
#define tcb ((TCB_TYPE*)(TCB_ADDR))
#define tbd_hdr ((TBD_TYPE*)(TBD_HEADER_ADDR))
/*##########################################################################
#*\
* Code Access Examples
\*##########################################################################
#*/
/* initialize the system configuration pointer (SCP) */
/* linear mode, int active low, lock disabled, internal tmr */
scp.sysbus = I82596_SCP_ASTEP_MODE |
I82596_SCP_INT_POL_LO |
I82596_SCP_LOCK_DSBL |
I82596_SCP_BTT_I_TRIG |
I82596_SCP_MODE_LINEAR;
scp.iscp_addr_lo = PHYS_LO(ISCP_ADDR);
scp.iscp_addr_hi = PHYS_HI(ISCP_ADDR);
scp.xx1 = 0;
scp.xx2 = 0;
scp.xx3 = 0;
/* initialize the intermediate system config pointer (ISCP) */
iscp.busy = 1; /* 596 will clear when info read */
iscp.xx1 = 0;
iscp.scb_offset = 0;
iscp.scb_addr_lo = PHYS_LO(SCB_ADDR);
iscp.scb_addr_hi = PHYS_HI(SCB_ADDR);
/* initialize transmit control block structures & header/data tbd structs
*/
for (i = 0; i < NO_OF_TCBS; i++)
{
/** TCB initialization **/
tcb[i].status = 0x8000; /* set complete bit to avoid 1st time
timeout*/
tcb[i].cmd = 0x8004; /* end of list, simplified mode */
tcb[i].link_addr_lo = PHYS_LO(&tcb[i]); /* link to self */
tcb[i].link_addr_hi = PHYS_HI(&tcb[i]);
tcb[i].tbd_addr_lo = 0xFFFF;/* all ones for simplified mode */
tcb[i].tbd_addr_hi = 0xFFFF;/* link to tbd_hdr for chaining */
tcb[i].eof_tcb_bcnt = 0x8000; /* this count includes dst_ena &
type_fld*/
tcb[i].xx1 = 0;
tcb[i].time_tag = 0xFFFFFFFF; /* implies invalid time tag */
tcb[i].xmit_no = 0;
tcb[i].free_addr = 0;
}
********** END OF CODE **********
I find the code using this method much more readable. Hope it helps.
Regards,
Rich
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Richard R. Jennings
Embedded Software Engineer 4 - The Boeing Company
Flight Simulation Technology / Advanced Avionics Center - St. Louis
Computational & Image Generation Group
(314)234-0460 FAX (314)232-7972
[EMAIL PROTECTED]
> ----------
> From: Norm Dresner[SMTP:[EMAIL PROTECTED]]
> Sent: Monday, July 10, 2000 9:10 AM
> To: [EMAIL PROTECTED]
> Subject: [rtl] possible insmod bug
>
> I'm having a problem because INSMOD is not loading one module correctly.
> Here's the system:
> RH 5.2 w/Real-Time Linux 0.9J extensions to the kernel
> gcc-2.7.2.3-14
> binutils (ld) 2.9.1.0.15-1
> modutils (insmod) 2.1.85-9
>
> An interface board I'm using has its 64K dual-ported segment located in
> PC-address space at 0x000D0000, so I'm trying to get the module compiled
> so
> that a particular `segment' falls at that address so I can use direct
> addressing of registers instead of having to dereference pointers for
> every
> access.
>
> Here's how the memory is declared in the C-function that uses it:
>
> unsigned char DualPortedMemory[2]
> __attribute__ ((section (".DPM" ) ) )
> ={0x68,0x89};
>
> and here's the loader command-file (invoked with -T load_cmds) on the
> ld-line of the make-file:
>
>
> MEMORY {
> DUALPORT (rw) : ORIGIN = 0x000D0000 , LENGTH = 64K
> }
>
>
> SECTIONS {
> .bss : { *(.bss) }
> .text : { *(.text) }
> .data : { *(.data) }
> .note : { *(.note) }
> .comment : { *(.comment) }
> .rodata : { *(.rodata) }
> .DPM 0x000D0000 (NOLOAD) : { *(.DPM) } >DUALPORT
> :NONE
> }
>
> The headers of the linked-moduel (as examined with objdump) show that the
> segment .DPM is located at the right address:
>
> dummy.o: file format elf32-i386
>
> Sections:
> Idx Name Size VMA LMA File off
> Algn
> . . .
> 6 .DPM 00000002 000d0000 000d0000 00001218 2**0
> ALLOC
>
> and the load-map from the insmod command has the following:
>
> Sections: Size Address Align
> .moduse 00000004 0807a000 2**2
> .text 0000088e 0807a004 2**2
> .rodata 00000358 0807a892 2**0
> .data 0000050c 0807abec 2**2
> .bss 0000009c 0807b0f8 2**2
> .DPM 00000002 0807b194 2**0
>
> showing that, despite everything I've tried, insmod insists on loading the
> module without properly relocating the .DPM-segment to 0x000D0000.
>
> I've tried just about every possible combination of things in the loader
> command-file, but that doesn't seem to be the problem since the disassemby
> of the loader's output shows that references to array DualPortedMemory[]
> are being correctly relocated to the .DPM segment located at the correct
> address.
>
> I've scanned the code for an older version of insmod (which is all I could
> find quickly) and it looks like it was never designed to do what I want it
> do .
>
> 1. Is there something obvious I'm missing?
> 2. Has anyone every done this successfully before?
> 3. Can anyone confirm this "bug"?
>
> I'd like to exhaust all possible approaches before I start creating dozens
> of pointers - an error-prone approach if the underlying structures change
> radically.
>
> Thanks.
>
> Norm
>
>
> -- [rtl] ---
> To unsubscribe:
> echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
> echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
> ---
> For more information on Real-Time Linux see:
> http://www.rtlinux.org/rtlinux/
>
-- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
---
For more information on Real-Time Linux see:
http://www.rtlinux.org/rtlinux/