diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/char/rio/riotable.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/char/rio/riotable.c')
-rw-r--r-- | drivers/char/rio/riotable.c | 1044 |
1 files changed, 1044 insertions, 0 deletions
diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c new file mode 100644 index 000000000000..8fb26ad2aa12 --- /dev/null +++ b/drivers/char/rio/riotable.c | |||
@@ -0,0 +1,1044 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : riotable.c | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 10:33:47 | ||
26 | ** Retrieved : 11/6/98 10:33:50 | ||
27 | ** | ||
28 | ** ident @(#)riotable.c 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | #ifdef SCCS_LABELS | ||
33 | static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2"; | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/errno.h> | ||
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/string.h> | ||
41 | |||
42 | #include <asm/io.h> | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/string.h> | ||
45 | #include <asm/semaphore.h> | ||
46 | #include <asm/uaccess.h> | ||
47 | |||
48 | #include <linux/termios.h> | ||
49 | #include <linux/serial.h> | ||
50 | |||
51 | #include <linux/generic_serial.h> | ||
52 | |||
53 | |||
54 | #include "linux_compat.h" | ||
55 | #include "rio_linux.h" | ||
56 | #include "typdef.h" | ||
57 | #include "pkt.h" | ||
58 | #include "daemon.h" | ||
59 | #include "rio.h" | ||
60 | #include "riospace.h" | ||
61 | #include "top.h" | ||
62 | #include "cmdpkt.h" | ||
63 | #include "map.h" | ||
64 | #include "riotypes.h" | ||
65 | #include "rup.h" | ||
66 | #include "port.h" | ||
67 | #include "riodrvr.h" | ||
68 | #include "rioinfo.h" | ||
69 | #include "func.h" | ||
70 | #include "errors.h" | ||
71 | #include "pci.h" | ||
72 | |||
73 | #include "parmmap.h" | ||
74 | #include "unixrup.h" | ||
75 | #include "board.h" | ||
76 | #include "host.h" | ||
77 | #include "error.h" | ||
78 | #include "phb.h" | ||
79 | #include "link.h" | ||
80 | #include "cmdblk.h" | ||
81 | #include "route.h" | ||
82 | #include "control.h" | ||
83 | #include "cirrus.h" | ||
84 | #include "rioioctl.h" | ||
85 | #include "param.h" | ||
86 | #include "list.h" | ||
87 | #include "sam.h" | ||
88 | #include "protsts.h" | ||
89 | |||
90 | /* | ||
91 | ** A configuration table has been loaded. It is now up to us | ||
92 | ** to sort it out and use the information contained therein. | ||
93 | */ | ||
94 | int | ||
95 | RIONewTable(p) | ||
96 | struct rio_info * p; | ||
97 | { | ||
98 | int Host, Host1, Host2, NameIsUnique, Entry, SubEnt; | ||
99 | struct Map *MapP; | ||
100 | struct Map *HostMapP; | ||
101 | struct Host *HostP; | ||
102 | |||
103 | char *cptr; | ||
104 | |||
105 | /* | ||
106 | ** We have been sent a new table to install. We need to break | ||
107 | ** it down into little bits and spread it around a bit to see | ||
108 | ** what we have got. | ||
109 | */ | ||
110 | /* | ||
111 | ** Things to check: | ||
112 | ** (things marked 'xx' aren't checked any more!) | ||
113 | ** (1) That there are no booted Hosts/RTAs out there. | ||
114 | ** (2) That the names are properly formed | ||
115 | ** (3) That blank entries really are. | ||
116 | ** xx (4) That hosts mentioned in the table actually exist. xx | ||
117 | ** (5) That the IDs are unique (per host). | ||
118 | ** (6) That host IDs are zero | ||
119 | ** (7) That port numbers are valid | ||
120 | ** (8) That port numbers aren't duplicated | ||
121 | ** (9) That names aren't duplicated | ||
122 | ** xx (10) That hosts that actually exist are mentioned in the table. xx | ||
123 | */ | ||
124 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n"); | ||
125 | if ( p->RIOSystemUp ) { /* (1) */ | ||
126 | p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED; | ||
127 | return -EBUSY; | ||
128 | } | ||
129 | |||
130 | p->RIOError.Error = NOTHING_WRONG_AT_ALL; | ||
131 | p->RIOError.Entry = -1; | ||
132 | p->RIOError.Other = -1; | ||
133 | |||
134 | for ( Entry=0; Entry<TOTAL_MAP_ENTRIES; Entry++ ) { | ||
135 | MapP = &p->RIOConnectTable[Entry]; | ||
136 | if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) { | ||
137 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n"); | ||
138 | cptr = MapP->Name; /* (2) */ | ||
139 | cptr[MAX_NAME_LEN-1]='\0'; | ||
140 | if ( cptr[0]=='\0' ) { | ||
141 | bcopy(MapP->RtaUniqueNum?"RTA NN":"HOST NN",MapP->Name,8); | ||
142 | MapP->Name[5] = '0'+Entry/10; | ||
143 | MapP->Name[6] = '0'+Entry%10; | ||
144 | } | ||
145 | while ( *cptr ) { | ||
146 | if ( *cptr<' ' || *cptr>'~' ) { | ||
147 | p->RIOError.Error = BAD_CHARACTER_IN_NAME; | ||
148 | p->RIOError.Entry = Entry; | ||
149 | return -ENXIO; | ||
150 | } | ||
151 | cptr++; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | ** If the entry saved was a tentative entry then just forget | ||
157 | ** about it. | ||
158 | */ | ||
159 | if ( MapP->Flags & SLOT_TENTATIVE ) { | ||
160 | MapP->HostUniqueNum = 0; | ||
161 | MapP->RtaUniqueNum = 0; | ||
162 | continue; | ||
163 | } | ||
164 | |||
165 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n"); | ||
166 | if ( !MapP->RtaUniqueNum && !MapP->HostUniqueNum ) { /* (3) */ | ||
167 | if ( MapP->ID || MapP->SysPort || MapP->Flags ) { | ||
168 | rio_dprintk (RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n",MapP->Name); | ||
169 | p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL; | ||
170 | p->RIOError.Entry = Entry; | ||
171 | return -ENXIO; | ||
172 | } | ||
173 | rio_dprintk (RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n"); | ||
174 | continue; | ||
175 | } | ||
176 | |||
177 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n"); | ||
178 | for ( Host=0; Host<p->RIONumHosts; Host++ ) { /* (4) */ | ||
179 | if ( p->RIOHosts[Host].UniqueNum==MapP->HostUniqueNum ) { | ||
180 | HostP = &p->RIOHosts[Host]; | ||
181 | /* | ||
182 | ** having done the lookup, we don't really want to do | ||
183 | ** it again, so hang the host number in a safe place | ||
184 | */ | ||
185 | MapP->Topology[0].Unit = Host; | ||
186 | break; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | if ( Host >= p->RIONumHosts ) { | ||
191 | rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n", | ||
192 | MapP->Name, MapP->HostUniqueNum); | ||
193 | MapP->HostUniqueNum = 0; | ||
194 | /* MapP->RtaUniqueNum = 0; */ | ||
195 | /* MapP->ID = 0; */ | ||
196 | /* MapP->Flags = 0; */ | ||
197 | /* MapP->SysPort = 0; */ | ||
198 | /* MapP->Name[0] = 0; */ | ||
199 | continue; | ||
200 | } | ||
201 | |||
202 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n"); | ||
203 | if ( MapP->RtaUniqueNum ) { /* (5) */ | ||
204 | if ( !MapP->ID ) { | ||
205 | rio_dprintk (RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n", | ||
206 | MapP->Name); | ||
207 | p->RIOError.Error = ZERO_RTA_ID; | ||
208 | p->RIOError.Entry = Entry; | ||
209 | return -ENXIO; | ||
210 | } | ||
211 | if ( MapP->ID > MAX_RUP ) { | ||
212 | rio_dprintk (RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n", | ||
213 | MapP->Name, MapP->ID); | ||
214 | p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; | ||
215 | p->RIOError.Entry = Entry; | ||
216 | return -ENXIO; | ||
217 | } | ||
218 | for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) { | ||
219 | if ( MapP->HostUniqueNum == | ||
220 | p->RIOConnectTable[SubEnt].HostUniqueNum && | ||
221 | MapP->ID == p->RIOConnectTable[SubEnt].ID ) { | ||
222 | rio_dprintk (RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n", | ||
223 | MapP->Name, p->RIOConnectTable[SubEnt].Name); | ||
224 | p->RIOError.Error = DUPLICATED_RTA_ID; | ||
225 | p->RIOError.Entry = Entry; | ||
226 | p->RIOError.Other = SubEnt; | ||
227 | return -ENXIO; | ||
228 | } | ||
229 | /* | ||
230 | ** If the RtaUniqueNum is the same, it may be looking at both | ||
231 | ** entries for a 16 port RTA, so check the ids | ||
232 | */ | ||
233 | if ((MapP->RtaUniqueNum == | ||
234 | p->RIOConnectTable[SubEnt].RtaUniqueNum) | ||
235 | && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) { | ||
236 | rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n",MapP->Name); | ||
237 | rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", | ||
238 | p->RIOConnectTable[SubEnt].Name); | ||
239 | p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER; | ||
240 | p->RIOError.Entry = Entry; | ||
241 | p->RIOError.Other = SubEnt; | ||
242 | return -ENXIO; | ||
243 | } | ||
244 | } | ||
245 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n"); | ||
246 | /* (7a) */ | ||
247 | if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort % PORTS_PER_RTA)) { | ||
248 | rio_dprintk (RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n", | ||
249 | (int)MapP->SysPort,MapP->Name, PORTS_PER_RTA); | ||
250 | p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; | ||
251 | p->RIOError.Entry = Entry; | ||
252 | return -ENXIO; | ||
253 | } | ||
254 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n"); | ||
255 | /* (7b) */ | ||
256 | if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort >= RIO_PORTS)) { | ||
257 | rio_dprintk (RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n", | ||
258 | (int)MapP->SysPort, MapP->Name); | ||
259 | p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; | ||
260 | p->RIOError.Entry = Entry; | ||
261 | return -ENXIO; | ||
262 | } | ||
263 | for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) { | ||
264 | if ( p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT ) | ||
265 | continue; | ||
266 | if ( p->RIOConnectTable[SubEnt].RtaUniqueNum ) { | ||
267 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n"); | ||
268 | /* (8) */ | ||
269 | if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort == | ||
270 | p->RIOConnectTable[SubEnt].SysPort) ) { | ||
271 | rio_dprintk (RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", | ||
272 | MapP->Name, p->RIOConnectTable[SubEnt].Name, | ||
273 | (int)MapP->SysPort); | ||
274 | p->RIOError.Error = TTY_NUMBER_IN_USE; | ||
275 | p->RIOError.Entry = Entry; | ||
276 | p->RIOError.Other = SubEnt; | ||
277 | return -ENXIO; | ||
278 | } | ||
279 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n"); | ||
280 | if (strcmp(MapP->Name, | ||
281 | p->RIOConnectTable[SubEnt].Name)==0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */ | ||
282 | rio_dprintk (RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name); | ||
283 | p->RIOError.Error = NAME_USED_TWICE; | ||
284 | p->RIOError.Entry = Entry; | ||
285 | p->RIOError.Other = SubEnt; | ||
286 | return -ENXIO; | ||
287 | } | ||
288 | } | ||
289 | } | ||
290 | } | ||
291 | else { /* (6) */ | ||
292 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n"); | ||
293 | if ( MapP->ID ) { | ||
294 | rio_dprintk (RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n", | ||
295 | MapP->Name); | ||
296 | p->RIOError.Error = HOST_ID_NOT_ZERO; | ||
297 | p->RIOError.Entry = Entry; | ||
298 | return -ENXIO; | ||
299 | } | ||
300 | if ( MapP->SysPort != NO_PORT ) { | ||
301 | rio_dprintk (RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n", | ||
302 | MapP->Name); | ||
303 | p->RIOError.Error = HOST_SYSPORT_BAD; | ||
304 | p->RIOError.Entry = Entry; | ||
305 | return -ENXIO; | ||
306 | } | ||
307 | } | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | ** wow! if we get here then it's a goody! | ||
312 | */ | ||
313 | |||
314 | /* | ||
315 | ** Zero the (old) entries for each host... | ||
316 | */ | ||
317 | for ( Host=0; Host<RIO_HOSTS; Host++ ) { | ||
318 | for ( Entry=0; Entry<MAX_RUP; Entry++ ) { | ||
319 | bzero((caddr_t)&p->RIOHosts[Host].Mapping[Entry], | ||
320 | sizeof(struct Map)); | ||
321 | } | ||
322 | bzero((caddr_t)&p->RIOHosts[Host].Name[0], | ||
323 | sizeof(p->RIOHosts[Host].Name) ); | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | ** Copy in the new table entries | ||
328 | */ | ||
329 | for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) { | ||
330 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry); | ||
331 | MapP = &p->RIOConnectTable[Entry]; | ||
332 | |||
333 | /* | ||
334 | ** Now, if it is an empty slot ignore it! | ||
335 | */ | ||
336 | if ( MapP->HostUniqueNum==0 ) | ||
337 | continue; | ||
338 | |||
339 | /* | ||
340 | ** we saved the host number earlier, so grab it back | ||
341 | */ | ||
342 | HostP = &p->RIOHosts[MapP->Topology[0].Unit]; | ||
343 | |||
344 | /* | ||
345 | ** If it is a host, then we only need to fill in the name field. | ||
346 | */ | ||
347 | if ( MapP->ID==0 ) { | ||
348 | rio_dprintk (RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name); | ||
349 | bcopy(MapP->Name,HostP->Name,MAX_NAME_LEN); | ||
350 | continue; | ||
351 | } | ||
352 | |||
353 | /* | ||
354 | ** Its an RTA entry, so fill in the host mapping entries for it | ||
355 | ** and the port mapping entries. Notice that entry zero is for | ||
356 | ** ID one. | ||
357 | */ | ||
358 | HostMapP = &HostP->Mapping[MapP->ID-1]; | ||
359 | |||
360 | if (MapP->Flags & SLOT_IN_USE) { | ||
361 | rio_dprintk (RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name); | ||
362 | /* | ||
363 | ** structure assign, then sort out the bits we shouldn't have done | ||
364 | */ | ||
365 | *HostMapP = *MapP; | ||
366 | |||
367 | HostMapP->Flags = SLOT_IN_USE; | ||
368 | if (MapP->Flags & RTA16_SECOND_SLOT) | ||
369 | HostMapP->Flags |= RTA16_SECOND_SLOT; | ||
370 | |||
371 | RIOReMapPorts(p, HostP, HostMapP ); | ||
372 | } | ||
373 | else { | ||
374 | rio_dprintk (RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) { | ||
379 | p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry]; | ||
380 | } | ||
381 | |||
382 | for ( Host=0; Host<p->RIONumHosts; Host++ ) { | ||
383 | for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) { | ||
384 | p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT; | ||
385 | p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK; | ||
386 | } | ||
387 | for ( Entry=0; Entry<MAX_RUP; Entry++ ) { | ||
388 | for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) { | ||
389 | p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = | ||
390 | ROUTE_DISCONNECT; | ||
391 | p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = | ||
392 | NO_LINK; | ||
393 | } | ||
394 | } | ||
395 | if ( !p->RIOHosts[Host].Name[0] ) { | ||
396 | bcopy("HOST 1",p->RIOHosts[Host].Name,7); | ||
397 | p->RIOHosts[Host].Name[5] += Host; | ||
398 | } | ||
399 | /* | ||
400 | ** Check that default name assigned is unique. | ||
401 | */ | ||
402 | Host1 = Host; | ||
403 | NameIsUnique = 0; | ||
404 | while (!NameIsUnique) { | ||
405 | NameIsUnique = 1; | ||
406 | for ( Host2=0; Host2<p->RIONumHosts; Host2++ ) { | ||
407 | if (Host2 == Host) | ||
408 | continue; | ||
409 | if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name) | ||
410 | == 0) { | ||
411 | NameIsUnique = 0; | ||
412 | Host1++; | ||
413 | if (Host1 >= p->RIONumHosts) | ||
414 | Host1 = 0; | ||
415 | p->RIOHosts[Host].Name[5] = '1' + Host1; | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | /* | ||
420 | ** Rename host if name already used. | ||
421 | */ | ||
422 | if (Host1 != Host) | ||
423 | { | ||
424 | rio_dprintk (RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name); | ||
425 | bcopy("HOST 1",p->RIOHosts[Host].Name,7); | ||
426 | p->RIOHosts[Host].Name[5] += Host1; | ||
427 | } | ||
428 | rio_dprintk (RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name); | ||
429 | } | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | /* | ||
434 | ** User process needs the config table - build it from first | ||
435 | ** principles. | ||
436 | */ | ||
437 | int | ||
438 | RIOApel(p) | ||
439 | struct rio_info * p; | ||
440 | { | ||
441 | int Host; | ||
442 | int link; | ||
443 | int Rup; | ||
444 | int Next = 0; | ||
445 | struct Map *MapP; | ||
446 | struct Host *HostP; | ||
447 | long oldspl; | ||
448 | |||
449 | disable(oldspl); /* strange but true! */ | ||
450 | |||
451 | rio_dprintk (RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n"); | ||
452 | |||
453 | bzero((caddr_t)&p->RIOConnectTable[0], | ||
454 | sizeof(struct Map) * TOTAL_MAP_ENTRIES ); | ||
455 | |||
456 | for ( Host=0; Host<RIO_HOSTS; Host++ ) { | ||
457 | rio_dprintk (RIO_DEBUG_TABLE, "Processing host %d\n", Host); | ||
458 | HostP = &p->RIOHosts[Host]; | ||
459 | MapP = &p->RIOConnectTable[Next++]; | ||
460 | MapP->HostUniqueNum = HostP->UniqueNum; | ||
461 | if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) | ||
462 | continue; | ||
463 | MapP->RtaUniqueNum = 0; | ||
464 | MapP->ID = 0; | ||
465 | MapP->Flags = SLOT_IN_USE; | ||
466 | MapP->SysPort = NO_PORT; | ||
467 | for ( link=0; link<LINKS_PER_UNIT; link++ ) | ||
468 | MapP->Topology[link] = HostP->Topology[link]; | ||
469 | bcopy(HostP->Name,MapP->Name,MAX_NAME_LEN); | ||
470 | for ( Rup=0; Rup<MAX_RUP; Rup++ ) { | ||
471 | if ( HostP->Mapping[Rup].Flags & (SLOT_IN_USE|SLOT_TENTATIVE) ) { | ||
472 | p->RIOConnectTable[Next] = HostP->Mapping[Rup]; | ||
473 | if ( HostP->Mapping[Rup].Flags & SLOT_IN_USE) | ||
474 | p->RIOConnectTable[Next].Flags |= SLOT_IN_USE; | ||
475 | if ( HostP->Mapping[Rup].Flags & SLOT_TENTATIVE) | ||
476 | p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE; | ||
477 | if ( HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT ) | ||
478 | p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT; | ||
479 | Next++; | ||
480 | } | ||
481 | } | ||
482 | } | ||
483 | restore(oldspl); | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | /* | ||
488 | ** config.rio has taken a dislike to one of the gross maps entries. | ||
489 | ** if the entry is suitably inactive, then we can gob on it and remove | ||
490 | ** it from the table. | ||
491 | */ | ||
492 | int | ||
493 | RIODeleteRta(p, MapP) | ||
494 | struct rio_info *p; | ||
495 | struct Map *MapP; | ||
496 | { | ||
497 | int host, entry, port, link; | ||
498 | int SysPort; | ||
499 | struct Host *HostP; | ||
500 | struct Map *HostMapP; | ||
501 | struct Port *PortP; | ||
502 | int work_done = 0; | ||
503 | unsigned long lock_flags, sem_flags; | ||
504 | |||
505 | rio_dprintk (RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", | ||
506 | MapP->HostUniqueNum, MapP->RtaUniqueNum); | ||
507 | |||
508 | for ( host=0; host < p->RIONumHosts; host++ ) { | ||
509 | HostP = &p->RIOHosts[host]; | ||
510 | |||
511 | rio_spin_lock_irqsave( &HostP->HostLock, lock_flags ); | ||
512 | |||
513 | if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) { | ||
514 | rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags); | ||
515 | continue; | ||
516 | } | ||
517 | |||
518 | for ( entry=0; entry<MAX_RUP; entry++ ) { | ||
519 | if ( MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum ) { | ||
520 | HostMapP = &HostP->Mapping[entry]; | ||
521 | rio_dprintk (RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", | ||
522 | entry, HostP->Name); | ||
523 | |||
524 | /* | ||
525 | ** Check all four links of the unit are disconnected | ||
526 | */ | ||
527 | for ( link=0; link< LINKS_PER_UNIT; link++ ) { | ||
528 | if ( HostMapP->Topology[link].Unit != ROUTE_DISCONNECT ) { | ||
529 | rio_dprintk (RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n"); | ||
530 | p->RIOError.Error = UNIT_IS_IN_USE; | ||
531 | rio_spin_unlock_irqrestore( &HostP->HostLock, lock_flags); | ||
532 | return -EBUSY; | ||
533 | } | ||
534 | } | ||
535 | /* | ||
536 | ** Slot has been allocated, BUT not booted/routed/ | ||
537 | ** connected/selected or anything else-ed | ||
538 | */ | ||
539 | SysPort = HostMapP->SysPort; | ||
540 | |||
541 | if ( SysPort != NO_PORT ) { | ||
542 | for (port=SysPort; port < SysPort+PORTS_PER_RTA; port++) { | ||
543 | PortP = p->RIOPortp[port]; | ||
544 | rio_dprintk (RIO_DEBUG_TABLE, "Unmap port\n"); | ||
545 | |||
546 | rio_spin_lock_irqsave( &PortP->portSem, sem_flags ); | ||
547 | |||
548 | PortP->Mapped = 0; | ||
549 | |||
550 | if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) { | ||
551 | |||
552 | rio_dprintk (RIO_DEBUG_TABLE, "Gob on port\n"); | ||
553 | PortP->TxBufferIn = PortP->TxBufferOut = 0; | ||
554 | /* What should I do | ||
555 | wakeup( &PortP->TxBufferIn ); | ||
556 | wakeup( &PortP->TxBufferOut); | ||
557 | */ | ||
558 | PortP->InUse = NOT_INUSE; | ||
559 | /* What should I do | ||
560 | wakeup( &PortP->InUse ); | ||
561 | signal(PortP->TtyP->t_pgrp,SIGKILL); | ||
562 | ttyflush(PortP->TtyP,(FREAD|FWRITE)); | ||
563 | */ | ||
564 | PortP->State |= RIO_CLOSING | RIO_DELETED; | ||
565 | } | ||
566 | |||
567 | /* | ||
568 | ** For the second slot of a 16 port RTA, the | ||
569 | ** driver needs to reset the changes made to | ||
570 | ** the phb to port mappings in RIORouteRup. | ||
571 | */ | ||
572 | if (PortP->SecondBlock) { | ||
573 | ushort dest_unit = HostMapP->ID; | ||
574 | ushort dest_port = port - SysPort; | ||
575 | WORD *TxPktP; | ||
576 | PKT *Pkt; | ||
577 | |||
578 | for (TxPktP = PortP->TxStart; | ||
579 | TxPktP <= PortP->TxEnd; TxPktP++) { | ||
580 | /* | ||
581 | ** *TxPktP is the pointer to the | ||
582 | ** transmit packet on the host card. | ||
583 | ** This needs to be translated into | ||
584 | ** a 32 bit pointer so it can be | ||
585 | ** accessed from the driver. | ||
586 | */ | ||
587 | Pkt = (PKT *) RIO_PTR(HostP->Caddr, | ||
588 | RWORD(*TxPktP)); | ||
589 | rio_dprintk (RIO_DEBUG_TABLE, | ||
590 | "Tx packet (%x) destination: Old %x:%x New %x:%x\n", | ||
591 | *TxPktP, Pkt->dest_unit, | ||
592 | Pkt->dest_port, dest_unit, dest_port); | ||
593 | WWORD(Pkt->dest_unit, dest_unit); | ||
594 | WWORD(Pkt->dest_port, dest_port); | ||
595 | } | ||
596 | rio_dprintk (RIO_DEBUG_TABLE, | ||
597 | "Port %d phb destination: Old %x:%x New %x:%x\n", | ||
598 | port, PortP->PhbP->destination & 0xff, | ||
599 | (PortP->PhbP->destination >> 8) & 0xff, | ||
600 | dest_unit, dest_port); | ||
601 | WWORD(PortP->PhbP->destination, | ||
602 | dest_unit + (dest_port << 8)); | ||
603 | } | ||
604 | rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags); | ||
605 | } | ||
606 | } | ||
607 | rio_dprintk (RIO_DEBUG_TABLE, "Entry nulled.\n"); | ||
608 | bzero((char *)HostMapP,sizeof(struct Map)); | ||
609 | work_done++; | ||
610 | } | ||
611 | } | ||
612 | rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags); | ||
613 | } | ||
614 | |||
615 | /* XXXXX lock me up */ | ||
616 | for ( entry=0; entry< TOTAL_MAP_ENTRIES; entry++ ) { | ||
617 | if ( p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) { | ||
618 | bzero((char *)&p->RIOSavedTable[entry],sizeof(struct Map)); | ||
619 | work_done++; | ||
620 | } | ||
621 | if ( p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) { | ||
622 | bzero((char *)&p->RIOConnectTable[entry],sizeof(struct Map)); | ||
623 | work_done++; | ||
624 | } | ||
625 | } | ||
626 | if ( work_done ) | ||
627 | return 0; | ||
628 | |||
629 | rio_dprintk (RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n"); | ||
630 | p->RIOError.Error = COULDNT_FIND_ENTRY; | ||
631 | return -ENXIO; | ||
632 | } | ||
633 | |||
634 | int RIOAssignRta( struct rio_info *p, struct Map *MapP ) | ||
635 | { | ||
636 | int host; | ||
637 | struct Map *HostMapP; | ||
638 | char *sptr; | ||
639 | int link; | ||
640 | |||
641 | |||
642 | rio_dprintk (RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", | ||
643 | MapP->HostUniqueNum,MapP->RtaUniqueNum, | ||
644 | MapP->ID, (int)MapP->SysPort); | ||
645 | |||
646 | if ((MapP->ID != (ushort)-1) && | ||
647 | ((int)MapP->ID < (int)1 || (int)MapP->ID > MAX_RUP )) | ||
648 | { | ||
649 | rio_dprintk (RIO_DEBUG_TABLE, "Bad ID in map entry!\n"); | ||
650 | p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; | ||
651 | return -EINVAL; | ||
652 | } | ||
653 | if (MapP->RtaUniqueNum == 0) | ||
654 | { | ||
655 | rio_dprintk (RIO_DEBUG_TABLE, "Rta Unique number zero!\n"); | ||
656 | p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO; | ||
657 | return -EINVAL; | ||
658 | } | ||
659 | if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA) ) | ||
660 | { | ||
661 | rio_dprintk (RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n",(int)MapP->SysPort,PORTS_PER_RTA); | ||
662 | p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; | ||
663 | return -EINVAL; | ||
664 | } | ||
665 | if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS) ) | ||
666 | { | ||
667 | rio_dprintk (RIO_DEBUG_TABLE, "Port %d not valid!\n",(int)MapP->SysPort); | ||
668 | p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; | ||
669 | return -EINVAL; | ||
670 | } | ||
671 | |||
672 | /* | ||
673 | ** Copy the name across to the map entry. | ||
674 | */ | ||
675 | MapP->Name[MAX_NAME_LEN-1] = '\0'; | ||
676 | sptr = MapP->Name; | ||
677 | while ( *sptr ) | ||
678 | { | ||
679 | if ( *sptr<' ' || *sptr>'~' ) | ||
680 | { | ||
681 | rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n"); | ||
682 | p->RIOError.Error = BAD_CHARACTER_IN_NAME; | ||
683 | return -EINVAL; | ||
684 | } | ||
685 | sptr++; | ||
686 | } | ||
687 | |||
688 | for ( host=0; host < p->RIONumHosts; host++ ) | ||
689 | { | ||
690 | if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum ) | ||
691 | { | ||
692 | if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING ) | ||
693 | { | ||
694 | p->RIOError.Error = HOST_NOT_RUNNING; | ||
695 | return -ENXIO; | ||
696 | } | ||
697 | |||
698 | /* | ||
699 | ** Now we have a host we need to allocate an ID | ||
700 | ** if the entry does not already have one. | ||
701 | */ | ||
702 | if (MapP->ID == (ushort)-1) | ||
703 | { | ||
704 | int nNewID; | ||
705 | |||
706 | rio_dprintk (RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", | ||
707 | MapP->Name); | ||
708 | /* | ||
709 | ** The idea here is to allow RTA's to be assigned | ||
710 | ** before they actually appear on the network. | ||
711 | ** This allows the addition of RTA's without having | ||
712 | ** to plug them in. | ||
713 | ** What we do is: | ||
714 | ** - Find a free ID and allocate it to the RTA. | ||
715 | ** - If this map entry is the second half of a | ||
716 | ** 16 port entry then find the other half and | ||
717 | ** make sure the 2 cross reference each other. | ||
718 | */ | ||
719 | if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) | ||
720 | { | ||
721 | p->RIOError.Error = COULDNT_FIND_ENTRY; | ||
722 | return -EBUSY; | ||
723 | } | ||
724 | MapP->ID = (ushort)nNewID + 1; | ||
725 | rio_dprintk (RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID); | ||
726 | HostMapP = &p->RIOHosts[host].Mapping[nNewID]; | ||
727 | HostMapP->RtaUniqueNum = MapP->RtaUniqueNum; | ||
728 | HostMapP->HostUniqueNum = MapP->HostUniqueNum; | ||
729 | HostMapP->ID = MapP->ID; | ||
730 | for (link = 0; link < LINKS_PER_UNIT; link++) | ||
731 | { | ||
732 | HostMapP->Topology[link].Unit = ROUTE_DISCONNECT; | ||
733 | HostMapP->Topology[link].Link = NO_LINK; | ||
734 | } | ||
735 | if (MapP->Flags & RTA16_SECOND_SLOT) | ||
736 | { | ||
737 | int unit; | ||
738 | |||
739 | for (unit = 0; unit < MAX_RUP; unit++) | ||
740 | if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == | ||
741 | MapP->RtaUniqueNum) | ||
742 | break; | ||
743 | if (unit == MAX_RUP) | ||
744 | { | ||
745 | p->RIOError.Error = COULDNT_FIND_ENTRY; | ||
746 | return -EBUSY; | ||
747 | } | ||
748 | HostMapP->Flags |= RTA16_SECOND_SLOT; | ||
749 | HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID; | ||
750 | p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID; | ||
751 | rio_dprintk (RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", | ||
752 | MapP->ID, | ||
753 | p->RIOHosts[host].Mapping[unit].ID); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1]; | ||
758 | |||
759 | if ( HostMapP->Flags & SLOT_IN_USE ) | ||
760 | { | ||
761 | rio_dprintk (RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID); | ||
762 | p->RIOError.Error = ID_ALREADY_IN_USE; | ||
763 | return -EBUSY; | ||
764 | } | ||
765 | |||
766 | /* | ||
767 | ** Assign the sys ports and the name, and mark the slot as | ||
768 | ** being in use. | ||
769 | */ | ||
770 | HostMapP->SysPort = MapP->SysPort; | ||
771 | if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) | ||
772 | CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN ); | ||
773 | HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED; | ||
774 | #if NEED_TO_FIX | ||
775 | RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID-1]); | ||
776 | #endif | ||
777 | if (MapP->Flags & RTA16_SECOND_SLOT) | ||
778 | HostMapP->Flags |= RTA16_SECOND_SLOT; | ||
779 | |||
780 | RIOReMapPorts( p, &p->RIOHosts[host], HostMapP ); | ||
781 | /* | ||
782 | ** Adjust 2nd block of 8 phbs | ||
783 | */ | ||
784 | if (MapP->Flags & RTA16_SECOND_SLOT) | ||
785 | RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1); | ||
786 | |||
787 | if ( HostMapP->SysPort != NO_PORT ) | ||
788 | { | ||
789 | if ( HostMapP->SysPort < p->RIOFirstPortsBooted ) | ||
790 | p->RIOFirstPortsBooted = HostMapP->SysPort; | ||
791 | if ( HostMapP->SysPort > p->RIOLastPortsBooted ) | ||
792 | p->RIOLastPortsBooted = HostMapP->SysPort; | ||
793 | } | ||
794 | if (MapP->Flags & RTA16_SECOND_SLOT) | ||
795 | rio_dprintk (RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", | ||
796 | p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name); | ||
797 | else | ||
798 | rio_dprintk (RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name); | ||
799 | return 0; | ||
800 | } | ||
801 | } | ||
802 | p->RIOError.Error = UNKNOWN_HOST_NUMBER; | ||
803 | rio_dprintk (RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum); | ||
804 | return -ENXIO; | ||
805 | } | ||
806 | |||
807 | |||
808 | int | ||
809 | RIOReMapPorts(p, HostP, HostMapP) | ||
810 | struct rio_info * p; | ||
811 | struct Host *HostP; | ||
812 | struct Map *HostMapP; | ||
813 | { | ||
814 | register struct Port *PortP; | ||
815 | uint SubEnt; | ||
816 | uint HostPort; | ||
817 | uint SysPort; | ||
818 | ushort RtaType; | ||
819 | unsigned long flags; | ||
820 | |||
821 | #ifdef CHECK | ||
822 | CheckHostP( HostP ); | ||
823 | CheckHostMapP( HostMapP ); | ||
824 | #endif | ||
825 | |||
826 | rio_dprintk (RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int)HostMapP->SysPort, HostMapP->ID); | ||
827 | |||
828 | /* | ||
829 | ** We need to tell the UnixRups which sysport the rup corresponds to | ||
830 | */ | ||
831 | HostP->UnixRups[HostMapP->ID-1].BaseSysPort = HostMapP->SysPort; | ||
832 | |||
833 | if ( HostMapP->SysPort == NO_PORT ) | ||
834 | return(0); | ||
835 | |||
836 | RtaType = GetUnitType(HostMapP->RtaUniqueNum); | ||
837 | rio_dprintk (RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", | ||
838 | (int)HostMapP->SysPort, (int)HostMapP->SysPort+PORTS_PER_RTA-1); | ||
839 | |||
840 | /* | ||
841 | ** now map each of its eight ports | ||
842 | */ | ||
843 | for ( SubEnt=0; SubEnt<PORTS_PER_RTA; SubEnt++) { | ||
844 | rio_dprintk (RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", | ||
845 | SubEnt, (int)HostMapP->SysPort); | ||
846 | SysPort = HostMapP->SysPort+SubEnt; /* portnumber within system */ | ||
847 | /* portnumber on host */ | ||
848 | |||
849 | HostPort = (HostMapP->ID-1)*PORTS_PER_RTA+SubEnt; | ||
850 | |||
851 | rio_dprintk (RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp); | ||
852 | PortP = p->RIOPortp[SysPort]; | ||
853 | #if 0 | ||
854 | PortP->TtyP = &p->channel[SysPort]; | ||
855 | #endif | ||
856 | rio_dprintk (RIO_DEBUG_TABLE, "Map port\n"); | ||
857 | |||
858 | /* | ||
859 | ** Point at all the real neat data structures | ||
860 | */ | ||
861 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
862 | PortP->HostP = HostP; | ||
863 | PortP->Caddr = HostP->Caddr; | ||
864 | |||
865 | /* | ||
866 | ** The PhbP cannot be filled in yet | ||
867 | ** unless the host has been booted | ||
868 | */ | ||
869 | if ((HostP->Flags & RUN_STATE) == RC_RUNNING) { | ||
870 | struct PHB *PhbP = PortP->PhbP = &HostP->PhbP[HostPort]; | ||
871 | PortP->TxAdd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_add)); | ||
872 | PortP->TxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_start)); | ||
873 | PortP->TxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_end)); | ||
874 | PortP->RxRemove=(WORD *)RIO_PTR(HostP->Caddr, | ||
875 | RWORD(PhbP->rx_remove)); | ||
876 | PortP->RxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_start)); | ||
877 | PortP->RxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_end)); | ||
878 | } | ||
879 | else | ||
880 | PortP->PhbP = NULL; | ||
881 | |||
882 | /* | ||
883 | ** port related flags | ||
884 | */ | ||
885 | PortP->HostPort = HostPort; | ||
886 | /* | ||
887 | ** For each part of a 16 port RTA, RupNum is ID - 1. | ||
888 | */ | ||
889 | PortP->RupNum = HostMapP->ID - 1; | ||
890 | if (HostMapP->Flags & RTA16_SECOND_SLOT) { | ||
891 | PortP->ID2 = HostMapP->ID2 - 1; | ||
892 | PortP->SecondBlock = TRUE; | ||
893 | } | ||
894 | else { | ||
895 | PortP->ID2 = 0; | ||
896 | PortP->SecondBlock = FALSE; | ||
897 | } | ||
898 | PortP->RtaUniqueNum = HostMapP->RtaUniqueNum; | ||
899 | |||
900 | /* | ||
901 | ** If the port was already mapped then thats all we need to do. | ||
902 | */ | ||
903 | if (PortP->Mapped) { | ||
904 | rio_spin_unlock_irqrestore( &PortP->portSem, flags); | ||
905 | continue; | ||
906 | } | ||
907 | else HostMapP->Flags &= ~RTA_NEWBOOT; | ||
908 | |||
909 | PortP->State = 0; | ||
910 | PortP->Config = 0; | ||
911 | /* | ||
912 | ** Check out the module type - if it is special (read only etc.) | ||
913 | ** then we need to set flags in the PortP->Config. | ||
914 | ** Note: For 16 port RTA, all ports are of the same type. | ||
915 | */ | ||
916 | if (RtaType == TYPE_RTA16) { | ||
917 | PortP->Config |= p->RIOModuleTypes[HostP->UnixRups | ||
918 | [HostMapP->ID-1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE]; | ||
919 | } else { | ||
920 | if ( SubEnt < PORTS_PER_MODULE ) | ||
921 | PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups | ||
922 | [HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE]; | ||
923 | else | ||
924 | PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups | ||
925 | [HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE]; | ||
926 | } | ||
927 | |||
928 | /* | ||
929 | ** more port related flags | ||
930 | */ | ||
931 | PortP->PortState = 0; | ||
932 | PortP->ModemLines = 0; | ||
933 | PortP->ModemState = 0; | ||
934 | PortP->CookMode = COOK_WELL; | ||
935 | PortP->ParamSem = 0; | ||
936 | PortP->FlushCmdBodge= 0; | ||
937 | PortP->WflushFlag = 0; | ||
938 | PortP->MagicFlags = 0; | ||
939 | PortP->Lock = 0; | ||
940 | PortP->Store = 0; | ||
941 | PortP->FirstOpen = 1; | ||
942 | |||
943 | /* | ||
944 | ** Buffers 'n things | ||
945 | */ | ||
946 | PortP->RxDataStart = 0; | ||
947 | PortP->Cor2Copy = 0; | ||
948 | PortP->Name = &HostMapP->Name[0]; | ||
949 | #ifdef STATS | ||
950 | bzero( (caddr_t)&PortP->Stat, sizeof(struct RIOStats) ); | ||
951 | #endif | ||
952 | PortP->statsGather = 0; | ||
953 | PortP->txchars = 0; | ||
954 | PortP->rxchars = 0; | ||
955 | PortP->opens = 0; | ||
956 | PortP->closes = 0; | ||
957 | PortP->ioctls = 0; | ||
958 | if ( PortP->TxRingBuffer ) | ||
959 | bzero( PortP->TxRingBuffer, p->RIOBufferSize ); | ||
960 | else if ( p->RIOBufferSize ) { | ||
961 | PortP->TxRingBuffer = sysbrk(p->RIOBufferSize); | ||
962 | bzero( PortP->TxRingBuffer, p->RIOBufferSize ); | ||
963 | } | ||
964 | PortP->TxBufferOut = 0; | ||
965 | PortP->TxBufferIn = 0; | ||
966 | PortP->Debug = 0; | ||
967 | /* | ||
968 | ** LastRxTgl stores the state of the rx toggle bit for this | ||
969 | ** port, to be compared with the state of the next pkt received. | ||
970 | ** If the same, we have received the same rx pkt from the RTA | ||
971 | ** twice. Initialise to a value not equal to PHB_RX_TGL or 0. | ||
972 | */ | ||
973 | PortP->LastRxTgl = ~(uchar)PHB_RX_TGL; | ||
974 | |||
975 | /* | ||
976 | ** and mark the port as usable | ||
977 | */ | ||
978 | PortP->Mapped = 1; | ||
979 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
980 | } | ||
981 | if ( HostMapP->SysPort < p->RIOFirstPortsMapped ) | ||
982 | p->RIOFirstPortsMapped = HostMapP->SysPort; | ||
983 | if ( HostMapP->SysPort > p->RIOLastPortsMapped ) | ||
984 | p->RIOLastPortsMapped = HostMapP->SysPort; | ||
985 | |||
986 | return 0; | ||
987 | } | ||
988 | |||
989 | int | ||
990 | RIOChangeName(p, MapP) | ||
991 | struct rio_info *p; | ||
992 | struct Map* MapP; | ||
993 | { | ||
994 | int host; | ||
995 | struct Map *HostMapP; | ||
996 | char *sptr; | ||
997 | |||
998 | rio_dprintk (RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", | ||
999 | MapP->HostUniqueNum,MapP->RtaUniqueNum, | ||
1000 | MapP->ID, (int)MapP->SysPort); | ||
1001 | |||
1002 | if ( MapP->ID > MAX_RUP ) { | ||
1003 | rio_dprintk (RIO_DEBUG_TABLE, "Bad ID in map entry!\n"); | ||
1004 | p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; | ||
1005 | return -EINVAL; | ||
1006 | } | ||
1007 | |||
1008 | MapP->Name[MAX_NAME_LEN-1] = '\0'; | ||
1009 | sptr = MapP->Name; | ||
1010 | |||
1011 | while ( *sptr ) { | ||
1012 | if ( *sptr<' ' || *sptr>'~' ) { | ||
1013 | rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n"); | ||
1014 | p->RIOError.Error = BAD_CHARACTER_IN_NAME; | ||
1015 | return -EINVAL; | ||
1016 | } | ||
1017 | sptr++; | ||
1018 | } | ||
1019 | |||
1020 | for ( host=0; host < p->RIONumHosts; host++ ) { | ||
1021 | if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum ) { | ||
1022 | if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING ) { | ||
1023 | p->RIOError.Error = HOST_NOT_RUNNING; | ||
1024 | return -ENXIO; | ||
1025 | } | ||
1026 | if ( MapP->ID==0 ) { | ||
1027 | CCOPY( MapP->Name, p->RIOHosts[host].Name, MAX_NAME_LEN ); | ||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1]; | ||
1032 | |||
1033 | if ( HostMapP->RtaUniqueNum != MapP->RtaUniqueNum ) { | ||
1034 | p->RIOError.Error = RTA_NUMBER_WRONG; | ||
1035 | return -ENXIO; | ||
1036 | } | ||
1037 | CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN ); | ||
1038 | return 0; | ||
1039 | } | ||
1040 | } | ||
1041 | p->RIOError.Error = UNKNOWN_HOST_NUMBER; | ||
1042 | rio_dprintk (RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum); | ||
1043 | return -ENXIO; | ||
1044 | } | ||