Deleted Added
sdiff udiff text old ( 45720 ) new ( 45798 )
full compact
1/*-
2 * Copyright (c) 1998,1999 S�ren Schmidt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $Id: ata-all.c,v 1.7 1999/04/16 21:21:52 peter Exp $
29 */
30
31#include "ata.h"
32#if NATA > 0
33#include "isa.h"
34#include "pci.h"
35#include "atadisk.h"
36#include "opt_global.h"
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#include <sys/interrupt.h>
41#include <sys/conf.h>
42#include <sys/module.h>
43#include <sys/bus.h>
44#include <sys/buf.h>
45#include <sys/malloc.h>
46#include <sys/devicestat.h>
47#include <vm/vm.h>
48#include <vm/pmap.h>
49#include <machine/resource.h>
50#include <machine/bus.h>
51#include <sys/rman.h>
52#include <machine/clock.h>
53#ifdef __i386__
54#include <machine/smp.h>
55#endif
56#include <pci/pcivar.h>
57#include <pci/pcireg.h>
58#include <isa/isavar.h>
59#include <isa/isareg.h>
60#include <dev/ata/ata-all.h>
61#include <dev/ata/ata-disk.h>
62#include <dev/ata/atapi-all.h>
63
64/* misc defines */
65#define UNIT(dev) (dev>>3 & 0x1f) /* assume 8 minor # per unit */
66#define MIN(a,b) ((a)>(b)?(b):(a))
67#if SMP == 0
68#define isa_apic_irq(x) x
69#endif
70
71/* prototypes */
72#if NPCI > 0
73static void promise_intr(int32_t);
74#endif
75static int32_t ata_probe(int32_t, int32_t, int32_t, device_t, int32_t *);
76static void ataintr(int32_t);
77
78/*
79 * Ought to be handled by the devclass.
80 */
81static int32_t atanlun = 0;
82struct ata_softc *atadevices[MAXATA];
83
84static devclass_t ata_devclass;
85
86#if NISA > 0
87
88static int
89ata_isaprobe(device_t dev)
90{
91 struct resource *port;
92 int rid;
93 int32_t ctlr, res;
94 int unit;
95
96 /* Allocate the port range */
97 rid = 0;
98 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE);
99 if (!port)
100 return (ENOMEM);
101
102 for (ctlr = 0; ctlr < atanlun; ctlr++) {
103 if (atadevices[ctlr]->ioaddr == rman_get_start(port)) {
104 printf("ata-isa%d: already registered as ata%d\n",
105 device_get_unit(dev), ctlr);
106 bus_release_resource(dev, SYS_RES_IOPORT, 0, port);
107 return ENXIO;
108 }
109 }
110
111 /*
112 * XXX not sure what to do with the unit. The new bus code will
113 * automatically assign unit numbers for both pci and isa. For
114 * now, store it in the softc.
115 */
116 res = ata_probe(rman_get_start(port), rman_get_start(port) + ATA_ALTPORT,
117 0, dev, &unit);
118 *(int *) device_get_softc(dev) = unit;
119
120 bus_release_resource(dev, SYS_RES_IOPORT, 0, port);
121
122 if (res) {
123 isa_set_portsize(dev, res);
124 return 0;
125 }
126
127 return ENXIO;
128}
129
130static int
131ata_isaattach(device_t dev)
132{
133 struct resource *port;
134 struct resource *irq;
135 int rid, unit;
136 void *ih;
137
138 /* Allocate the port range and interrupt */
139 rid = 0;
140 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE);
141 if (!port)
142 return (ENOMEM);
143
144 rid = 0;
145 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE);
146 if (!irq) {
147 bus_release_resource(dev, SYS_RES_IOPORT, 0, port);
148 return (ENOMEM);
149 }
150
151 /*
152 * The interrupt code could be changed to take the ata_softc as
153 * its argument directly.
154 */
155 unit = *(int *) device_get_softc(dev);
156 return bus_setup_intr(dev, irq, (driver_intr_t *) ataintr,
157 (void*)(uintptr_t) unit, &ih);
158}
159
160static device_method_t ata_isa_methods[] = {
161 /* Device interface */
162 DEVMETHOD(device_probe, ata_isaprobe),
163 DEVMETHOD(device_attach, ata_isaattach),
164 { 0, 0 }
165};
166
167static driver_t ata_isa_driver = {
168 "ata",
169 ata_isa_methods,
170 DRIVER_TYPE_BIO,
171 sizeof(int),
172};
173
174DRIVER_MODULE(ata, isa, ata_isa_driver, ata_devclass, 0, 0);
175
176#endif
177
178#if NPCI > 0
179
180static const char *
181ata_pcimatch(device_t dev)
182{
183 u_int32_t data;
184
185 data = pci_read_config(dev, PCI_CLASS_REG, 4);
186 if (pci_get_class(dev) == PCIC_STORAGE &&
187 (pci_get_subclass(dev) == PCIS_STORAGE_IDE ||
188 pci_get_subclass(dev) == PCIS_STORAGE_RAID)) {
189 switch (pci_get_devid(dev)) {
190 case 0x12308086:
191 return "Intel PIIX IDE controller";
192 case 0x70108086:
193 return "Intel PIIX3 IDE controller";
194 case 0x71118086:
195 return "Intel PIIX4 IDE controller";
196 case 0x4d33105a:
197 return "Promise Ultra/33 IDE controller";
198 case 0x522910b9:
199 return "AcerLabs Aladdin IDE controller";
200#if 0
201 case 0x05711106:
202 return "VIA Apollo IDE controller";
203 case 0x06401095:
204 return "CMD 640 IDE controller";
205 case 0x06461095:
206 return "CMD 646 IDE controller";
207 case 0xc6931080:
208 return "Cypress 82C693 IDE controller";
209 case 0x01021078:
210 return "Cyrix 5530 IDE controller";
211#endif
212 default:
213 return "Unknown PCI IDE controller";
214 }
215 }
216 return NULL;
217}
218
219static int
220ata_pciprobe(device_t dev)
221{
222 const char *desc = ata_pcimatch(dev);
223 if (desc) {
224 device_set_desc(dev, desc);
225 return 0;
226 }
227 else
228 return ENXIO;
229}
230
231static int
232ata_pciattach(device_t dev)
233{
234 int unit = device_get_unit(dev);
235 u_int32_t type;
236 u_int8_t class, subclass;
237 u_int32_t cmd;
238 int32_t iobase_1, iobase_2, altiobase_1, altiobase_2;
239 int32_t bmaddr_1 = 0, bmaddr_2 = 0, sysctrl = 0, irq1, irq2;
240 int32_t lun;
241
242 /* set up vendor-specific stuff */
243 type = pci_get_devid(dev);
244 class = pci_get_class(dev);
245 subclass = pci_get_subclass(dev);
246 cmd = pci_read_config(dev, PCIR_COMMAND, 4);
247
248#ifdef ATA_DEBUG
249 printf("ata%d: type=%08x class=%02x subclass=%02x cmd=%08x\n",
250 unit, type, class, subclass, cmd);
251#endif
252
253 /* if this is a Promise controller handle it specially */
254 if (type == 0x4d33105a) {
255 iobase_1 = pci_read_config(dev, 0x10, 4) & 0xfffc;
256 altiobase_1 = pci_read_config(dev, 0x14, 4) & 0xfffc;
257 iobase_2 = pci_read_config(dev, 0x18, 4) & 0xfffc;
258 altiobase_2 = pci_read_config(dev, 0x1c, 4) & 0xfffc;
259 irq1 = irq2 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff;
260 bmaddr_1 = pci_read_config(dev, 0x20, 4) & 0xfffc;
261 bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1;
262 sysctrl = (pci_read_config(dev, 0x20, 4) & 0xfffc) + 0x1c;
263 outb(bmaddr_1 + 0x1f, inb(bmaddr_1 + 0x1f) | 0x01);
264 printf("ata-pci%d: Busmastering DMA supported\n", unit);
265 }
266 /* everybody else seems to do it this way */
267 else {
268 if ((unit == 0) &&
269 (pci_get_progif(dev) & PCIP_STORAGE_IDE_MODEPRIM) == 0) {
270 iobase_1 = IO_WD1;
271 altiobase_1 = iobase_1 + ATA_ALTPORT;
272 irq1 = 14;
273 }
274 else {
275 iobase_1 = pci_read_config(dev, 0x10, 4) & 0xfffc;
276 altiobase_1 = pci_read_config(dev, 0x14, 4) & 0xfffc;
277 irq1 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff;
278 }
279 if ((unit == 0) &&
280 (pci_get_progif(dev) & PCIP_STORAGE_IDE_MODESEC) == 0) {
281 iobase_2 = IO_WD2;
282 altiobase_2 = iobase_2 + ATA_ALTPORT;
283 irq2 = 15;
284 }
285 else {
286 iobase_2 = pci_read_config(dev, 0x18, 4) & 0xfffc;
287 altiobase_2 = pci_read_config(dev, 0x1c, 4) & 0xfffc;
288 irq2 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff;
289 }
290
291 /* is this controller busmaster capable ? */
292 if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) {
293 /* is busmastering support turned on ? */
294 if ((pci_read_config(dev, PCI_COMMAND_STATUS_REG, 4) & 5) == 5) {
295 /* is there a valid port range to connect to ? */
296 if ((bmaddr_1 = pci_read_config(dev, 0x20, 4) & 0xfffc)) {
297 bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1;
298 printf("ata-pci%d: Busmastering DMA supported\n", unit);
299 }
300 else
301 printf("ata-pci%d: Busmastering DMA not configured\n",unit);
302 }
303 else
304 printf("ata-pci%d: Busmastering DMA not enabled\n", unit);
305 }
306 else
307 printf("ata-pci%d: Busmastering DMA not supported\n", unit);
308 }
309
310 /* now probe the addresse found for "real" ATA/ATAPI hardware */
311 lun = 0;
312 if (ata_probe(iobase_1, altiobase_1, bmaddr_1, dev, &lun)) {
313 if (iobase_1 == IO_WD1)
314#ifdef __i386__
315 register_intr(irq1,(int)"",0,(inthand2_t *)ataintr,&bio_imask,lun);
316#endif
317#ifdef __alpha__
318 alpha_platform_setup_ide_intr(0, ataintr, (void *)(intptr_t)lun);
319#endif
320 else {
321 struct resource *irq;
322 int rid = 0;
323 void *ih;
324
325 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0,1,RF_ACTIVE);
326 if (sysctrl)
327 bus_setup_intr(dev, irq, (driver_intr_t *)promise_intr,
328 (void *)lun, &ih);
329 else
330 bus_setup_intr(dev, irq, (driver_intr_t *)ataintr,
331 (void *)lun, &ih);
332 }
333 printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
334 lun, iobase_1, isa_apic_irq(irq1), unit);
335 }
336 lun = 1;
337 if (ata_probe(iobase_2, altiobase_2, bmaddr_2, dev, &lun)) {
338 if (iobase_2 == IO_WD2)
339#ifdef __i386__
340 register_intr(irq2,(int)"",0,(inthand2_t *)ataintr,&bio_imask,lun);
341#endif
342#ifdef __alpha__
343 alpha_platform_setup_ide_intr(1, ataintr, (void *)(intptr_t)lun);
344#endif
345 else {
346 struct resource *irq;
347 int rid = 0;
348 void *ih;
349
350 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0,1,RF_ACTIVE);
351 if (!sysctrl)
352 bus_setup_intr(dev, irq, (driver_intr_t *)ataintr,
353 (void *)lun, &ih);
354 }
355 printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
356 lun, iobase_2, isa_apic_irq(irq2), unit);
357 }
358 return 0;
359}
360
361static device_method_t ata_pci_methods[] = {
362 /* Device interface */
363 DEVMETHOD(device_probe, ata_pciprobe),
364 DEVMETHOD(device_attach, ata_pciattach),
365 { 0, 0 }
366};
367
368static driver_t ata_pci_driver = {
369 "ata",
370 ata_pci_methods,
371 DRIVER_TYPE_BIO,
372 sizeof(int),
373};
374
375DRIVER_MODULE(ata, pci, ata_pci_driver, ata_devclass, 0, 0);
376
377static void
378promise_intr(int32_t unit)
379{
380 struct ata_softc *scp = atadevices[unit];
381 int32_t channel = inl((pci_read_config(scp->dev, 0x20, 4) & 0xfffc) + 0x1c);
382
383 if (channel & 0x00000400)
384 ataintr(unit);
385
386 if (channel & 0x00004000)
387 ataintr(unit+1);
388}
389#endif
390
391static int32_t
392ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr,
393 device_t dev, int32_t *unit)
394{
395 struct ata_softc *scp = atadevices[atanlun];
396 int32_t mask = 0;
397 int32_t timeout;
398 int32_t lun = atanlun;
399 u_int8_t status0, status1;
400
401#ifdef ATA_STATIC_ID

--- 130 unchanged lines hidden (view full) ---

532#endif
533 if (!scp->devices) {
534 free(scp, M_DEVBUF);
535 return 0;
536 }
537 bufq_init(&scp->ata_queue);
538 TAILQ_INIT(&scp->atapi_queue);
539 *unit = scp->lun;
540 scp->dev = dev;
541 if (bmaddr)
542 scp->bmaddr = bmaddr;
543 atadevices[scp->lun] = scp;
544#ifndef ATA_STATIC_ID
545 atanlun++;
546#endif
547 return ATA_IOSIZE;
548}
549
550static void
551ataintr(int32_t unit)
552{
553 struct ata_softc *scp;
554 struct atapi_request *atapi_request;

--- 207 unchanged lines hidden ---