aboutsummaryrefslogtreecommitdiff
path: root/sys/i386/isa/pcic.h
blob: 6b99d72b680d4f59e6a414473559d7db70405a23 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*-
 * TODO:
 * [1] integrate into current if_ed.c
 * [2] parse tuples to find out where to map the shared memory buffer,
 *     and what to write into the configuration register
 * [3] move pcic-specific code into a separate module.
 *
 * Device driver for IBM PCMCIA Credit Card Adapter for Ethernet,
 * if_ze.c
 *
 * Based on the Device driver for National Semiconductor DS8390 ethernet
 * adapters by David Greenman.  Modifications for PCMCIA by Keith Moore.
 * Adapted for FreeBSD 1.1.5 by Jordan Hubbard.
 *
 * Currently supports only the IBM Credit Card Adapter for Ethernet, but
 * could probably work with other PCMCIA cards also, if it were modified
 * to get the locations of the PCMCIA configuration option register (COR)
 * by parsing the configuration tuples, rather than by hard-coding in
 * the value expected by IBM's card.
 *
 * Sources for data on the PCMCIA/IBM CCAE specific portions of the driver:
 *
 * [1] _Local Area Network Credit Card Adapters Technical Reference_,
 *     IBM Corp., SC30-3585-00, part # 33G9243.
 * [2] "pre-alpha" PCMCIA support code for Linux by Barry Jaspan.
 * [3] Intel 82536SL PC Card Interface Controller Data Sheet, Intel
 *     Order Number 290423-002
 * [4] National Semiconductor DP83902A ST-NIC (tm) Serial Network
 *     Interface Controller for Twisted Pair data sheet.
 *
 *
 * Copyright (C) 1993, David Greenman. This software may be used, modified,
 *   copied, distributed, and sold, in both source and binary form provided
 *   that the above copyright and these terms are retained. Under no
 *   circumstances is the author responsible for the proper functioning
 *   of this software, nor does the author assume any responsibility
 *   for damages incurred with its use.
 */

#ifndef __PCIC_H__
#define __PCIC_H__

/*****************************************************************************
 *                 pcmcia controller chip (PCIC) support                     *
 *               (eventually, move this to a separate file)                  *
 *****************************************************************************/
#include "ic/i82365.h"

/*
 * Each PCIC chip (82365SL or clone) can handle two card slots, and there
 * can be up to four PCICs in a system.  (On some machines, not all of the
 * address lines are decoded, so a card may appear to be in more than one
 * slot.)
 */
#define MAXSLOT 8

/*
 * To access a register on the PCIC for a particular slot, you
 * first write the correct OFFSET value for that slot in the
 * INDEX register for the PCIC controller.  You then read or write
 * the value from or to the DATA register for that controller.
 *
 * The first pair of chips shares I/O addresss for DATA and INDEX,
 * as does the second pair.   (To the programmer, it looks like each
 * pair is a single chip.)  The i/o port addresses are hard-wired
 * into the PCIC; so the following addresses should be valid for
 * any machine that uses this chip.
 */

#define PCIC_INDEX_0	0x3E0	/* index reg, chips 0 and 1 */
#define PCIC_DATA_0	0x3E1	/* data register, chips 0 and 1 */
#define PCIC_INDEX_1	0x3E2	/* index reg, chips 1 and 2 */
#define PCIC_DATA_1	0x3E3	/* data register, chips 1 and 2 */

/*
 * Given a slot number, calculate the INDEX and DATA registers
 * to talk to that slot.  OFFSET is added to the register number
 * to address the registers for a particular slot.
 */
#define INDEX(slot) ((slot) < 4 ? PCIC_INDEX_0 : PCIC_INDEX_1)
#define DATA(slot) ((slot) < 4 ? PCIC_DATA_0 : PCIC_DATA_1)
#define OFFSET(slot) ((slot) % 4 * 0x40)

/*
 * There are 5 sets (windows) of memory mapping registers on the PCIC chip
 * for each slot, numbered 0..4.
 *
 * They start at 10/50 hex within the chip's register space (not system
 * I/O space), and are eight addresses apart.  These are actually pairs of
 * 8-bit-wide registers (low byte first, then high byte) since the
 * address fields are actually 12 bits long.  The upper bits are used
 * for other things like 8/16-bit select and wait states.
 *
 * Memory mapping registers include start/stop addresses to define the
 * region to be mapped (in terms of system memory addresses), and
 * an offset register to allow for translation from system space
 * to card space.  The lower 12 bits aren't included in these, so memory is
 * mapped in 4K chunks.
 */
#define MEM_START_ADDR(window) (((window) * 0x08) + 0x10)
#define MEM_STOP_ADDR(window) (((window) * 0x08) + 0x12)
#define MEM_OFFSET(window) (((window) * 0x08) + 0x14)
/*
 * this bit gets set in the address window enable register (PCIC_ADDRWINE)
 * to enable a particular address window.
 */
#define MEM_ENABLE_BIT(window) ((1) << (window))

/*
 * There are two i/o port addressing windows.  I/O ports cannot be
 * relocated within system i/o space (unless the card doesn't decode
 * all of the address bits); unlike card memory, there is no address
 * translation offset.
 */
#define IO_START_ADDR(window) ((window) ? PCIC_IO1_STL : PCIC_IO0_STL)
#define IO_STOP_ADDR(window) ((window) ? PCIC_IO1_SPL : PCIC_IO0_SPL)
#define IO_ENABLE_BIT(window) ((window) ? PCIC_IO1_EN : PCIC_IO0_EN)
#define IO_CS16_BIT(window) ((window) ? PCIC_IO1_CS16 : PCIC_IO0_CS16)

/*
 * types of mapped memory
 */
enum memtype { COMMON, ATTRIBUTE };

/*
 * read a byte from a pcic register for a particular slot
 */
static inline unsigned char
pcic_getb (int slot, int reg)
{
    outb (INDEX(slot), OFFSET (slot) + reg);
    return inb (DATA (slot));
}

/*
 * write a byte to a pcic register for a particular slot
 */
static inline void
pcic_putb (int slot, int reg, unsigned char val)
{
    outb (INDEX(slot), OFFSET (slot) + reg);
    outb (DATA (slot), val);
}

/*
 * read a word from a pcic register for a particular slot
 */
static inline unsigned short
pcic_getw (int slot, int reg)
{
    return pcic_getb (slot, reg) | (pcic_getb (slot, reg+1) << 8);
}

/*
 * write a word to a pcic register at a particular slot
 */
static inline void
pcic_putw (int slot, int reg, unsigned short val)
{
    pcic_putb (slot, reg, val & 0xff);
    pcic_putb (slot, reg + 1, (val >> 8) & 0xff);
}


void pcic_print_regs (int slot);
void pcic_map_memory (int slot, int window, unsigned long sys_addr,
                      unsigned long card_addr, unsigned long length,
                      enum memtype type, int width);
void pcic_unmap_memory (int slot, int window);
void pcic_map_io (int slot, int window, unsigned short base,
                  unsigned short length, unsigned short width);
#ifdef TEST
void pcic_unmap_io (int slot, int window);
#endif /* TEST */
void pcic_map_irq (int slot, int irq);
void pcic_power_on (int slot);
void pcic_power_off (int slot);
void pcic_reset (int slot);


#endif /* __PCIC_H__ */