kernel: Sync ACPICA with Intel's version 20140424.
[dragonfly.git] / sys / dev / atm / hfa / fore_load.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/dev/hfa/fore_load.c,v 1.13 1999/09/25 18:23:49 phk Exp $
27  *      @(#) $DragonFly: src/sys/dev/atm/hfa/fore_load.c,v 1.14 2008/03/01 22:03:13 swildner Exp $
28  */
29
30 /*
31  * FORE Systems 200-Series Adapter Support
32  * ---------------------------------------
33  *
34  * Loadable kernel module and device identification support
35  *
36  */
37
38 #include "fore_include.h"
39
40 /*
41  * Local functions
42  */
43 static int      fore_start (void);
44 static const char *     fore_pci_probe (pcici_t, pcidi_t);
45 static void     fore_pci_attach (pcici_t, int);
46 static void     fore_pci_shutdown (void *, int);
47 static void     fore_unattach (Fore_unit *);
48 static void     fore_reset (Fore_unit *);
49
50
51 /*
52  * Local variables
53  */
54 static int      fore_inited = 0;
55
56 /*
57  * Driver entry points
58  */
59 static  u_long  fore_pci_count = 0;
60
61 static struct pci_device fore_pci_device = {
62         FORE_DEV_NAME,
63         fore_pci_probe,
64         fore_pci_attach,
65         &fore_pci_count,
66         NULL
67 };
68
69 COMPAT_PCI_DRIVER(fore_pci, fore_pci_device);
70
71 /*
72  * Initialize driver processing
73  * 
74  * This will be called during module loading.  Not much to do here, as
75  * we must wait for our identify/attach routines to get called before
76  * we know what we're in for.
77  *
78  * Arguments:
79  *      none
80  *
81  * Returns:
82  *      0       startup was successful 
83  *      errno   startup failed - reason indicated
84  *
85  */
86 static int
87 fore_start(void)
88 {
89
90         /*
91          * Verify software version
92          */
93         if (atm_version != ATM_VERSION) {
94                 log(LOG_ERR, "version mismatch: fore=%d.%d kernel=%d.%d\n",
95                         ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),
96                         ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));
97                 return (EINVAL);
98         }
99
100         /*
101          * Initialize DMA mapping
102          */
103         DMA_INIT();
104
105         /*
106          * Start up watchdog timer
107          */
108         atm_timeout(&fore_timer, ATM_HZ * FORE_TIME_TICK, fore_timeout);
109
110         fore_inited = 1;
111
112         return (0);
113 }
114
115 /*
116  * Device probe routine
117  * 
118  * Determine if this driver will support the identified device.  If we claim
119  * to support the device, our attach routine will (later) be called for the
120  * device.
121  *
122  * Arguments:
123  *      config_id       device's PCI configuration ID
124  *      device_id       device's PCI Vendor/Device ID
125  *
126  * Returns:
127  *      name    device identification string
128  *      NULL    device not claimed by this driver
129  *
130  */
131 static const char *
132 fore_pci_probe(pcici_t config_id, pcidi_t device_id)
133 {
134
135         /*
136          * Initialize driver stuff
137          */
138         if (fore_inited == 0) {
139                 if (fore_start())
140                         return (NULL);
141         }
142
143         if ((device_id & 0xffff) != FORE_VENDOR_ID)
144                 return (NULL);
145
146         if (((device_id >> 16) & 0xffff) == FORE_PCA200E_ID)
147                 return ("FORE Systems PCA-200E ATM");
148
149         return (NULL);
150 }
151
152
153 /*
154  * Device attach routine
155  * 
156  * Attach a device we've previously claimed to support.  Walk through its
157  * register set and map, as required.  Determine what level the device will
158  * be interrupting at and then register an interrupt handler for it.  If we
159  * succeed, then reset the adapter and initialize the microcode.
160  * Last, register the interface with the kernel ATM services.
161  *
162  * Arguments:
163  *      config_id       device's PCI configuration ID
164  *      unit            device unit number
165  *
166  * Returns:
167  *      none
168  *
169  */
170 static void
171 fore_pci_attach(pcici_t config_id, int unit)
172 {
173         Fore_unit       *fup;
174         vm_offset_t     va;
175         vm_offset_t     pa;
176         pcidi_t         device_id;
177         long            val;
178         int             err_count = BOOT_LOOPS;
179
180         /*
181          * Just checking...
182          */
183         if (unit >= FORE_MAX_UNITS) {
184                 log(LOG_ERR, "%s%d: too many devices\n", 
185                         FORE_DEV_NAME, unit);
186                 return;
187         }
188
189         /*
190          * Make sure this isn't a duplicate unit
191          */
192         if (fore_units[unit] != NULL)
193                 return;
194
195         /*
196          * Allocate a new unit structure
197          */
198         fup = (Fore_unit *) atm_dev_alloc(sizeof(Fore_unit), sizeof(int), 0);
199         if (fup == NULL)
200                 return;
201
202         /*
203          * Start initializing it
204          */
205         fup->fu_unit = unit;
206         fup->fu_mtu = FORE_IFF_MTU;
207         fup->fu_pcitag = config_id;
208         fup->fu_vcc_pool = &fore_vcc_pool;
209         fup->fu_nif_pool = &fore_nif_pool;
210         fup->fu_ioctl = fore_atm_ioctl;
211         fup->fu_instvcc = fore_instvcc;
212         fup->fu_openvcc = fore_openvcc;
213         fup->fu_closevcc = fore_closevcc;
214         fup->fu_output = fore_output;
215         callout_init(&fup->fu_init_timer);
216
217         /*
218          * Get our device type
219          */
220         device_id = pci_conf_read ( config_id, PCI_ID_REG );
221         switch ((device_id >> 16) & 0xffff) {
222
223         case FORE_PCA200E_ID:
224                 fup->fu_config.ac_device = DEV_FORE_PCA200E;
225                 break;
226
227         default:
228                 fup->fu_config.ac_device = DEV_UNKNOWN;
229         }
230
231         /*
232          * Enable Memory Mapping / Bus Mastering 
233          */
234         val = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
235         val |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
236         pci_conf_write(config_id, PCI_COMMAND_STATUS_REG, val);
237
238         /*
239          * Map RAM
240          */
241         val = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
242         if ((val & PCIM_CMD_MEMEN) == 0) {
243                 log(LOG_ERR, "%s%d: memory mapping not enabled\n", 
244                         FORE_DEV_NAME, unit);
245                 goto failed;
246         }
247         if ((pci_map_mem(config_id, PCA200E_PCI_MEMBASE, &va, &pa)) == 0) {
248                 log(LOG_ERR, "%s%d: unable to map memory\n", 
249                         FORE_DEV_NAME, unit);
250                 goto failed;
251         }
252         fup->fu_ram = (Fore_mem *)va;
253         fup->fu_ramsize = PCA200E_RAM_SIZE;
254         fup->fu_mon = (Mon960 *)(fup->fu_ram + MON960_BASE);
255         fup->fu_ctlreg = (Fore_reg *)(va + PCA200E_HCR_OFFSET);
256         fup->fu_imask = (Fore_reg *)(va + PCA200E_IMASK_OFFSET);
257         fup->fu_psr = (Fore_reg *)(va + PCA200E_PSR_OFFSET);
258
259         /*
260          * Convert Endianess of Slave RAM accesses
261          */
262         val = pci_conf_read(config_id, PCA200E_PCI_MCTL);
263         val |= PCA200E_MCTL_SWAP;
264         pci_conf_write(config_id, PCA200E_PCI_MCTL, val);
265
266         /*
267          * Map interrupt in
268          */
269         if ( !pci_map_int( config_id, fore_intr, fup) ) {
270                 log(LOG_ERR, "%s%d: unable to map interrupt\n", 
271                         FORE_DEV_NAME, unit);
272                 goto failed;
273         }
274
275         /*
276          * Poke the hardware - boot the CP and prepare it for downloading
277          */
278         fore_reset(fup);
279
280         /*
281          * Wait for the monitor to perform self-test
282          */
283         while (CP_READ(fup->fu_mon->mon_bstat) != BOOT_MONREADY) {
284                 if (CP_READ(fup->fu_mon->mon_bstat) == BOOT_FAILTEST) {
285                         log(LOG_ERR, "%s%d: failed self-test\n", 
286                                 FORE_DEV_NAME, unit);
287                         goto failed;
288                 } else if ( --err_count == 0 ) {
289                         log(LOG_ERR, "%s%d: unable to boot - status=0x%lx\n", 
290                                 FORE_DEV_NAME, unit,
291                                 (u_long)CP_READ(fup->fu_mon->mon_bstat));
292                         goto failed;
293                 }
294                 DELAY ( BOOT_DELAY );
295         }
296
297         /*
298          * Setup the adapter config info - at least as much as we can
299          */
300         fup->fu_config.ac_vendor = VENDOR_FORE;
301         fup->fu_config.ac_vendapi = VENDAPI_FORE_1;
302         fup->fu_config.ac_media = MEDIA_OC3C;
303         fup->fu_pif.pif_pcr = ATM_PCR_OC3C;
304         fup->fu_config.ac_bustype = BUS_PCI;
305         fup->fu_config.ac_busslot = config_id->bus << 8 | config_id->slot;
306
307         /*
308          * Save device ram info for user-level programs
309          */
310         fup->fu_config.ac_ram = (long)fup->fu_ram;
311         fup->fu_config.ac_ramsize = fup->fu_ramsize;
312
313         /*
314          * Set device capabilities
315          */
316         fup->fu_pif.pif_maxvpi = FORE_MAX_VPI;
317         fup->fu_pif.pif_maxvci = FORE_MAX_VCI;
318
319         /*
320          * Register this interface with ATM core services
321          */
322         if ( atm_physif_register
323                         ((Cmn_unit *)fup, FORE_DEV_NAME, fore_services) != 0 )
324         {
325                 /*
326                  * Registration failed - back everything out
327                  */
328                 goto failed;
329         }
330
331         fore_units[unit] = fup;
332         fore_nunits++;
333
334         /*
335          * Add hook to our shutdown function
336          */
337         EVENTHANDLER_REGISTER(shutdown_post_sync, fore_pci_shutdown, fup,
338                               SHUTDOWN_PRI_DRIVER);
339
340         /*
341          * Initialize the CP microcode program.
342          */
343         fore_initialize(fup);
344
345         return;
346
347 failed:
348         /*
349          * Unattach the device from the system
350          */
351         fore_unattach(fup);
352
353         /*
354          * Free any Fore-specific device resources
355          */
356         fore_interface_free(fup);
357
358         atm_dev_free(fup);
359
360         return;
361 }
362
363 /*
364  * Device shutdown routine
365  * 
366  * Arguments:
367  *      howto           type of shutdown
368  *      fup             pointer to device unit structure
369  *
370  * Returns:
371  *      none
372  *
373  */
374 static void
375 fore_pci_shutdown(void *fup, int howto)
376 {
377
378         fore_reset((Fore_unit *) fup);
379
380         return;
381 }
382
383 /*
384  * Device unattach routine
385  * 
386  * Reset the physical device, remove any pending timeouts, 
387  * unmap any register sets, and unregister any interrupts.
388  *
389  * Arguments:
390  *      fup             pointer to device unit structure
391  *
392  * Returns:
393  *      none
394  */ 
395 static void
396 fore_unattach(Fore_unit *fup)
397 {
398         /*
399          * Reset the board and return it to cold_start state.
400          * Hopefully, this will prevent use of resources as
401          * we're trying to free things up.
402          */
403         fore_reset(fup);
404
405         /*
406          * Lock out all device interrupts
407          */
408         DEVICE_LOCK((Cmn_unit *)fup);
409
410         /*
411          * Remove any pending timeout()'s
412          */
413         callout_stop(&fup->fu_init_timer);
414
415         /*
416          * Unmap the device interrupt
417          */
418         (void) pci_unmap_int(fup->fu_pcitag);
419
420         /*
421          * Unmap memory
422          */
423 #ifdef notdef
424         (void) pci_unmap_mem(fup->fu_pcitag, PCA200E_PCI_MEMBASE);
425 #endif
426
427         DEVICE_UNLOCK((Cmn_unit *)fup);
428 }
429
430
431 /*
432  * Device reset routine
433  * 
434  * Reset the physical device
435  *
436  * Arguments:
437  *      fup             pointer to device unit structure
438  *
439  * Returns:
440  *      none
441  */ 
442 static void
443 fore_reset(Fore_unit *fup)
444 {
445         /*
446          * Reset the board and return it to cold_start state
447          */
448         crit_enter();
449         if (fup->fu_mon)
450                 fup->fu_mon->mon_bstat = CP_WRITE(BOOT_COLDSTART);
451
452         if (fup->fu_ctlreg) {
453
454                 switch (fup->fu_config.ac_device) {
455
456                 case DEV_FORE_PCA200E:
457                         /*
458                          * Reset i960 by setting and clearing RESET
459                          */
460                         PCA200E_HCR_INIT(*fup->fu_ctlreg, PCA200E_RESET);
461                         DELAY(10000);
462                         PCA200E_HCR_CLR(*fup->fu_ctlreg, PCA200E_RESET);
463                         break;
464
465                 default:
466                         panic("fore_reset: unknown device type");
467                         break;
468                 }
469         }
470         crit_exit();
471         return;
472 }
473
474
475 #ifndef ATM_LINKED
476 /*
477  *******************************************************************
478  *
479  * Loadable Module Support
480  *
481  *******************************************************************
482  */
483
484 #ifdef notdef
485
486 /*
487  * Driver entry points
488  */
489 static struct cdevsw fore_cdev = {
490         /* name */      noname,
491         /* maj */       -1,
492         /* flags */     0,
493         /* port */      NULL,
494         /* clone */     NULL,
495
496         /* open */      noopen,
497         /* close */     noclose,
498         /* read */      noread,
499         /* write */     nowrite,
500         /* ioctl */     noioctl,
501         /* poll */      nopoll,
502         /* mmap */      nommap,
503         /* strategy */  nostrategy,
504         /* dump */      nodump,
505         /* psize */     nopsize
506 };
507
508
509 /*
510  * Loadable device driver module description
511  */
512 MOD_DEV(fore, LM_DT_CHAR, -1, (void *)&fore_cdev);
513
514
515 /*
516  * Loadable module support "load" entry point
517  * 
518  * This is the routine called by the lkm driver whenever the
519  * modload(1) command is issued for this module.
520  *
521  * Arguments:
522  *      lkmtp   pointer to lkm drivers's structure
523  *      cmd     lkm command code
524  *
525  * Returns:
526  *      0       command was successful 
527  *      errno   command failed - reason indicated
528  *
529  */
530 static int
531 fore_load(struct lkm_table *lkmtp, int cmd)
532 {
533         return(fore_doload());
534 }
535
536
537 /*
538  * Loadable module support "unload" entry point
539  * 
540  * This is the routine called by the lkm driver whenever the
541  * modunload(1) command is issued for this module.
542  *
543  * Arguments:
544  *      lkmtp   pointer to lkm drivers's structure
545  *      cmd     lkm command code
546  *
547  * Returns:
548  *      0       command was successful 
549  *      errno   command failed - reason indicated
550  *
551  */
552 static int
553 fore_unload(struct lkm_table *lkmtp, int cmd)
554 {
555         return(fore_dounload());
556 }
557
558
559 /*
560  * Loadable module support entry point
561  * 
562  * This is the routine called by the lkm driver for all loadable module
563  * functions for this driver.  This routine name must be specified
564  * on the modload(1) command.  This routine will be called whenever the
565  * modload(1), modunload(1) or modstat(1) commands are issued for this
566  * module.
567  *
568  * Arguments:
569  *      lkmtp   pointer to lkm drivers's structure
570  *      cmd     lkm command code
571  *      ver     lkm version
572  *
573  * Returns:
574  *      0       command was successful 
575  *      errno   command failed - reason indicated
576  *
577  */
578 int
579 fore_mod(struct lkm_table *lkmtp, int cmd, int ver)
580 {
581         DISPATCH(lkmtp, cmd, ver, fore_load, fore_unload, lkm_nullcmd);
582 }
583 #endif  /* notdef */
584
585 #endif  /* ATM_LINKED */
586