FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/pcicx.c
1 /*-
2 * TODO:
3 * [1] integrate into current if_ed.c
4 * [2] parse tuples to find out where to map the shared memory buffer,
5 * and what to write into the configuration register
6 * [3] move pcic-specific code into a separate module.
7 *
8 * Device driver for IBM PCMCIA Credit Card Adapter for Ethernet,
9 * if_ze.c
10 *
11 * Based on the Device driver for National Semiconductor DS8390 ethernet
12 * adapters by David Greenman. Modifications for PCMCIA by Keith Moore.
13 * Adapted for FreeBSD 1.1.5 by Jordan Hubbard.
14 *
15 * Currently supports only the IBM Credit Card Adapter for Ethernet, but
16 * could probably work with other PCMCIA cards also, if it were modified
17 * to get the locations of the PCMCIA configuration option register (COR)
18 * by parsing the configuration tuples, rather than by hard-coding in
19 * the value expected by IBM's card.
20 *
21 * Sources for data on the PCMCIA/IBM CCAE specific portions of the driver:
22 *
23 * [1] _Local Area Network Credit Card Adapters Technical Reference_,
24 * IBM Corp., SC30-3585-00, part # 33G9243.
25 * [2] "pre-alpha" PCMCIA support code for Linux by Barry Jaspan.
26 * [3] Intel 82536SL PC Card Interface Controller Data Sheet, Intel
27 * Order Number 290423-002
28 * [4] National Semiconductor DP83902A ST-NIC (tm) Serial Network
29 * Interface Controller for Twisted Pair data sheet.
30 *
31 *
32 * Copyright (C) 1993, David Greenman. This software may be used, modified,
33 * copied, distributed, and sold, in both source and binary form provided
34 * that the above copyright and these terms are retained. Under no
35 * circumstances is the author responsible for the proper functioning
36 * of this software, nor does the author assume any responsibility
37 * for damages incurred with its use.
38 */
39 #include <sys/param.h>
40 #if defined(__FreeBSD__)
41 #include <sys/systm.h>
42 #include <machine/clock.h>
43 #endif
44 #include <i386/isa/isa_device.h>
45 #include <i386/isa/pcic.h>
46
47 /*
48 * map a portion of the card's memory space into system memory
49 * space.
50 *
51 * slot = # of the slot the card is plugged into
52 * window = which pcic memory map registers to use (0..4)
53 * sys_addr = base system PHYSICAL memory address where we want it. must
54 * be on an appropriate boundary (lower 12 bits are zero).
55 * card_addr = the base address of the card's memory to correspond
56 * to sys_addr
57 * length = length of the segment to map (may be rounded up as necessary)
58 * type = which card memory space to map (attribute or shared)
59 * width = 1 for byte-wide mapping; 2 for word (16-bit) mapping.
60 */
61
62 void
63 pcic_map_memory (int slot, int window, unsigned long sys_addr,
64 unsigned long card_addr, unsigned long length,
65 enum memtype type, int width)
66 {
67 unsigned short offset;
68 unsigned short mem_start_addr;
69 unsigned short mem_stop_addr;
70
71 sys_addr >>= 12;
72 card_addr >>= 12;
73 length >>= 12;
74 /*
75 * compute an offset for the chip such that
76 * (sys_addr + offset) = card_addr
77 * but the arithmetic is done modulo 2^14
78 */
79 offset = (card_addr - sys_addr) & 0x3FFF;
80 /*
81 * now OR in the bit for "attribute memory" if necessary
82 */
83 if (type == ATTRIBUTE) {
84 offset |= (PCIC_REG << 8);
85 /* REG == "region active" pin on card */
86 }
87 /*
88 * okay, set up the chip memory mapping registers, and turn
89 * on the enable bit for this window.
90 * if we are doing 16-bit wide accesses (width == 2),
91 * turn on the appropriate bit.
92 *
93 * XXX for now, we set all of the wait state bits to zero.
94 * Not really sure how they should be set.
95 */
96 mem_start_addr = sys_addr & 0xFFF;
97 if (width == 2)
98 mem_start_addr |= (PCIC_DATA16 << 8);
99 mem_stop_addr = (sys_addr + length) & 0xFFF;
100
101 pcic_putw (slot, MEM_START_ADDR(window), mem_start_addr);
102 pcic_putw (slot, MEM_STOP_ADDR(window), mem_stop_addr);
103 pcic_putw (slot, MEM_OFFSET(window), offset);
104 /*
105 * Assert the bit (PCIC_MEMCS16) that says to decode all of
106 * the address lines.
107 */
108 pcic_putb (slot, PCIC_ADDRWINE,
109 pcic_getb (slot, PCIC_ADDRWINE) |
110 MEM_ENABLE_BIT(window) | PCIC_MEMCS16);
111 }
112
113 void
114 pcic_unmap_memory (int slot, int window)
115 {
116 /*
117 * seems like we need to turn off the enable bit first, after which
118 * we can clear the registers out just to be sure.
119 */
120 pcic_putb (slot, PCIC_ADDRWINE,
121 pcic_getb (slot, PCIC_ADDRWINE) & ~MEM_ENABLE_BIT(window));
122 pcic_putw (slot, MEM_START_ADDR(window), 0);
123 pcic_putw (slot, MEM_STOP_ADDR(window), 0);
124 pcic_putw (slot, MEM_OFFSET(window), 0);
125 }
126
127 /*
128 * map a range of addresses into system i/o space
129 * (no translation of i/o addresses is possible)
130 *
131 * 'width' is:
132 * + 0 to tell the PCIC to generate the ISA IOCS16* signal from
133 * the PCMCIA IOIS16* signal.
134 * + 1 to select 8-bit width
135 * + 2 to select 16-bit width
136 */
137
138 void
139 pcic_map_io (int slot, int window, unsigned short base, unsigned short length,
140 unsigned short width)
141 {
142 unsigned char x;
143
144 pcic_putw (slot, IO_START_ADDR(window), base);
145 pcic_putw (slot, IO_STOP_ADDR(window), base+length-1);
146 /*
147 * select the bits that determine whether
148 * an i/o operation is 8 or 16 bits wide
149 */
150 x = pcic_getb (slot, PCIC_IOCTL);
151 switch (width) {
152 case 0: /* PCMCIA card decides */
153 if (window)
154 x = (x & 0xf0) | PCIC_IO1_CS16;
155 else
156 x = (x & 0x0f) | PCIC_IO0_CS16;
157 break;
158 case 1: /* 8 bits wide */
159 break;
160 case 2: /* 16 bits wide */
161 if (window)
162 x = (x & 0xf0) | PCIC_IO1_16BIT;
163 else
164 x = (x & 0x0f) | PCIC_IO0_16BIT;
165 break;
166 }
167 pcic_putb (slot, PCIC_IOCTL, x);
168 pcic_putb (slot, PCIC_ADDRWINE,
169 pcic_getb (slot, PCIC_ADDRWINE) | IO_ENABLE_BIT(window));
170 }
171
172 #ifdef TEST
173 void
174 pcic_unmap_io (int slot, int window)
175 {
176 pcic_putb (slot, PCIC_ADDRWINE,
177 pcic_getb (slot, PCIC_ADDRWINE) & ~IO_ENABLE_BIT(window));
178 pcic_putw (slot, IO_START_ADDR(window), 0);
179 pcic_putw (slot, IO_STOP_ADDR(window), 0);
180 }
181 #endif /* TEST */
182
183 /*
184 * tell the PCIC which irq we want to use. only the following are legal:
185 * 3, 4, 5, 7, 9, 10, 11, 12, 14, 15
186 *
187 * NB: 'irq' is an interrupt NUMBER, not a MASK as in struct isa_device.
188 */
189
190 void
191 pcic_map_irq (int slot, int irq)
192 {
193 if (irq < 3 || irq == 6 || irq == 8 || irq == 13 || irq > 15) {
194 printf ("zp: pcic_map_irq (slot %d): illegal irq %d\n", slot, irq);
195 return;
196 }
197 pcic_putb (slot, PCIC_INT_GEN,
198 pcic_getb (slot, PCIC_INT_GEN) | (irq & 0x0F));
199 }
200
201 void
202 pcic_power_on (int slot)
203 {
204 pcic_putb (slot, PCIC_STATUS,
205 pcic_getb (slot, PCIC_STATUS) | PCIC_POW);
206 DELAY (100000);
207 pcic_putb (slot, PCIC_POWER,
208 pcic_getb (slot, PCIC_POWER) | PCIC_DISRST | PCIC_PCPWRE);
209 DELAY (100000);
210 pcic_putb (slot, PCIC_POWER,
211 pcic_getb (slot, PCIC_POWER) | PCIC_OUTENA);
212 }
213
214 void
215 pcic_power_off (int slot)
216 {
217 pcic_putb (slot, PCIC_POWER,
218 pcic_getb (slot, PCIC_POWER) & ~(PCIC_OUTENA|PCIC_PCPWRE));
219 }
220
221 void
222 pcic_reset (int slot)
223 {
224 /* assert RESET (by clearing a bit!), wait a bit, and de-assert it */
225 pcic_putb (slot, PCIC_INT_GEN,
226 pcic_getb (slot, PCIC_INT_GEN) & ~PCIC_CARDRESET);
227 DELAY (100000);
228 pcic_putb (slot, PCIC_INT_GEN,
229 pcic_getb (slot, PCIC_INT_GEN) | PCIC_CARDRESET);
230 }
231
Cache object: b229820cfe61cf52127dfa5ad47a2da2
|