57 58#include <machine/md_var.h> 59#include <machine/vm86.h> 60#include <machine/pc/bios.h> 61#include <machine/pc/vesa.h> 62 63#include <dev/fb/fbreg.h> 64#include <dev/fb/vgareg.h> 65 66#define S3PCI_DEBUG 1 67 68#define PCI_S3_VENDOR_ID 0x5333 69 70#define S3_CONFIG_IO 0x3c0 /* VGA standard config io ports */ 71#define S3_CONFIG_IO_SIZE 0x20 72 73#define S3_ENHANCED_IO 0x4ae8 /* Extended config register */ 74#define S3_ENHANCED_IO_SIZE 1 75 76#define S3_CRTC_ADDR 0x14 77#define S3_CRTC_VALUE 0x15 78 79#define PCI_BASE_MEMORY 0x10 80 81#define outb_p(value, offset) bus_space_write_1(sc->st, sc->sh, offset, value) 82#define inb_p(offset) (bus_space_read_1(sc->st, sc->sh, offset)) 83#define outb_enh(value, offset) bus_space_write_1(sc->enh_st, sc->enh_sh, \ 84 offset, value) 85#define inb_enh(offset) (bus_space_read_1(sc->enh_st, sc->enh_sh, offset)) 86 87struct s3pci_softc { 88 bus_space_tag_t st; 89 bus_space_handle_t sh; 90 bus_space_tag_t enh_st; 91 bus_space_handle_t enh_sh; 92 struct resource *port_res; 93 struct resource *enh_res; 94 struct resource *mem_res; 95 u_long mem_base; 96 u_long mem_size; 97}; 98 99static int s3lfb_error(void); 100static vi_probe_t s3lfb_probe; 101static vi_init_t s3lfb_init; 102static vi_get_info_t s3lfb_get_info; 103static vi_query_mode_t s3lfb_query_mode; 104static vi_set_mode_t s3lfb_set_mode; 105static vi_save_font_t s3lfb_save_font; 106static vi_load_font_t s3lfb_load_font; 107static vi_show_font_t s3lfb_show_font; 108static vi_save_palette_t s3lfb_save_palette; 109static vi_load_palette_t s3lfb_load_palette; 110static vi_set_border_t s3lfb_set_border; 111static vi_save_state_t s3lfb_save_state; 112static vi_load_state_t s3lfb_load_state; 113static vi_set_win_org_t s3lfb_set_origin; 114static vi_read_hw_cursor_t s3lfb_read_hw_cursor; 115static vi_set_hw_cursor_t s3lfb_set_hw_cursor; 116static vi_set_hw_cursor_shape_t s3lfb_set_hw_cursor_shape; 117static vi_blank_display_t s3lfb_blank_display; 118static vi_mmap_t s3lfb_mmap; 119static vi_ioctl_t s3lfb_ioctl; 120static vi_clear_t s3lfb_clear; 121static vi_fill_rect_t s3lfb_fill_rect; 122static vi_bitblt_t s3lfb_bitblt; 123static vi_diag_t s3lfb_diag; 124 125static video_switch_t s3lfbvidsw = { 126 s3lfb_probe, 127 s3lfb_init, 128 s3lfb_get_info, 129 s3lfb_query_mode, 130 s3lfb_set_mode, 131 s3lfb_save_font, 132 s3lfb_load_font, 133 s3lfb_show_font, 134 s3lfb_save_palette, 135 s3lfb_load_palette, 136 s3lfb_set_border, 137 s3lfb_save_state, 138 s3lfb_load_state, 139 s3lfb_set_origin, 140 s3lfb_read_hw_cursor, 141 s3lfb_set_hw_cursor, 142 s3lfb_set_hw_cursor_shape, 143 s3lfb_blank_display, 144 s3lfb_mmap, 145 s3lfb_ioctl, 146 s3lfb_clear, 147 s3lfb_fill_rect, 148 s3lfb_bitblt, 149 s3lfb_error, 150 s3lfb_error, 151 s3lfb_diag, 152}; 153 154static video_switch_t *prevvidsw; 155static device_t s3pci_dev = NULL; 156 157static int 158s3lfb_probe(int unit, video_adapter_t **adpp, void *arg, int flags) 159{ 160 return (*prevvidsw->probe)(unit, adpp, arg, flags); 161} 162 163static int 164s3lfb_init(int unit, video_adapter_t *adp, int flags) 165{ 166 return (*prevvidsw->init)(unit, adp, flags); 167} 168 169static int 170s3lfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) 171{ 172#if 0 173 device_t dev = s3pci_dev; /* XXX */ 174 struct s3pci_softc *sc = (struct s3pci_softc *)device_get_softc(dev); 175#endif 176 int error; 177 178 if ((error = (*prevvidsw->get_info)(adp, mode, info))) 179 return error; 180 181#if 0 182 /* Don't use linear addressing with text modes 183 */ 184 if ((mode > M_VESA_BASE) && 185 (info->vi_flags & V_INFO_GRAPHICS) && 186 !(info->vi_flags & V_INFO_LINEAR)) { 187 188 info->vi_flags |= V_INFO_LINEAR; 189 info->vi_buffer = sc->mem_base; 190 191 } else { 192 info->vi_buffer = 0; 193 } 194#endif 195 196 return 0; 197} 198 199static int 200s3lfb_query_mode(video_adapter_t *adp, video_info_t *info) 201{ 202 return (*prevvidsw->query_mode)(adp, info); 203} 204 205static vm_offset_t 206s3lfb_map_buffer(u_int paddr, size_t size) 207{ 208 vm_offset_t vaddr; 209 u_int off; 210 211 off = paddr - trunc_page(paddr); 212 vaddr = (vm_offset_t)pmap_mapdev(paddr - off, size + off); 213 214 return (vaddr + off); 215} 216 217static int 218s3lfb_set_mode(video_adapter_t *adp, int mode) 219{ 220 device_t dev = s3pci_dev; /* XXX */ 221 struct s3pci_softc *sc = (struct s3pci_softc *)device_get_softc(dev); 222#if 0 223 unsigned char tmp; 224#endif 225 int error; 226 227 /* First, set the mode as if it was a classic VESA card 228 */ 229 if ((error = (*prevvidsw->set_mode)(adp, mode))) 230 return error; 231 232 /* If not in a linear mode (according to s3lfb_get_info() called 233 * by vesa_set_mode in the (*vidsw[adp->va_index]->get_info)... 234 * sequence, return with no error 235 */ 236#if 0 237 if (!(adp->va_info.vi_flags & V_INFO_LINEAR)) 238 return 0; 239#endif 240 241 if ((mode <= M_VESA_BASE) || 242 !(adp->va_info.vi_flags & V_INFO_GRAPHICS) || 243 (adp->va_info.vi_flags & V_INFO_LINEAR)) 244 return 0; 245 246 /* Ok, now apply the configuration to the card */ 247 248 outb_p(0x38, S3_CRTC_ADDR); outb_p(0x48, S3_CRTC_VALUE); 249 outb_p(0x39, S3_CRTC_ADDR); outb_p(0xa5, S3_CRTC_VALUE); 250 251 /* check that CR47 is read/write */ 252 253#if 0 254 outb_p(0x47, S3_CRTC_ADDR); outb_p(0xff, S3_CRTC_VALUE); 255 tmp = inb_p(S3_CRTC_VALUE); 256 outb_p(0x00, S3_CRTC_VALUE); 257 if ((tmp != 0xff) || (inb_p(S3_CRTC_VALUE))) 258 { 259 /* lock S3 registers */ 260 261 outb_p(0x39, S3_CRTC_ADDR); outb_p(0x5a, S3_CRTC_VALUE); 262 outb_p(0x38, S3_CRTC_ADDR); outb_p(0x00, S3_CRTC_VALUE); 263 264 return ENXIO; 265 } 266#endif 267 268 /* enable enhanced register access */ 269 270 outb_p(0x40, S3_CRTC_ADDR); 271 outb_p(inb_p(S3_CRTC_VALUE) | 1, S3_CRTC_VALUE); 272 273 /* enable enhanced functions */ 274 275 outb_enh(inb_enh(0) | 1, 0x0); 276 277 /* enable enhanced mode memory mapping */ 278 279 outb_p(0x31, S3_CRTC_ADDR); 280 outb_p(inb_p(S3_CRTC_VALUE) | 8, S3_CRTC_VALUE); 281 282 /* enable linear frame buffer and set address window to max */ 283 284 outb_p(0x58, S3_CRTC_ADDR); 285 outb_p(inb_p(S3_CRTC_VALUE) | 0x13, S3_CRTC_VALUE); 286 287 /* disabled enhanced register access */ 288 289 outb_p(0x40, S3_CRTC_ADDR); 290 outb_p(inb_p(S3_CRTC_VALUE) & ~1, S3_CRTC_VALUE); 291 292 /* lock S3 registers */ 293 294 outb_p(0x39, S3_CRTC_ADDR); outb_p(0x5a, S3_CRTC_VALUE); 295 outb_p(0x38, S3_CRTC_ADDR); outb_p(0x00, S3_CRTC_VALUE); 296 297 adp->va_info.vi_flags |= V_INFO_LINEAR; 298 adp->va_info.vi_buffer = sc->mem_base; 299 adp->va_buffer = s3lfb_map_buffer(adp->va_info.vi_buffer, 300 adp->va_info.vi_buffer_size); 301 adp->va_buffer_size = adp->va_info.vi_buffer_size; 302 adp->va_window = adp->va_buffer; 303 adp->va_window_size = adp->va_info.vi_buffer_size/adp->va_info.vi_planes; 304 adp->va_window_gran = adp->va_info.vi_buffer_size/adp->va_info.vi_planes; 305 306 return 0; 307} 308 309static int 310s3lfb_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, 311 int ch, int count) 312{ 313 return (*prevvidsw->save_font)(adp, page, fontsize, data, ch, count); 314} 315 316static int 317s3lfb_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, 318 int ch, int count) 319{ 320 return (*prevvidsw->load_font)(adp, page, fontsize, data, ch, count); 321} 322 323static int 324s3lfb_show_font(video_adapter_t *adp, int page) 325{ 326 return (*prevvidsw->show_font)(adp, page); 327} 328 329static int 330s3lfb_save_palette(video_adapter_t *adp, u_char *palette) 331{ 332 return (*prevvidsw->save_palette)(adp, palette); 333} 334 335static int 336s3lfb_load_palette(video_adapter_t *adp, u_char *palette) 337{ 338 return (*prevvidsw->load_palette)(adp, palette); 339} 340 341static int 342s3lfb_set_border(video_adapter_t *adp, int color) 343{ 344 return (*prevvidsw->set_border)(adp, color); 345} 346 347static int 348s3lfb_save_state(video_adapter_t *adp, void *p, size_t size) 349{ 350 return (*prevvidsw->save_state)(adp, p, size); 351} 352 353static int 354s3lfb_load_state(video_adapter_t *adp, void *p) 355{ 356 return (*prevvidsw->load_state)(adp, p); 357} 358 359static int 360s3lfb_set_origin(video_adapter_t *adp, off_t offset) 361{ 362 return (*prevvidsw->set_win_org)(adp, offset); 363} 364 365static int 366s3lfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 367{ 368 return (*prevvidsw->read_hw_cursor)(adp, col, row); 369} 370 371static int 372s3lfb_set_hw_cursor(video_adapter_t *adp, int col, int row) 373{ 374 return (*prevvidsw->set_hw_cursor)(adp, col, row); 375} 376 377static int 378s3lfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 379 int celsize, int blink) 380{ 381 return (*prevvidsw->set_hw_cursor_shape)(adp, base, height, 382 celsize, blink); 383} 384 385static int 386s3lfb_blank_display(video_adapter_t *adp, int mode) 387{ 388 return (*prevvidsw->blank_display)(adp, mode); 389} 390 391static int 392s3lfb_mmap(video_adapter_t *adp, vm_offset_t offset, vm_offset_t *paddr, 393 int prot) 394{ 395 return (*prevvidsw->mmap)(adp, offset, paddr, prot); 396} 397 398static int 399s3lfb_clear(video_adapter_t *adp) 400{ 401 return (*prevvidsw->clear)(adp); 402} 403 404static int 405s3lfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 406{ 407 return (*prevvidsw->fill_rect)(adp, val, x, y, cx, cy); 408} 409 410static int 411s3lfb_bitblt(video_adapter_t *adp,...) 412{ 413 return (*prevvidsw->bitblt)(adp); /* XXX */ 414} 415 416static int 417s3lfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) 418{ 419 return (*prevvidsw->ioctl)(adp, cmd, arg); 420} 421 422static int 423s3lfb_diag(video_adapter_t *adp, int level) 424{ 425 return (*prevvidsw->diag)(adp, level); 426} 427 428static int 429s3lfb_error(void) 430{ 431 return 1; 432} 433 434/***********************************/ 435/* PCI detection/attachement stuff */ 436/***********************************/ 437 438static int 439s3pci_probe(device_t dev) 440{ 441 u_int32_t vendor, class, subclass, device_id; 442 443 device_id = pci_get_devid(dev); 444 vendor = device_id & 0xffff; 445 class = pci_get_class(dev); 446 subclass = pci_get_subclass(dev); 447 448 if ((class != PCIC_DISPLAY) || (subclass != PCIS_DISPLAY_VGA) || 449 (vendor != PCI_S3_VENDOR_ID)) 450 return ENXIO; 451 452 device_set_desc(dev, "S3 graphic card"); 453 454 bus_set_resource(dev, SYS_RES_IOPORT, 0, 455 S3_CONFIG_IO, S3_CONFIG_IO_SIZE); 456 bus_set_resource(dev, SYS_RES_IOPORT, 1, 457 S3_ENHANCED_IO, S3_ENHANCED_IO_SIZE); 458 459 return 0; 460 461}; 462 463static int 464s3pci_attach(device_t dev) 465{ 466 struct s3pci_softc* sc = (struct s3pci_softc*)device_get_softc(dev); 467 video_adapter_t *adp; 468 469#if 0 470 unsigned char tmp; 471#endif 472 int rid, i; 473 474 if (s3pci_dev) { 475 printf("%s: driver already attached!\n", __func__); 476 goto error; 477 } 478 479 /* Allocate resources 480 */ 481 rid = 0; 482 if (!(sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 483 0ul, ~0ul, 0, RF_ACTIVE | RF_SHAREABLE))) { 484 printf("%s: port resource allocation failed!\n", __func__); 485 goto error; 486 } 487 sc->st = rman_get_bustag(sc->port_res); 488 sc->sh = rman_get_bushandle(sc->port_res); 489 490 rid = 1; 491 if (!(sc->enh_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 492 0ul, ~0ul, 0, RF_ACTIVE | RF_SHAREABLE))) { 493 printf("%s: enhanced port resource allocation failed!\n", 494 __func__); 495 goto error; 496 } 497 sc->enh_st = rman_get_bustag(sc->enh_res); 498 sc->enh_sh = rman_get_bushandle(sc->enh_res); 499 500 rid = PCI_BASE_MEMORY; 501 if (!(sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 502 0, ~0, 1, RF_ACTIVE))) { 503 504 printf("%s: mem resource allocation failed!\n", __func__); 505 goto error; 506 } 507 508 /* The memory base address will be our LFB base address 509 */ 510 /* sc->mem_base = (u_long)rman_get_virtual(sc->mem_res); */ 511 sc->mem_base = bus_get_resource_start(dev, SYS_RES_MEMORY, rid); 512 sc->mem_size = bus_get_resource_count(dev, SYS_RES_MEMORY, rid); 513 514 /* Attach the driver to the VGA/VESA framework 515 */ 516 for (i = 0; (adp = vid_get_adapter(i)) != NULL; ++i) { 517 if ((adp->va_type == KD_VGA)) 518 break; 519 } 520 521 /* If the VESA module hasn't been loaded, or VGA doesn't 522 * exist, abort 523 */ 524 if ((adp == NULL) || !(adp->va_flags & V_ADP_VESA)) { 525 printf("%s: VGA adapter not found or VESA module not loaded!\n", 526 __func__); 527 goto error; 528 } 529 530 /* Replace the VESA video switch by owers 531 */ 532 prevvidsw = vidsw[adp->va_index]; 533 vidsw[adp->va_index] = &s3lfbvidsw; 534 535 /* Remember who we are on the bus */ 536 s3pci_dev = (void *)dev; /* XXX */ 537 538 return 0; 539 540error: 541 if (sc->mem_res) 542 bus_release_resource(dev, SYS_RES_MEMORY, PCI_BASE_MEMORY, sc->mem_res); 543 544 if (sc->enh_res) 545 bus_release_resource(dev, SYS_RES_IOPORT, 1, sc->enh_res); 546 547 if (sc->port_res) 548 bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port_res); 549 550 return ENXIO; 551}; 552 553static device_method_t s3pci_methods[] = { 554 555 DEVMETHOD(device_probe, s3pci_probe), 556 DEVMETHOD(device_attach, s3pci_attach), 557 {0,0} 558}; 559 560static driver_t s3pci_driver = { 561 "s3pci", 562 s3pci_methods, 563 sizeof(struct s3pci_softc), 564}; 565 566static devclass_t s3pci_devclass; 567 568DRIVER_MODULE(s3pci, pci, s3pci_driver, s3pci_devclass, 0, 0);
| 57 58#include <machine/md_var.h> 59#include <machine/vm86.h> 60#include <machine/pc/bios.h> 61#include <machine/pc/vesa.h> 62 63#include <dev/fb/fbreg.h> 64#include <dev/fb/vgareg.h> 65 66#define S3PCI_DEBUG 1 67 68#define PCI_S3_VENDOR_ID 0x5333 69 70#define S3_CONFIG_IO 0x3c0 /* VGA standard config io ports */ 71#define S3_CONFIG_IO_SIZE 0x20 72 73#define S3_ENHANCED_IO 0x4ae8 /* Extended config register */ 74#define S3_ENHANCED_IO_SIZE 1 75 76#define S3_CRTC_ADDR 0x14 77#define S3_CRTC_VALUE 0x15 78 79#define PCI_BASE_MEMORY 0x10 80 81#define outb_p(value, offset) bus_space_write_1(sc->st, sc->sh, offset, value) 82#define inb_p(offset) (bus_space_read_1(sc->st, sc->sh, offset)) 83#define outb_enh(value, offset) bus_space_write_1(sc->enh_st, sc->enh_sh, \ 84 offset, value) 85#define inb_enh(offset) (bus_space_read_1(sc->enh_st, sc->enh_sh, offset)) 86 87struct s3pci_softc { 88 bus_space_tag_t st; 89 bus_space_handle_t sh; 90 bus_space_tag_t enh_st; 91 bus_space_handle_t enh_sh; 92 struct resource *port_res; 93 struct resource *enh_res; 94 struct resource *mem_res; 95 u_long mem_base; 96 u_long mem_size; 97}; 98 99static int s3lfb_error(void); 100static vi_probe_t s3lfb_probe; 101static vi_init_t s3lfb_init; 102static vi_get_info_t s3lfb_get_info; 103static vi_query_mode_t s3lfb_query_mode; 104static vi_set_mode_t s3lfb_set_mode; 105static vi_save_font_t s3lfb_save_font; 106static vi_load_font_t s3lfb_load_font; 107static vi_show_font_t s3lfb_show_font; 108static vi_save_palette_t s3lfb_save_palette; 109static vi_load_palette_t s3lfb_load_palette; 110static vi_set_border_t s3lfb_set_border; 111static vi_save_state_t s3lfb_save_state; 112static vi_load_state_t s3lfb_load_state; 113static vi_set_win_org_t s3lfb_set_origin; 114static vi_read_hw_cursor_t s3lfb_read_hw_cursor; 115static vi_set_hw_cursor_t s3lfb_set_hw_cursor; 116static vi_set_hw_cursor_shape_t s3lfb_set_hw_cursor_shape; 117static vi_blank_display_t s3lfb_blank_display; 118static vi_mmap_t s3lfb_mmap; 119static vi_ioctl_t s3lfb_ioctl; 120static vi_clear_t s3lfb_clear; 121static vi_fill_rect_t s3lfb_fill_rect; 122static vi_bitblt_t s3lfb_bitblt; 123static vi_diag_t s3lfb_diag; 124 125static video_switch_t s3lfbvidsw = { 126 s3lfb_probe, 127 s3lfb_init, 128 s3lfb_get_info, 129 s3lfb_query_mode, 130 s3lfb_set_mode, 131 s3lfb_save_font, 132 s3lfb_load_font, 133 s3lfb_show_font, 134 s3lfb_save_palette, 135 s3lfb_load_palette, 136 s3lfb_set_border, 137 s3lfb_save_state, 138 s3lfb_load_state, 139 s3lfb_set_origin, 140 s3lfb_read_hw_cursor, 141 s3lfb_set_hw_cursor, 142 s3lfb_set_hw_cursor_shape, 143 s3lfb_blank_display, 144 s3lfb_mmap, 145 s3lfb_ioctl, 146 s3lfb_clear, 147 s3lfb_fill_rect, 148 s3lfb_bitblt, 149 s3lfb_error, 150 s3lfb_error, 151 s3lfb_diag, 152}; 153 154static video_switch_t *prevvidsw; 155static device_t s3pci_dev = NULL; 156 157static int 158s3lfb_probe(int unit, video_adapter_t **adpp, void *arg, int flags) 159{ 160 return (*prevvidsw->probe)(unit, adpp, arg, flags); 161} 162 163static int 164s3lfb_init(int unit, video_adapter_t *adp, int flags) 165{ 166 return (*prevvidsw->init)(unit, adp, flags); 167} 168 169static int 170s3lfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) 171{ 172#if 0 173 device_t dev = s3pci_dev; /* XXX */ 174 struct s3pci_softc *sc = (struct s3pci_softc *)device_get_softc(dev); 175#endif 176 int error; 177 178 if ((error = (*prevvidsw->get_info)(adp, mode, info))) 179 return error; 180 181#if 0 182 /* Don't use linear addressing with text modes 183 */ 184 if ((mode > M_VESA_BASE) && 185 (info->vi_flags & V_INFO_GRAPHICS) && 186 !(info->vi_flags & V_INFO_LINEAR)) { 187 188 info->vi_flags |= V_INFO_LINEAR; 189 info->vi_buffer = sc->mem_base; 190 191 } else { 192 info->vi_buffer = 0; 193 } 194#endif 195 196 return 0; 197} 198 199static int 200s3lfb_query_mode(video_adapter_t *adp, video_info_t *info) 201{ 202 return (*prevvidsw->query_mode)(adp, info); 203} 204 205static vm_offset_t 206s3lfb_map_buffer(u_int paddr, size_t size) 207{ 208 vm_offset_t vaddr; 209 u_int off; 210 211 off = paddr - trunc_page(paddr); 212 vaddr = (vm_offset_t)pmap_mapdev(paddr - off, size + off); 213 214 return (vaddr + off); 215} 216 217static int 218s3lfb_set_mode(video_adapter_t *adp, int mode) 219{ 220 device_t dev = s3pci_dev; /* XXX */ 221 struct s3pci_softc *sc = (struct s3pci_softc *)device_get_softc(dev); 222#if 0 223 unsigned char tmp; 224#endif 225 int error; 226 227 /* First, set the mode as if it was a classic VESA card 228 */ 229 if ((error = (*prevvidsw->set_mode)(adp, mode))) 230 return error; 231 232 /* If not in a linear mode (according to s3lfb_get_info() called 233 * by vesa_set_mode in the (*vidsw[adp->va_index]->get_info)... 234 * sequence, return with no error 235 */ 236#if 0 237 if (!(adp->va_info.vi_flags & V_INFO_LINEAR)) 238 return 0; 239#endif 240 241 if ((mode <= M_VESA_BASE) || 242 !(adp->va_info.vi_flags & V_INFO_GRAPHICS) || 243 (adp->va_info.vi_flags & V_INFO_LINEAR)) 244 return 0; 245 246 /* Ok, now apply the configuration to the card */ 247 248 outb_p(0x38, S3_CRTC_ADDR); outb_p(0x48, S3_CRTC_VALUE); 249 outb_p(0x39, S3_CRTC_ADDR); outb_p(0xa5, S3_CRTC_VALUE); 250 251 /* check that CR47 is read/write */ 252 253#if 0 254 outb_p(0x47, S3_CRTC_ADDR); outb_p(0xff, S3_CRTC_VALUE); 255 tmp = inb_p(S3_CRTC_VALUE); 256 outb_p(0x00, S3_CRTC_VALUE); 257 if ((tmp != 0xff) || (inb_p(S3_CRTC_VALUE))) 258 { 259 /* lock S3 registers */ 260 261 outb_p(0x39, S3_CRTC_ADDR); outb_p(0x5a, S3_CRTC_VALUE); 262 outb_p(0x38, S3_CRTC_ADDR); outb_p(0x00, S3_CRTC_VALUE); 263 264 return ENXIO; 265 } 266#endif 267 268 /* enable enhanced register access */ 269 270 outb_p(0x40, S3_CRTC_ADDR); 271 outb_p(inb_p(S3_CRTC_VALUE) | 1, S3_CRTC_VALUE); 272 273 /* enable enhanced functions */ 274 275 outb_enh(inb_enh(0) | 1, 0x0); 276 277 /* enable enhanced mode memory mapping */ 278 279 outb_p(0x31, S3_CRTC_ADDR); 280 outb_p(inb_p(S3_CRTC_VALUE) | 8, S3_CRTC_VALUE); 281 282 /* enable linear frame buffer and set address window to max */ 283 284 outb_p(0x58, S3_CRTC_ADDR); 285 outb_p(inb_p(S3_CRTC_VALUE) | 0x13, S3_CRTC_VALUE); 286 287 /* disabled enhanced register access */ 288 289 outb_p(0x40, S3_CRTC_ADDR); 290 outb_p(inb_p(S3_CRTC_VALUE) & ~1, S3_CRTC_VALUE); 291 292 /* lock S3 registers */ 293 294 outb_p(0x39, S3_CRTC_ADDR); outb_p(0x5a, S3_CRTC_VALUE); 295 outb_p(0x38, S3_CRTC_ADDR); outb_p(0x00, S3_CRTC_VALUE); 296 297 adp->va_info.vi_flags |= V_INFO_LINEAR; 298 adp->va_info.vi_buffer = sc->mem_base; 299 adp->va_buffer = s3lfb_map_buffer(adp->va_info.vi_buffer, 300 adp->va_info.vi_buffer_size); 301 adp->va_buffer_size = adp->va_info.vi_buffer_size; 302 adp->va_window = adp->va_buffer; 303 adp->va_window_size = adp->va_info.vi_buffer_size/adp->va_info.vi_planes; 304 adp->va_window_gran = adp->va_info.vi_buffer_size/adp->va_info.vi_planes; 305 306 return 0; 307} 308 309static int 310s3lfb_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, 311 int ch, int count) 312{ 313 return (*prevvidsw->save_font)(adp, page, fontsize, data, ch, count); 314} 315 316static int 317s3lfb_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, 318 int ch, int count) 319{ 320 return (*prevvidsw->load_font)(adp, page, fontsize, data, ch, count); 321} 322 323static int 324s3lfb_show_font(video_adapter_t *adp, int page) 325{ 326 return (*prevvidsw->show_font)(adp, page); 327} 328 329static int 330s3lfb_save_palette(video_adapter_t *adp, u_char *palette) 331{ 332 return (*prevvidsw->save_palette)(adp, palette); 333} 334 335static int 336s3lfb_load_palette(video_adapter_t *adp, u_char *palette) 337{ 338 return (*prevvidsw->load_palette)(adp, palette); 339} 340 341static int 342s3lfb_set_border(video_adapter_t *adp, int color) 343{ 344 return (*prevvidsw->set_border)(adp, color); 345} 346 347static int 348s3lfb_save_state(video_adapter_t *adp, void *p, size_t size) 349{ 350 return (*prevvidsw->save_state)(adp, p, size); 351} 352 353static int 354s3lfb_load_state(video_adapter_t *adp, void *p) 355{ 356 return (*prevvidsw->load_state)(adp, p); 357} 358 359static int 360s3lfb_set_origin(video_adapter_t *adp, off_t offset) 361{ 362 return (*prevvidsw->set_win_org)(adp, offset); 363} 364 365static int 366s3lfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 367{ 368 return (*prevvidsw->read_hw_cursor)(adp, col, row); 369} 370 371static int 372s3lfb_set_hw_cursor(video_adapter_t *adp, int col, int row) 373{ 374 return (*prevvidsw->set_hw_cursor)(adp, col, row); 375} 376 377static int 378s3lfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 379 int celsize, int blink) 380{ 381 return (*prevvidsw->set_hw_cursor_shape)(adp, base, height, 382 celsize, blink); 383} 384 385static int 386s3lfb_blank_display(video_adapter_t *adp, int mode) 387{ 388 return (*prevvidsw->blank_display)(adp, mode); 389} 390 391static int 392s3lfb_mmap(video_adapter_t *adp, vm_offset_t offset, vm_offset_t *paddr, 393 int prot) 394{ 395 return (*prevvidsw->mmap)(adp, offset, paddr, prot); 396} 397 398static int 399s3lfb_clear(video_adapter_t *adp) 400{ 401 return (*prevvidsw->clear)(adp); 402} 403 404static int 405s3lfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 406{ 407 return (*prevvidsw->fill_rect)(adp, val, x, y, cx, cy); 408} 409 410static int 411s3lfb_bitblt(video_adapter_t *adp,...) 412{ 413 return (*prevvidsw->bitblt)(adp); /* XXX */ 414} 415 416static int 417s3lfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) 418{ 419 return (*prevvidsw->ioctl)(adp, cmd, arg); 420} 421 422static int 423s3lfb_diag(video_adapter_t *adp, int level) 424{ 425 return (*prevvidsw->diag)(adp, level); 426} 427 428static int 429s3lfb_error(void) 430{ 431 return 1; 432} 433 434/***********************************/ 435/* PCI detection/attachement stuff */ 436/***********************************/ 437 438static int 439s3pci_probe(device_t dev) 440{ 441 u_int32_t vendor, class, subclass, device_id; 442 443 device_id = pci_get_devid(dev); 444 vendor = device_id & 0xffff; 445 class = pci_get_class(dev); 446 subclass = pci_get_subclass(dev); 447 448 if ((class != PCIC_DISPLAY) || (subclass != PCIS_DISPLAY_VGA) || 449 (vendor != PCI_S3_VENDOR_ID)) 450 return ENXIO; 451 452 device_set_desc(dev, "S3 graphic card"); 453 454 bus_set_resource(dev, SYS_RES_IOPORT, 0, 455 S3_CONFIG_IO, S3_CONFIG_IO_SIZE); 456 bus_set_resource(dev, SYS_RES_IOPORT, 1, 457 S3_ENHANCED_IO, S3_ENHANCED_IO_SIZE); 458 459 return 0; 460 461}; 462 463static int 464s3pci_attach(device_t dev) 465{ 466 struct s3pci_softc* sc = (struct s3pci_softc*)device_get_softc(dev); 467 video_adapter_t *adp; 468 469#if 0 470 unsigned char tmp; 471#endif 472 int rid, i; 473 474 if (s3pci_dev) { 475 printf("%s: driver already attached!\n", __func__); 476 goto error; 477 } 478 479 /* Allocate resources 480 */ 481 rid = 0; 482 if (!(sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 483 0ul, ~0ul, 0, RF_ACTIVE | RF_SHAREABLE))) { 484 printf("%s: port resource allocation failed!\n", __func__); 485 goto error; 486 } 487 sc->st = rman_get_bustag(sc->port_res); 488 sc->sh = rman_get_bushandle(sc->port_res); 489 490 rid = 1; 491 if (!(sc->enh_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 492 0ul, ~0ul, 0, RF_ACTIVE | RF_SHAREABLE))) { 493 printf("%s: enhanced port resource allocation failed!\n", 494 __func__); 495 goto error; 496 } 497 sc->enh_st = rman_get_bustag(sc->enh_res); 498 sc->enh_sh = rman_get_bushandle(sc->enh_res); 499 500 rid = PCI_BASE_MEMORY; 501 if (!(sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 502 0, ~0, 1, RF_ACTIVE))) { 503 504 printf("%s: mem resource allocation failed!\n", __func__); 505 goto error; 506 } 507 508 /* The memory base address will be our LFB base address 509 */ 510 /* sc->mem_base = (u_long)rman_get_virtual(sc->mem_res); */ 511 sc->mem_base = bus_get_resource_start(dev, SYS_RES_MEMORY, rid); 512 sc->mem_size = bus_get_resource_count(dev, SYS_RES_MEMORY, rid); 513 514 /* Attach the driver to the VGA/VESA framework 515 */ 516 for (i = 0; (adp = vid_get_adapter(i)) != NULL; ++i) { 517 if ((adp->va_type == KD_VGA)) 518 break; 519 } 520 521 /* If the VESA module hasn't been loaded, or VGA doesn't 522 * exist, abort 523 */ 524 if ((adp == NULL) || !(adp->va_flags & V_ADP_VESA)) { 525 printf("%s: VGA adapter not found or VESA module not loaded!\n", 526 __func__); 527 goto error; 528 } 529 530 /* Replace the VESA video switch by owers 531 */ 532 prevvidsw = vidsw[adp->va_index]; 533 vidsw[adp->va_index] = &s3lfbvidsw; 534 535 /* Remember who we are on the bus */ 536 s3pci_dev = (void *)dev; /* XXX */ 537 538 return 0; 539 540error: 541 if (sc->mem_res) 542 bus_release_resource(dev, SYS_RES_MEMORY, PCI_BASE_MEMORY, sc->mem_res); 543 544 if (sc->enh_res) 545 bus_release_resource(dev, SYS_RES_IOPORT, 1, sc->enh_res); 546 547 if (sc->port_res) 548 bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port_res); 549 550 return ENXIO; 551}; 552 553static device_method_t s3pci_methods[] = { 554 555 DEVMETHOD(device_probe, s3pci_probe), 556 DEVMETHOD(device_attach, s3pci_attach), 557 {0,0} 558}; 559 560static driver_t s3pci_driver = { 561 "s3pci", 562 s3pci_methods, 563 sizeof(struct s3pci_softc), 564}; 565 566static devclass_t s3pci_devclass; 567 568DRIVER_MODULE(s3pci, pci, s3pci_driver, s3pci_devclass, 0, 0);
|