Make sure a serial port exists by determining whether it is possible to drain
[dragonfly.git] / sys / dev / agp / agp_i810.c
1 /*-
2  * Copyright (c) 2000 Doug Rabson
3  * Copyright (c) 2000 Ruslan Ermilov
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *      $FreeBSD: src/sys/pci/agp_i810.c,v 1.1.2.5 2002/09/15 08:45:41 anholt Exp $
28  *      $DragonFly: src/sys/dev/agp/agp_i810.c,v 1.7 2004/05/13 14:33:14 joerg Exp $
29  */
30
31 /*
32  * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
33  */
34
35 #include "opt_bus.h"
36 #include "opt_pci.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
42 #include <sys/bus.h>
43 #include <sys/lock.h>
44
45 #include <bus/pci/pcivar.h>
46 #include <bus/pci/pcireg.h>
47 #include "agppriv.h"
48 #include "agpreg.h"
49
50 #include <vm/vm.h>
51 #include <vm/vm_object.h>
52 #include <vm/vm_page.h>
53 #include <vm/vm_pageout.h>
54 #include <vm/pmap.h>
55
56 #include <machine/bus.h>
57 #include <machine/resource.h>
58 #include <sys/rman.h>
59
60 MALLOC_DECLARE(M_AGP);
61
62 #define READ1(off)      bus_space_read_1(sc->bst, sc->bsh, off)
63 #define READ4(off)      bus_space_read_4(sc->bst, sc->bsh, off)
64 #define WRITE4(off,v)   bus_space_write_4(sc->bst, sc->bsh, off, v)
65
66 #define CHIP_I810 0     /* i810/i815 */
67 #define CHIP_I830 1     /* i830/i845 */
68
69 struct agp_i810_softc {
70         struct agp_softc agp;
71         u_int32_t initial_aperture;     /* aperture size at startup */
72         struct agp_gatt *gatt;
73         int chiptype;                   /* i810-like or i830 */
74         u_int32_t dcache_size;          /* i810 only */
75         u_int32_t stolen;               /* number of i830/845 gtt entries for stolen memory */
76         device_t bdev;                  /* bridge device */
77         struct resource *regs;          /* memory mapped GC registers */
78         bus_space_tag_t bst;            /* bus_space tag */
79         bus_space_handle_t bsh;         /* bus_space handle */
80 };
81
82 static const char*
83 agp_i810_match(device_t dev)
84 {
85         if (pci_get_class(dev) != PCIC_DISPLAY
86             || pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
87                 return NULL;
88
89         switch (pci_get_devid(dev)) {
90         case 0x71218086:
91                 return ("Intel 82810 (i810 GMCH) SVGA controller");
92
93         case 0x71238086:
94                 return ("Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller");
95
96         case 0x71258086:
97                 return ("Intel 82810E (i810E GMCH) SVGA controller");
98
99         case 0x11328086:
100                 return ("Intel 82815 (i815 GMCH) SVGA controller");
101
102         case 0x35778086:
103                 return ("Intel 82830 (i830M GMCH) SVGA controller");
104
105         case 0x25628086:
106                 return ("Intel 82845 (i845 GMCH) SVGA controller");
107
108         case 0x25728086:
109                 return ("Intel 82865 (i865 GMCH) SVGA controller");
110         };
111
112         return NULL;
113 }
114
115 /*
116  * Find bridge device.
117  */
118 static device_t
119 agp_i810_find_bridge(device_t dev)
120 {
121         device_t *children, child;
122         int nchildren, i;
123         u_int32_t devid;
124
125         /*
126          * Calculate bridge device's ID.
127          */
128         devid = pci_get_devid(dev);
129         switch (devid) {
130         case 0x71218086:
131         case 0x71238086:
132         case 0x71258086:
133                 devid -= 0x10000;
134                 break;
135
136         case 0x11328086:
137         case 0x35778086:
138         case 0x25628086:
139         case 0x25728086:
140                 devid -= 0x20000;
141                 break;
142         };
143         if (device_get_children(device_get_parent(dev), &children, &nchildren))
144                 return 0;
145
146         for (i = 0; i < nchildren; i++) {
147                 child = children[i];
148
149                 if (pci_get_devid(child) == devid) {
150                         free(children, M_TEMP);
151                         return child;
152                 }
153         }
154         free(children, M_TEMP);
155         return 0;
156 }
157
158 static int
159 agp_i810_probe(device_t dev)
160 {
161         const char *desc;
162
163         desc = agp_i810_match(dev);
164         if (desc) {
165                 device_t bdev;
166                 u_int8_t smram;
167                 int devid = pci_get_devid(dev);
168
169                 bdev = agp_i810_find_bridge(dev);
170                 if (!bdev) {
171                         if (bootverbose)
172                                 printf("I810: can't find bridge device\n");
173                         return ENXIO;
174                 }
175
176                 /*
177                  * checking whether internal graphics device has been activated.
178                  */
179                 if ( (devid != 0x35778086 ) &&
180                      (devid != 0x25628086 ) &&
181                      (devid != 0x25728086 ) ) {
182                         smram = pci_read_config(bdev, AGP_I810_SMRAM, 1);
183                         if ((smram & AGP_I810_SMRAM_GMS)
184                             == AGP_I810_SMRAM_GMS_DISABLED) {
185                                 if (bootverbose)
186                                         printf("I810: disabled, not probing\n");
187                                 return ENXIO;
188                         }
189                 } else {        /* I830MG */
190                         unsigned int gcc1;
191                         gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1);
192                         if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED) {
193                                 if (bootverbose)
194                                         printf("I830: disabled, not probing\n");
195                                         return ENXIO;
196                         }
197                 }
198
199                 device_verbose(dev);
200                 device_set_desc(dev, desc);
201                 return 0;
202         }
203
204         return ENXIO;
205 }
206
207 static int
208 agp_i810_attach(device_t dev)
209 {
210         struct agp_i810_softc *sc = device_get_softc(dev);
211         struct agp_gatt *gatt;
212         int error, rid;
213
214         sc->bdev = agp_i810_find_bridge(dev);
215         if (!sc->bdev)
216                 return ENOENT;
217
218         error = agp_generic_attach(dev);
219         if (error)
220                 return error;
221
222         switch (pci_get_devid(dev)) {
223         case 0x71218086:
224         case 0x71238086:
225         case 0x71258086:
226         case 0x11328086:
227                 sc->chiptype = CHIP_I810;
228                 break;
229         case 0x35778086:
230         case 0x25628086:
231         case 0x25728086:
232                 sc->chiptype = CHIP_I830;
233                 break;
234         };
235
236         /* Same for i810 and i830 */
237         rid = AGP_I810_MMADR;
238         sc->regs = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
239                                       0, ~0, 1, RF_ACTIVE);
240         if (!sc->regs) {
241                 agp_generic_detach(dev);
242                 return ENOMEM;
243         }
244         sc->bst = rman_get_bustag(sc->regs);
245         sc->bsh = rman_get_bushandle(sc->regs);
246
247         sc->initial_aperture = AGP_GET_APERTURE(dev);
248         if (sc->initial_aperture == 0) {
249                 device_printf(dev, "bad initial aperture size, disabling\n");
250                 return ENXIO;
251         }
252
253         gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_INTWAIT);
254         sc->gatt = gatt;
255
256         gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
257
258         if ( sc->chiptype == CHIP_I810 ) {
259                 /* Some i810s have on-chip memory called dcache */
260                 if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
261                         sc->dcache_size = 4 * 1024 * 1024;
262                 else
263                         sc->dcache_size = 0;
264
265                 /* According to the specs the gatt on the i810 must be 64k */
266                 gatt->ag_virtual = contigmalloc( 64 * 1024, M_AGP, 0, 
267                                         0, ~0, PAGE_SIZE, 0);
268                 if (!gatt->ag_virtual) {
269                         if (bootverbose)
270                                 device_printf(dev, "contiguous allocation failed\n");
271                         free(gatt, M_AGP);
272                         agp_generic_detach(dev);
273                         return ENOMEM;
274                 }
275                 bzero(gatt->ag_virtual, gatt->ag_entries * sizeof(u_int32_t));
276         
277                 gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
278                 agp_flush_cache();
279                 /* Install the GATT. */
280                 WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
281         } else {
282                 /* The i830 automatically initializes the 128k gatt on boot. */
283                 unsigned int gcc1, pgtblctl;
284                 
285                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1);
286                 switch (gcc1 & AGP_I830_GCC1_GMS) {
287                         case AGP_I830_GCC1_GMS_STOLEN_512:
288                                 sc->stolen = (512 - 132) * 1024 / 4096;
289                                 break;
290                         case AGP_I830_GCC1_GMS_STOLEN_1024: 
291                                 sc->stolen = (1024 - 132) * 1024 / 4096;
292                                 break;
293                         case AGP_I830_GCC1_GMS_STOLEN_8192: 
294                                 sc->stolen = (8192 - 132) * 1024 / 4096;
295                                 break;
296                         default:
297                                 sc->stolen = 0;
298                                 device_printf(dev, "unknown memory configuration, disabling\n");
299                                 agp_generic_detach(dev);
300                                 return EINVAL;
301                 }
302                 if (sc->stolen > 0)
303                         device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
304                 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
305
306                 /* GATT address is already in there, make sure it's enabled */
307                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
308 #if 0
309                 device_printf(dev, "PGTBL_CTL is 0x%08x\n", pgtblctl);
310 #endif
311                 pgtblctl |= 1;
312                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
313
314                 gatt->ag_physical = pgtblctl & ~1;
315         }
316
317         /*
318          * Make sure the chipset can see everything.
319          */
320         agp_flush_cache();
321
322         return 0;
323 }
324
325 static int
326 agp_i810_detach(device_t dev)
327 {
328         struct agp_i810_softc *sc = device_get_softc(dev);
329         int error;
330
331         error = agp_generic_detach(dev);
332         if (error)
333                 return error;
334
335         /* Clear the GATT base. */
336         if ( sc->chiptype == CHIP_I810 ) {
337                 WRITE4(AGP_I810_PGTBL_CTL, 0);
338         } else {
339                 unsigned int pgtblctl;
340                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
341                 pgtblctl &= ~1;
342                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
343         }
344
345         /* Put the aperture back the way it started. */
346         AGP_SET_APERTURE(dev, sc->initial_aperture);
347
348         if ( sc->chiptype == CHIP_I810 ) {
349                 contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP);
350         }
351         free(sc->gatt, M_AGP);
352
353         bus_release_resource(dev, SYS_RES_MEMORY,
354                              AGP_I810_MMADR, sc->regs);
355
356         return 0;
357 }
358
359 static u_int32_t
360 agp_i810_get_aperture(device_t dev)
361 {
362         struct agp_i810_softc *sc = device_get_softc(dev);
363
364         if ( sc->chiptype == CHIP_I810 ) {
365                 u_int16_t miscc;
366                 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
367                 if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
368                         return 32 * 1024 * 1024;
369                 else
370                         return 64 * 1024 * 1024;
371         } else {        /* I830 */
372                 unsigned int gcc1;
373
374                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
375                 if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
376                         return 64 * 1024 * 1024;
377                 else
378                         return 128 * 1024 * 1024;
379         }
380 }
381
382 static int
383 agp_i810_set_aperture(device_t dev, u_int32_t aperture)
384 {
385         struct agp_i810_softc *sc = device_get_softc(dev);
386         u_int16_t miscc;
387
388         if ( sc->chiptype == CHIP_I810 ) {
389                 /*
390                  * Double check for sanity.
391                  */
392                 if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
393                         device_printf(dev, "bad aperture size %d\n", aperture);
394                         return EINVAL;
395                 }
396         
397                 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
398                 miscc &= ~AGP_I810_MISCC_WINSIZE;
399                 if (aperture == 32 * 1024 * 1024)
400                         miscc |= AGP_I810_MISCC_WINSIZE_32;
401                 else
402                         miscc |= AGP_I810_MISCC_WINSIZE_64;
403         
404                 pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
405         } else {        /* I830 */
406                 unsigned int gcc1;
407
408                 if (aperture != 64 * 1024 * 1024 && aperture != 128 * 1024 * 1024) {
409                         device_printf(dev, "bad aperture size %d\n", aperture);
410                         return EINVAL;
411                 }
412                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
413                 gcc1 &= ~AGP_I830_GCC1_GMASIZE;
414                 if (aperture == 64 * 1024 * 1024)
415                         gcc1 |= AGP_I830_GCC1_GMASIZE_64;
416                 else
417                         gcc1 |= AGP_I830_GCC1_GMASIZE_128;
418
419                 pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
420         }
421
422         return 0;
423 }
424
425 static int
426 agp_i810_bind_page(device_t dev, int offset, vm_offset_t physical)
427 {
428         struct agp_i810_softc *sc = device_get_softc(dev);
429
430         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
431                 device_printf(dev, "failed: offset is 0x%08x, shift is %d, entries is %d\n", offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries);
432                 return EINVAL;
433         }
434
435         if ( sc->chiptype == CHIP_I830 ) {
436                 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
437                         device_printf(dev, "trying to bind into stolen memory");
438                         return EINVAL;
439                 }
440         }
441
442         WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, physical | 1);
443         return 0;
444 }
445
446 static int
447 agp_i810_unbind_page(device_t dev, int offset)
448 {
449         struct agp_i810_softc *sc = device_get_softc(dev);
450
451         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
452                 return EINVAL;
453
454         if ( sc->chiptype == CHIP_I830 ) {
455                 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
456                         device_printf(dev, "trying to unbind from stolen memory");
457                         return EINVAL;
458                 }
459         }
460
461         WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 0);
462         return 0;
463 }
464
465 /*
466  * Writing via memory mapped registers already flushes all TLBs.
467  */
468 static void
469 agp_i810_flush_tlb(device_t dev)
470 {
471 }
472
473 static int
474 agp_i810_enable(device_t dev, u_int32_t mode)
475 {
476
477         return 0;
478 }
479
480 static struct agp_memory *
481 agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
482 {
483         struct agp_i810_softc *sc = device_get_softc(dev);
484         struct agp_memory *mem;
485
486         if ((size & (AGP_PAGE_SIZE - 1)) != 0)
487                 return 0;
488
489         if (sc->agp.as_allocated + size > sc->agp.as_maxmem)
490                 return 0;
491
492         if (type == 1) {
493                 /*
494                  * Mapping local DRAM into GATT.
495                  */
496                 if ( sc->chiptype == CHIP_I830 )
497                         return 0;
498                 if (size != sc->dcache_size)
499                         return 0;
500         } else if (type == 2) {
501                 /*
502                  * Bogus mapping of a single page for the hardware cursor.
503                  */
504                 if (size != AGP_PAGE_SIZE)
505                         return 0;
506         }
507
508         mem = malloc(sizeof *mem, M_AGP, M_INTWAIT);
509         mem->am_id = sc->agp.as_nextid++;
510         mem->am_size = size;
511         mem->am_type = type;
512         if (type != 1)
513                 mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
514                                                  atop(round_page(size)));
515         else
516                 mem->am_obj = 0;
517
518         if (type == 2) {
519                 /*
520                  * Allocate and wire down the page now so that we can
521                  * get its physical address.
522                  */
523                 vm_page_t m;
524                 m = vm_page_grab(mem->am_obj, 0, 
525                         VM_ALLOC_NORMAL|VM_ALLOC_ZERO|VM_ALLOC_RETRY);
526                 if ((m->flags & PG_ZERO) == 0)
527                         vm_page_zero_fill(m);
528                 vm_page_wire(m);
529                 mem->am_physical = VM_PAGE_TO_PHYS(m);
530                 vm_page_wakeup(m);
531         } else {
532                 mem->am_physical = 0;
533         }
534
535         mem->am_offset = 0;
536         mem->am_is_bound = 0;
537         TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
538         sc->agp.as_allocated += size;
539
540         return mem;
541 }
542
543 static int
544 agp_i810_free_memory(device_t dev, struct agp_memory *mem)
545 {
546         struct agp_i810_softc *sc = device_get_softc(dev);
547
548         if (mem->am_is_bound)
549                 return EBUSY;
550
551         if (mem->am_type == 2) {
552                 /*
553                  * Unwire the page which we wired in alloc_memory.
554                  */
555                 vm_page_t m = vm_page_lookup(mem->am_obj, 0);
556                 vm_page_unwire(m, 0);
557         }
558
559         sc->agp.as_allocated -= mem->am_size;
560         TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
561         if (mem->am_obj)
562                 vm_object_deallocate(mem->am_obj);
563         free(mem, M_AGP);
564         return 0;
565 }
566
567 static int
568 agp_i810_bind_memory(device_t dev, struct agp_memory *mem,
569                      vm_offset_t offset)
570 {
571         struct agp_i810_softc *sc = device_get_softc(dev);
572         vm_offset_t i;
573
574         if (mem->am_type != 1)
575                 return agp_generic_bind_memory(dev, mem, offset);
576
577         if ( sc->chiptype == CHIP_I830 )
578                 return EINVAL;
579
580         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
581                 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4,
582                        i | 3);
583         }
584
585         return 0;
586 }
587
588 static int
589 agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
590 {
591         struct agp_i810_softc *sc = device_get_softc(dev);
592         vm_offset_t i;
593
594         if (mem->am_type != 1)
595                 return agp_generic_unbind_memory(dev, mem);
596
597         if ( sc->chiptype == CHIP_I830 )
598                 return EINVAL;
599
600         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
601                 WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
602
603         return 0;
604 }
605
606 static device_method_t agp_i810_methods[] = {
607         /* Device interface */
608         DEVMETHOD(device_probe,         agp_i810_probe),
609         DEVMETHOD(device_attach,        agp_i810_attach),
610         DEVMETHOD(device_detach,        agp_i810_detach),
611         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
612         DEVMETHOD(device_suspend,       bus_generic_suspend),
613         DEVMETHOD(device_resume,        bus_generic_resume),
614
615         /* AGP interface */
616         DEVMETHOD(agp_get_aperture,     agp_i810_get_aperture),
617         DEVMETHOD(agp_set_aperture,     agp_i810_set_aperture),
618         DEVMETHOD(agp_bind_page,        agp_i810_bind_page),
619         DEVMETHOD(agp_unbind_page,      agp_i810_unbind_page),
620         DEVMETHOD(agp_flush_tlb,        agp_i810_flush_tlb),
621         DEVMETHOD(agp_enable,           agp_i810_enable),
622         DEVMETHOD(agp_alloc_memory,     agp_i810_alloc_memory),
623         DEVMETHOD(agp_free_memory,      agp_i810_free_memory),
624         DEVMETHOD(agp_bind_memory,      agp_i810_bind_memory),
625         DEVMETHOD(agp_unbind_memory,    agp_i810_unbind_memory),
626
627         { 0, 0 }
628 };
629
630 static driver_t agp_i810_driver = {
631         "agp",
632         agp_i810_methods,
633         sizeof(struct agp_i810_softc),
634 };
635
636 static devclass_t agp_devclass;
637
638 DRIVER_MODULE(agp_i810, pci, agp_i810_driver, agp_devclass, 0, 0);
639 MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
640 MODULE_DEPEND(agp_i810, pci, 1, 1, 1);