11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1996-2001 Linus Torvalds & author (see below) 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Version 0.03 Cleaned auto-tune, added probe 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Version 0.04 Added second channel tuning 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Version 0.05 Enhanced tuning ; added qd6500 support 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Version 0.06 Added dos driver's list 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Version 0.07 Second channel bug fix 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * QDI QD6500/QD6580 EIDE controller fast support 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To activate controller support, use "ide0=qd65xx" 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by 195193535517825f9a07967e4868a1103013d0a99dSamuel Thibault * Samuel Thibault <samuel.thibault@ens-lyon.org> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ide.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35d92f1a2829dbe29c644569a3b64a021e4d90005dBartlomiej Zolnierkiewicz#define DRV_NAME "qd65xx" 36d92f1a2829dbe29c644569a3b64a021e4d90005dBartlomiej Zolnierkiewicz 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "qd65xx.h" 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * I/O ports are 0x30-0x31 (and 0x32-0x33 for qd6580) 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or 0xb0-0xb1 (and 0xb2-0xb3 for qd6580) 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -- qd6500 is a single IDE interface 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -- qd6580 is a dual IDE interface 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * More research on qd6580 being done by willmore@cig.mot.com (David) 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * More Information given by Petr Soucek (petr@ryston.cz) 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * http://www.ryston.cz/petr/vlb 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * base: Timer1 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * base+0x01: Config (R/O) 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 (only useful for qd6500) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bit 1: qd65xx baseport: 1 = 0xb0 ; 0 = 0x30 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bit 3: qd6500: 1 = disabled, 0 = enabled 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qd6580: 1 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * upper nibble: 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qd6500: 1100 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qd6580: either 1010 or 0101 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * base+0x02: Timer2 (qd6580 only) 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * base+0x03: Control (qd6580 only) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bits 0-3 must always be set 1 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 = Primary and Secondary ports enabled : channel 0 for hda & hdb 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * channel 1 for hdc & hdd 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bit 1 : 1 = only disks on primary port 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 = disks & ATAPI devices on primary port 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bit 2-4 : always 0 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bit 5 : status, but of what ? 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bit 6 : always set 1 by dos driver 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bit 7 : set 1 for non-ATAPI devices on primary port 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (maybe read-ahead and post-write buffer ?) 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 88d07616f19336b514eef06e6a361988c4073e6ecbBartlomiej Zolnierkiewicz * qd65xx_select: 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 90d07616f19336b514eef06e6a361988c4073e6ecbBartlomiej Zolnierkiewicz * This routine is invoked to prepare for access to a given drive. 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 93abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyovstatic void qd65xx_dev_select(ide_drive_t *drive) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) | 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (QD_TIMREG(drive) & 0x02); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (timings[index] != QD_TIMING(drive)) 99c196567a81af6988d1a71b43dd21c47e1ff46f6eBartlomiej Zolnierkiewicz outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); 100abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov 101abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov outb(drive->select | ATA_DEVICE_OBS, drive->hwif->io_ports.device_addr); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qd6500_compute_timing 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * computes the timing value where 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lower nibble represents active time, in count of VLB clocks 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * upper nibble represents recovery time, in count of VLB clocks 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11430e5ee4d1a651a0c66e86c6612c003034bd20ba2Bartlomiej Zolnierkiewicz int clk = ide_vlb_clk ? ide_vlb_clk : 50; 115ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz u8 act_cyc, rec_cyc; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 117ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz if (clk <= 33) { 118ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz act_cyc = 9 - IDE_IN(active_time * clk / 1000 + 1, 2, 9); 119ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 0, 15); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 121ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz act_cyc = 8 - IDE_IN(active_time * clk / 1000 + 1, 1, 8); 122ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz rec_cyc = 18 - IDE_IN(recovery_time * clk / 1000 + 1, 3, 18); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 125ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz return (rec_cyc << 4) | 0x08 | act_cyc; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qd6580_compute_timing 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * idem for qd6580 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 qd6580_compute_timing (int active_time, int recovery_time) 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13630e5ee4d1a651a0c66e86c6612c003034bd20ba2Bartlomiej Zolnierkiewicz int clk = ide_vlb_clk ? ide_vlb_clk : 50; 137ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz u8 act_cyc, rec_cyc; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 139ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz act_cyc = 17 - IDE_IN(active_time * clk / 1000 + 1, 2, 17); 140ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 2, 15); 141ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz 142ebae41a5a0583fb732c41445df4ac2c41016df74Bartlomiej Zolnierkiewicz return (rec_cyc << 4) | act_cyc; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qd_find_disk_type 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tries to find timing from dos driver's table 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int qd_find_disk_type (ide_drive_t *drive, 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int *active_time, int *recovery_time) 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct qd65xx_timing_s *p; 1554dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz char *m = (char *)&drive->id[ATA_ID_PROD]; 1564dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz char model[ATA_ID_PROD_LEN]; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1584dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz if (*m == 0) 1594dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz return 0; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1614dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz strncpy(model, m, ATA_ID_PROD_LEN); 1624dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz ide_fixstring(model, ATA_ID_PROD_LEN, 1); /* byte-swap */ 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (p = qd65xx_timing ; p->offset != -1 ; p++) { 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp(p->model, model+p->offset, 4)) { 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "%s: listed !\n", drive->name); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *active_time = p->active; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *recovery_time = p->recovery; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qd_set_timing: 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 178d07616f19336b514eef06e6a361988c4073e6ecbBartlomiej Zolnierkiewicz * records the timing 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void qd_set_timing (ide_drive_t *drive, u8 timing) 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1835bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos unsigned long data = (unsigned long)ide_get_drivedata(drive); 1845bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos 1855bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos data &= 0xff00; 1865bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos data |= timing; 1875bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos ide_set_drivedata(drive, (void *)data); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "%s: %#x\n", drive->name, timing); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 192e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewiczstatic void qd6500_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1944dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz u16 *id = drive->id; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int active_time = 175; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int recovery_time = 415; /* worst case values from the dos driver */ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 198e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewicz /* FIXME: use drive->pio_mode value */ 1994dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz if (!qd_find_disk_type(drive, &active_time, &recovery_time) && 20048fb2688aa67baba373531cc4ed2d9e695983c3fBartlomiej Zolnierkiewicz (id[ATA_ID_OLD_PIO_MODES] & 0xff) && (id[ATA_ID_FIELD_VALID] & 2) && 2014dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz id[ATA_ID_EIDE_PIO] >= 240) { 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "%s: PIO mode%d\n", drive->name, 20348fb2688aa67baba373531cc4ed2d9e695983c3fBartlomiej Zolnierkiewicz id[ATA_ID_OLD_PIO_MODES] & 0xff); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds active_time = 110; 2054dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz recovery_time = drive->id[ATA_ID_EIDE_PIO] - 120; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 208898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz qd_set_timing(drive, qd6500_compute_timing(drive->hwif, 209898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz active_time, recovery_time)); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 212e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewiczstatic void qd6580_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 214e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewicz const u8 pio = drive->pio_mode - XFER_PIO_0; 2152feecface7fd62be75bd4961324dc279a04bef22Bartlomiej Zolnierkiewicz struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); 2167dd00083b1160b560fa2a0a486799b57baa5d035Bartlomiej Zolnierkiewicz unsigned int cycle_time; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int active_time = 175; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int recovery_time = 415; /* worst case values from the dos driver */ 21979472b6ea9e74ee4400ba57ba84cad86426e2d6dBartlomiej Zolnierkiewicz u8 base = (hwif->config_data & 0xff00) >> 8; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) { 2227dd00083b1160b560fa2a0a486799b57baa5d035Bartlomiej Zolnierkiewicz cycle_time = ide_pio_cycle_time(drive, pio); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (pio) { 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: break; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 3: 2277dd00083b1160b560fa2a0a486799b57baa5d035Bartlomiej Zolnierkiewicz if (cycle_time >= 110) { 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds active_time = 86; 2297dd00083b1160b560fa2a0a486799b57baa5d035Bartlomiej Zolnierkiewicz recovery_time = cycle_time - 102; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: 2347dd00083b1160b560fa2a0a486799b57baa5d035Bartlomiej Zolnierkiewicz if (cycle_time >= 69) { 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds active_time = 70; 2367dd00083b1160b560fa2a0a486799b57baa5d035Bartlomiej Zolnierkiewicz recovery_time = cycle_time - 61; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2417dd00083b1160b560fa2a0a486799b57baa5d035Bartlomiej Zolnierkiewicz if (cycle_time >= 180) { 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds active_time = 110; 2437dd00083b1160b560fa2a0a486799b57baa5d035Bartlomiej Zolnierkiewicz recovery_time = cycle_time - 120; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2452feecface7fd62be75bd4961324dc279a04bef22Bartlomiej Zolnierkiewicz active_time = t->active; 2467dd00083b1160b560fa2a0a486799b57baa5d035Bartlomiej Zolnierkiewicz recovery_time = cycle_time - active_time; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "%s: PIO mode%d\n", drive->name,pio); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 252898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz if (!hwif->channel && drive->media != ide_disk) { 253c196567a81af6988d1a71b43dd21c47e1ff46f6eBartlomiej Zolnierkiewicz outb(0x5f, QD_CONTROL_PORT); 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO " 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "and post-write buffer on %s.\n", 256898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz drive->name, hwif->name); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time)); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qd_testreg 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tests if the given port is a register 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init qd_testreg(int port) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 271f949820de30b6fd0eb958f7eea87dac190de1cecBartlomiej Zolnierkiewicz u8 savereg, readreg; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 273c196567a81af6988d1a71b43dd21c47e1ff46f6eBartlomiej Zolnierkiewicz local_irq_save(flags); 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds savereg = inb_p(port); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(QD_TESTVAL, port); /* safe value */ 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readreg = inb_p(port); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(savereg, port); 278c196567a81af6988d1a71b43dd21c47e1ff46f6eBartlomiej Zolnierkiewicz local_irq_restore(flags); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (savereg == QD_TESTVAL) { 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n"); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Please contact maintainers to tell about your hardware\n"); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Assuming qd65xx is not present.\n"); 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (readreg != QD_TESTVAL); 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 290e6d95bd14928926d6658b5e4ace905e8b83ed27aBartlomiej Zolnierkiewiczstatic void __init qd6500_init_dev(ide_drive_t *drive) 2911f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz{ 292e6d95bd14928926d6658b5e4ace905e8b83ed27aBartlomiej Zolnierkiewicz ide_hwif_t *hwif = drive->hwif; 29379472b6ea9e74ee4400ba57ba84cad86426e2d6dBartlomiej Zolnierkiewicz u8 base = (hwif->config_data & 0xff00) >> 8; 29479472b6ea9e74ee4400ba57ba84cad86426e2d6dBartlomiej Zolnierkiewicz u8 config = QD_CONFIG(hwif); 2951f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz 2965bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos ide_set_drivedata(drive, (void *)QD6500_DEF_DATA); 2971f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz} 2981f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz 299e6d95bd14928926d6658b5e4ace905e8b83ed27aBartlomiej Zolnierkiewiczstatic void __init qd6580_init_dev(ide_drive_t *drive) 3001f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz{ 301e6d95bd14928926d6658b5e4ace905e8b83ed27aBartlomiej Zolnierkiewicz ide_hwif_t *hwif = drive->hwif; 3021f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz u16 t1, t2; 30379472b6ea9e74ee4400ba57ba84cad86426e2d6dBartlomiej Zolnierkiewicz u8 base = (hwif->config_data & 0xff00) >> 8; 30479472b6ea9e74ee4400ba57ba84cad86426e2d6dBartlomiej Zolnierkiewicz u8 config = QD_CONFIG(hwif); 3051f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz 30679472b6ea9e74ee4400ba57ba84cad86426e2d6dBartlomiej Zolnierkiewicz if (hwif->host_flags & IDE_HFLAG_SINGLE) { 3071f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz t1 = QD6580_DEF_DATA; 3081f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz t2 = QD6580_DEF_DATA2; 3091f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz } else 3101f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA; 3111f2cf8b0014fdfa3141449b508aca25e78c078a7Bartlomiej Zolnierkiewicz 3125bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos ide_set_drivedata(drive, (void *)((drive->dn & 1) ? t2 : t1)); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 315abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyovstatic const struct ide_tp_ops qd65xx_tp_ops = { 316abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov .exec_command = ide_exec_command, 317abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov .read_status = ide_read_status, 318abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov .read_altstatus = ide_read_altstatus, 319abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov .write_devctl = ide_write_devctl, 320abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov 321abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov .dev_select = qd65xx_dev_select, 322abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov .tf_load = ide_tf_load, 323abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov .tf_read = ide_tf_read, 324abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov 325abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov .input_data = ide_input_data, 326abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov .output_data = ide_output_data, 327abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov}; 328abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov 329ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic const struct ide_port_ops qd6500_port_ops = { 330e6d95bd14928926d6658b5e4ace905e8b83ed27aBartlomiej Zolnierkiewicz .init_dev = qd6500_init_dev, 331ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .set_pio_mode = qd6500_set_pio_mode, 332ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz}; 333ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz 334ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic const struct ide_port_ops qd6580_port_ops = { 335e6d95bd14928926d6658b5e4ace905e8b83ed27aBartlomiej Zolnierkiewicz .init_dev = qd6580_init_dev, 336ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .set_pio_mode = qd6580_set_pio_mode, 337ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz}; 338ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz 339c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewiczstatic const struct ide_port_info qd65xx_port_info __initdata = { 340d92f1a2829dbe29c644569a3b64a021e4d90005dBartlomiej Zolnierkiewicz .name = DRV_NAME, 341abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov .tp_ops = &qd65xx_tp_ops, 342c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz .chipset = ide_qd65xx, 343c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz .host_flags = IDE_HFLAG_IO_32BIT | 3440d28ec7f213eee37855741410a95ec559f9fa87aBartlomiej Zolnierkiewicz IDE_HFLAG_NO_DMA, 345c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz .pio_mask = ATA_PIO4, 346c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz}; 347c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qd_probe: 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * looks at the specified baseport, and if qd found, registers & initialises it 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return 1 if another qd may be probed 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init qd_probe(int base) 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3570bfeee7d4190938291a76536c7f6cd8f4e2dc30cBartlomiej Zolnierkiewicz int rc; 3587a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz u8 config, unit, control; 359e277f91fef8a0ff7726ad33eb79c6f0d0c6229a8Bartlomiej Zolnierkiewicz struct ide_port_info d = qd65xx_port_info; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361c196567a81af6988d1a71b43dd21c47e1ff46f6eBartlomiej Zolnierkiewicz config = inb(QD_CONFIG_PORT); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) 3647daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz return -ENODEV; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit = ! (config & QD_CONFIG_IDE_BASEPORT); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 368e277f91fef8a0ff7726ad33eb79c6f0d0c6229a8Bartlomiej Zolnierkiewicz if (unit) 369e277f91fef8a0ff7726ad33eb79c6f0d0c6229a8Bartlomiej Zolnierkiewicz d.host_flags |= IDE_HFLAG_QD_2ND_PORT; 370e277f91fef8a0ff7726ad33eb79c6f0d0c6229a8Bartlomiej Zolnierkiewicz 3717a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz switch (config & 0xf0) { 3727a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz case QD_CONFIG_QD6500: 3737daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz if (qd_testreg(base)) 3747daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz return -ENODEV; /* bad register */ 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (config & QD_CONFIG_DISABLED) { 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "qd6500 is disabled !\n"); 3787daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz return -ENODEV; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381e277f91fef8a0ff7726ad33eb79c6f0d0c6229a8Bartlomiej Zolnierkiewicz printk(KERN_NOTICE "qd6500 at %#x\n", base); 382e277f91fef8a0ff7726ad33eb79c6f0d0c6229a8Bartlomiej Zolnierkiewicz printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n", 383e277f91fef8a0ff7726ad33eb79c6f0d0c6229a8Bartlomiej Zolnierkiewicz config, QD_ID3); 384e277f91fef8a0ff7726ad33eb79c6f0d0c6229a8Bartlomiej Zolnierkiewicz 385ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz d.port_ops = &qd6500_port_ops; 38679472b6ea9e74ee4400ba57ba84cad86426e2d6dBartlomiej Zolnierkiewicz d.host_flags |= IDE_HFLAG_SINGLE; 3877a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz break; 3887a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz case QD_CONFIG_QD6580_A: 3897a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz case QD_CONFIG_QD6580_B: 3907daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz if (qd_testreg(base) || qd_testreg(base + 0x02)) 3917daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz return -ENODEV; /* bad registers */ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 393c196567a81af6988d1a71b43dd21c47e1ff46f6eBartlomiej Zolnierkiewicz control = inb(QD_CONTROL_PORT); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_NOTICE "qd6580 at %#x\n", base); 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config, control, QD_ID3); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 399788d669736dd3d15195fea07bf97ec5a2e9f15e7Bartlomiej Zolnierkiewicz outb(QD_DEF_CONTR, QD_CONTROL_PORT); 400788d669736dd3d15195fea07bf97ec5a2e9f15e7Bartlomiej Zolnierkiewicz 401ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz d.port_ops = &qd6580_port_ops; 4027a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz if (control & QD_CONTR_SEC_DISABLED) 40379472b6ea9e74ee4400ba57ba84cad86426e2d6dBartlomiej Zolnierkiewicz d.host_flags |= IDE_HFLAG_SINGLE; 40479472b6ea9e74ee4400ba57ba84cad86426e2d6dBartlomiej Zolnierkiewicz 4057a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz printk(KERN_INFO "qd6580: %s IDE board\n", 4067a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz (control & QD_CONTR_SEC_DISABLED) ? "single" : "dual"); 4077a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz break; 4087a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz default: 4097a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz return -ENODEV; 4107a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz } 41126bcb879c03254545a19c6700fe5bcef6f21e7b1Bartlomiej Zolnierkiewicz 4127a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz rc = ide_legacy_device_add(&d, (base << 8) | config); 413e277f91fef8a0ff7726ad33eb79c6f0d0c6229a8Bartlomiej Zolnierkiewicz 4147a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz if (d.host_flags & IDE_HFLAG_SINGLE) 4157a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz return (rc == 0) ? 1 : rc; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4177a2199f341edb2515021ccd6fe122c0d15b08fc7Bartlomiej Zolnierkiewicz return rc; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42090ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool probe_qd65xx; 421849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewicz 422849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewiczmodule_param_named(probe, probe_qd65xx, bool, 0); 423849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej ZolnierkiewiczMODULE_PARM_DESC(probe, "probe for QD65xx chipsets"); 424849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewicz 425ade2daf9c6e57845fe83a24e0a9fa1c03c6e91b1Bartlomiej Zolnierkiewiczstatic int __init qd65xx_init(void) 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4277daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz int rc1, rc2 = -ENODEV; 4287daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz 429849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewicz if (probe_qd65xx == 0) 430849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewicz return -ENODEV; 431849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewicz 4327daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz rc1 = qd_probe(0x30); 4337daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz if (rc1) 4347daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz rc2 = qd_probe(0xb0); 4357daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz 4367daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz if (rc1 < 0 && rc2 < 0) 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4387daf66dd142b1978bf8670d9d959d835de37476fBartlomiej Zolnierkiewicz 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(qd65xx_init); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Samuel Thibault"); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("support of qd65xx vlb ide chipset"); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 447