etc/protocols - sync with NetBSD-8
[minix.git] / sys / arch / i386 / stand / lib / isapnp.c
blobcd3ba5f6d4fd7f3ad6862430d2f4598515277a80
1 /* $NetBSD: isapnp.c,v 1.5 2008/12/14 17:03:43 christos Exp $ */
3 /*
4 * Copyright (c) 1997
5 * Matthias Drochner. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * minimal ISA PnP implementation: find adapter, return settings (1 IO and 1
31 * DMA only for now)
34 #include <sys/types.h>
35 #include <machine/pio.h>
37 #include <lib/libsa/stand.h>
39 #include <libi386.h>
41 #include "isapnpvar.h"
43 #define PNPADDR 0x0279
44 #define PNPWDATA 0x0a79
45 #define PNPRDATAMIN 0x0203
46 #define PNPRDATAMAX 0x03ff
48 enum {
49 DATAPORT,
50 ISOL,
51 CONTROL,
52 WAKE,
53 RESDATA,
54 RESSTAT,
55 SETCSN,
56 SETLDEV
59 #define MEMBASE 0x40
60 #define IOBASE 0x60
61 #define INTBASE 0x70
62 #define DMABASE 0x74
64 static int pnpdataport;
66 static int
67 getiobase(int nr)
69 unsigned short iobase;
71 outb(PNPADDR, SETLDEV);
72 outb(PNPWDATA, 0); /* subdev 0 */
74 outb(PNPADDR, IOBASE + nr * 2);
75 iobase = (inb(pnpdataport) << 8);
76 outb(PNPADDR, IOBASE + nr * 2 + 1);
77 iobase |= inb(pnpdataport);
79 return iobase;
82 static int
83 getdmachan(int nr)
85 unsigned char dmachannel;
87 outb(PNPADDR, SETLDEV);
88 outb(PNPWDATA, 0); /* subdev 0 */
90 outb(PNPADDR, DMABASE + nr);
91 dmachannel = inb(pnpdataport) & 0x07;
93 return dmachannel;
96 struct cardid {
97 unsigned char eisaid[4];
98 unsigned int serial;
99 unsigned char crc;
103 do isolation, call pnpscanresc() in board config state
105 static int
106 pnpisol(int csn)
108 unsigned char buf[9];
109 int i, j;
110 struct cardid *id;
111 unsigned char crc = 0x6a;
114 * do 72 pairs of reads from ISOL register all but 1 go to sleep
115 * state (ch. 3.3)
117 outb(PNPADDR, ISOL);
118 delay(1000);
120 for (i = 0; i < 9; i++) {
121 for (j = 0; j < 8; j++) {
122 unsigned char a, b;
123 int bitset;
125 a = inb(pnpdataport);
126 b = inb(pnpdataport);
127 if ((a == 0x55) && (b == 0xaa))
128 bitset = 1;
129 else if ((a == 0xff) && (b == 0xff))
130 bitset = 0;
131 else
132 return -1; /* data port conflict */
134 buf[i] = (buf[i] >> 1) | (bitset << 7);
136 if (i < 8) /* calc crc for first 8 bytes (app.
137 * B.2) */
138 crc = (crc >> 1) |
139 ((bitset != ((crc & 1) == !(crc & 2))) << 7);
141 delay(250);
144 id = (struct cardid *) buf;
146 if (id->crc != crc)
147 return 0; /* normal end */
149 outb(PNPADDR, SETCSN);
150 outb(PNPWDATA, csn); /* set csn for winning card and put it to
151 * config state */
153 return (id->eisaid[0] << 24) | (id->eisaid[1] << 16)
154 | (id->eisaid[2] << 8) | (id->eisaid[3]);
157 static void
158 pnpisolreset(void)
160 outb(PNPADDR, WAKE);
161 outb(PNPWDATA, 0); /* put all remaining cards to isolation state */
165 send initiation sequence (app. B.1)
167 static void
168 pnpinit(void)
170 int i;
171 unsigned char key = 0x6a;
173 outb(PNPADDR, 0);
174 outb(PNPADDR, 0);
176 for (i = 0; i < 32; i++) {
177 outb(PNPADDR, key);
178 key = (key >> 1) |
179 (((key & 1) == !(key & 2)) << 7);
184 isapnp_finddev(int id, int *iobase, int *dmachan)
186 int csn;
188 outb(PNPADDR, CONTROL);
189 outb(PNPWDATA, 2); /* XXX force wait for key */
191 /* scan all allowed data ports (ch. 3.1) */
192 for (pnpdataport = PNPRDATAMIN; pnpdataport <= PNPRDATAMAX;
193 pnpdataport += 4) {
194 int res, found = 0;
196 pnpinit(); /* initiation sequence */
198 outb(PNPADDR, CONTROL);
199 outb(PNPWDATA, 4); /* CSN=0 - only these respond to
200 * WAKE[0] */
202 outb(PNPADDR, WAKE);
203 outb(PNPWDATA, 0); /* put into isolation state */
205 outb(PNPADDR, DATAPORT);
206 outb(PNPWDATA, pnpdataport >> 2); /* set READ_DATA port */
208 csn = 0;
209 do {
210 res = pnpisol(++csn);
212 if ((res) == id) {
213 if (iobase)
214 *iobase = getiobase(0);
215 if (dmachan)
216 *dmachan = getdmachan(0);
217 found = 1;
219 pnpisolreset();
220 } while ((res != 0) && (res != -1));
222 outb(PNPADDR, CONTROL);
223 outb(PNPWDATA, 2); /* return to wait for key */
225 if (csn > 1) /* at least 1 board found */
226 return !found;
228 /* if no board found, try next dataport */
230 return -1; /* nothing found */