edc_mca.c revision 1.6 1 /* $NetBSD: edc_mca.c,v 1.6 2001/04/23 06:10:08 jdolecek Exp $ */
2
3 /*
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Jaromir Dolecek.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the NetBSD
20 * Foundation, Inc. and its contributors.
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 /*
37 * Driver for MCA ESDI controllers and disks conforming to IBM DASD
38 * spec.
39 *
40 * The driver was written with DASD Storage Interface Specification
41 * for MCA rev. 2.2 in hands, thanks to Scott Telford <st (at) epcc.ed.ac.uk>.
42 *
43 * TODO:
44 * - finish support for kernel memory crash dump
45 * - move the MCA DMA controller (edc_setup_dma()) goo to device driver
46 * independant location
47 * - improve error recovery
48 * add any soft resets when anything gets stuck?
49 * - test with > 1 disk (this is supported by some controllers), eliminate
50 * any remaining devno=0 assumptions if there are any still
51 * - test with > 1 ESDI controller in machine; shared interrupts
52 * necessary for this to work should be supported - edc_intr() specifically
53 * checks if the interrupt is for this controller
54 */
55
56 #include "rnd.h"
57
58 #include <sys/param.h>
59 #include <sys/systm.h>
60 #include <sys/errno.h>
61 #include <sys/device.h>
62 #include <sys/malloc.h>
63 #include <sys/endian.h>
64 #include <sys/disklabel.h>
65 #include <sys/disk.h>
66 #include <sys/syslog.h>
67 #include <sys/proc.h>
68 #include <sys/vnode.h>
69 #include <sys/kernel.h>
70 #if NRND > 0
71 #include <sys/rnd.h>
72 #endif
73
74 #include <machine/bus.h>
75 #include <machine/intr.h>
76
77 #include <dev/mca/mcareg.h>
78 #include <dev/mca/mcavar.h>
79 #include <dev/mca/mcadevs.h>
80
81 #include <dev/mca/edcreg.h>
82 #include <dev/mca/edvar.h>
83 #include <dev/mca/edcvar.h>
84
85 #define DASD_MAXDEVS 7
86 struct edc_mca_softc {
87 struct device sc_dev;
88
89 bus_space_tag_t sc_iot;
90 bus_space_handle_t sc_ioh;
91
92 bus_dma_tag_t sc_dmat; /* DMA tag as passed by parent */
93 bus_space_handle_t sc_dmaextcmdh;
94 bus_space_handle_t sc_dmaexech;
95
96 void *sc_ih; /* interrupt handle */
97 int sc_drq; /* DRQ number */
98 int sc_cmd_async; /* asynchronous cmd pending */
99
100 int sc_flags;
101 #define DASD_QUIET 0x01 /* don't dump cmd error info */
102 struct ed_softc *sc_ed[DASD_MAXDEVS];
103
104 int sc_maxdevs; /* maximum # of devs supported by
105 * controller */
106 };
107
108 int edc_mca_probe __P((struct device *, struct cfdata *, void *));
109 void edc_mca_attach __P((struct device *, struct device *, void *));
110
111 struct cfattach edc_mca_ca = {
112 sizeof(struct edc_mca_softc), edc_mca_probe, edc_mca_attach
113 };
114
115 #define DMA_EXTCMD 0x18
116 #define DMA_EXEC 0x1A
117
118 static int edc_intr __P((void *));
119 static void edc_attach_ed __P((struct device *));
120 static void edc_dump_status_block __P((struct edc_mca_softc *, int, int));
121 static int edc_setup_dma __P((struct edc_mca_softc *, struct buf *,
122 bus_addr_t, bus_size_t));
123 static int edc_do_attn __P((struct edc_mca_softc *, int, int, int));
124
125 int
126 edc_mca_probe(parent, match, aux)
127 struct device *parent;
128 struct cfdata *match;
129 void *aux;
130 {
131 struct mca_attach_args *ma = aux;
132
133 switch (ma->ma_id) {
134 case MCA_PRODUCT_IBM_ESDIC:
135 case MCA_PRODUCT_IBM_ESDIC_IG:
136 return (1);
137 default:
138 return (0);
139 }
140 }
141
142 void
143 edc_mca_attach(parent, self, aux)
144 struct device *parent, *self;
145 void *aux;
146 {
147 struct edc_mca_softc *sc = (void *) self;
148 struct mca_attach_args *ma = aux;
149 int pos2, pos3, pos4;
150 int irq, drq, iobase;
151 const char *typestr;
152
153 pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2);
154 pos3 = mca_conf_read(ma->ma_mc, ma->ma_slot, 3);
155 pos4 = mca_conf_read(ma->ma_mc, ma->ma_slot, 4);
156
157 /*
158 * POS register 2: (adf pos0)
159 *
160 * 7 6 5 4 3 2 1 0
161 * \ \____/ \ \__ enable: 0=adapter disabled, 1=adapter enabled
162 * \ \ \___ Primary/Alternate Port Adresses:
163 * \ \ 0=0x3510-3517 1=0x3518-0x351f
164 * \ \_____ DMA Arbitration Level: 0101=5 0110=6 0111=7
165 * \ 0000=0 0001=1 0011=3 0100=4
166 * \_________ Fairness On/Off: 1=On 0=Off
167 *
168 * POS register 3: (adf pos1)
169 *
170 * 7 6 5 4 3 2 1 0
171 * 0 0 \_/
172 * \__________ DMA Burst Pacing Interval: 10=24ms 11=31ms
173 * 01=16ms 00=Burst Disabled
174 *
175 * POS register 4: (adf pos2)
176 *
177 * 7 6 5 4 3 2 1 0
178 * \_/ \__ DMA Pacing Control: 1=Disabled 0=Enabled
179 * \____ Time to Release: 1X=6ms 01=3ms 00=Immediate
180 *
181 * IRQ is fixed to 14 (0x0e).
182 */
183
184 switch (ma->ma_id) {
185 case MCA_PRODUCT_IBM_ESDIC:
186 typestr = "IBM ESDI Fixed Disk Controller";
187 break;
188 case MCA_PRODUCT_IBM_ESDIC_IG:
189 typestr = "IBM Integ. ESDI Fixed Disk & Controller";
190 break;
191 default:
192 /* never reached */
193 }
194
195 irq = ESDIC_IRQ;
196 iobase = (pos2 & IO_IS_ALT) ? ESDIC_IOALT : ESDIC_IOPRM;
197 drq = (pos2 & DRQ_MASK) >> 2;
198
199 printf(" slot %d irq %d: %s\n", ma->ma_slot+1, irq, typestr);
200
201 #ifdef DIAGNOSTIC
202 /*
203 * It's not strictly necessary to check this, machine configuration
204 * utility uses only valid adresses.
205 */
206 if (drq == 2 || drq >= 8) {
207 printf("%s: invalid DMA Arbitration Level %d\n",
208 sc->sc_dev.dv_xname, drq);
209 return;
210 }
211 #endif
212
213 printf("%s: Fairness %s, Release %s, DRQ %d, ",
214 sc->sc_dev.dv_xname,
215 (pos2 & FAIRNESS_ENABLE) ? "On" : "Off",
216 (pos4 & RELEASE_1) ? "6ms"
217 : ((pos4 & RELEASE_2) ? "3ms" : "Immediate"),
218 drq);
219 if ((pos4 & PACING_CTRL_DISABLE) == 0) {
220 static const char * const pacint[] =
221 { "disabled", "16ms", "24ms", "31ms"};
222 printf("DMA burst pacing interval %s\n",
223 pacint[(pos3 & PACING_INT_MASK) >> 4]);
224 } else
225 printf("DMA pacing control disabled\n");
226
227 sc->sc_iot = ma->ma_iot;
228 sc->sc_drq = drq;
229
230 if (bus_space_map(sc->sc_iot, iobase,
231 ESDIC_REG_NPORTS, 0, &sc->sc_ioh)) {
232 printf("%s: couldn't map registers\n",
233 sc->sc_dev.dv_xname);
234 return;
235 }
236
237 if (bus_space_map(sc->sc_iot, DMA_EXTCMD, 1, 0, &sc->sc_dmaextcmdh)) {
238 printf("%s: couldn't map registers\n",
239 sc->sc_dev.dv_xname);
240 return;
241 }
242 if (bus_space_map(sc->sc_iot, DMA_EXEC, 1, 0, &sc->sc_dmaexech)) {
243 printf("%s: couldn't map registers\n",
244 sc->sc_dev.dv_xname);
245 return;
246 }
247
248 sc->sc_dmat = ma->ma_dmat;
249
250 sc->sc_ih = mca_intr_establish(ma->ma_mc, irq, IPL_BIO, edc_intr, sc);
251 if (sc->sc_ih == NULL) {
252 printf("%s: couldn't establish interrupt handler\n",
253 sc->sc_dev.dv_xname);
254 return;
255 }
256
257 /*
258 * Integrated ESDI controller supports only one disk, other
259 * controllers support two disks.
260 */
261 if (ma->ma_id == MCA_PRODUCT_IBM_ESDIC_IG)
262 sc->sc_maxdevs = 1;
263 else
264 sc->sc_maxdevs = 2;
265
266 /* Defer probe for individual disks until interrupts are enabled. */
267 config_interrupts(self, edc_attach_ed);
268 }
269
270 /*
271 * Try to attach ed* at edc? if any configured and installed now
272 * that interrupts are enabled.
273 */
274 static void
275 edc_attach_ed(self)
276 struct device *self;
277 {
278 struct edc_mca_softc *sc = (void *) self;
279 struct ed_softc *ed;
280 struct ed_attach_args eda;
281 int devno;
282
283 /* Do a reset to ensure sane state after warm boot. */
284 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_BUSY) {
285 /* hard reset */
286 printf("%s: controller busy, performing hardware reset ...\n",
287 sc->sc_dev.dv_xname);
288 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR,
289 BCR_INT_ENABLE|BCR_RESET);
290 } else {
291 /* "SOFT" reset */
292 edc_do_attn(sc, ATN_RESET_ATTACHMENT, DASD_DEVNO_CONTROLLER,0);
293 }
294
295 /* Wait until the reset completes. */
296 while(bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_BUSY)
297 delay(1);
298
299 /*
300 * Get dummy ed_softc to be used during probe. Once a disk is
301 * found, ed_mca_attach() calls edc_add_disk() to insert the
302 * right pointer into sc->sc_ed[] array.
303 */
304 MALLOC(ed, struct ed_softc *, sizeof(struct ed_softc),
305 M_TEMP, M_WAITOK);
306
307 /* be quiet duting probes */
308 sc->sc_flags |= DASD_QUIET;
309
310 /* check for attached disks */
311 for(devno=0; devno < sc->sc_maxdevs; devno++) {
312 eda.sc_devno = devno;
313 eda.sc_dmat = sc->sc_dmat;
314 sc->sc_ed[devno] = ed;
315 sc->sc_ed[devno] =
316 (void *) config_found_sm(self, &eda, NULL, NULL);
317 }
318
319 /* enable full error dumps again */
320 sc->sc_flags &= ~DASD_QUIET;
321
322 /* cleanup */
323 FREE(ed, M_TEMP);
324
325 /* XXX disestablish interrupt if no disks found ? */
326 }
327
328 void
329 edc_add_disk(sc, ed, devno)
330 struct edc_mca_softc *sc;
331 struct ed_softc *ed;
332 int devno;
333 {
334 sc->sc_ed[devno] = ed;
335 }
336
337 static int
338 edc_intr(arg)
339 void *arg;
340 {
341 struct edc_mca_softc *sc = arg;
342 u_int8_t isr, intr_id;
343 u_int16_t sifr;
344 int cmd=-1, devno, bioerror=0;
345 struct ed_softc *ed=NULL;
346
347 /*
348 * Check if the interrupt was for us.
349 */
350 if ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_INTR) == 0)
351 return (0);
352
353 /*
354 * Read ISR to find out interrupt type. This also clears the interrupt
355 * condition and BSR_INTR flag. Accordings to docs interrupt ID of 0, 2
356 * and 4 are reserved and not used.
357 */
358 isr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ISR);
359 intr_id = isr & ISR_INTR_ID_MASK;
360
361 #ifdef DEBUG
362 if (intr_id == 0 || intr_id == 2 || intr_id == 4) {
363 printf("%s: bogus interrupt id %d\n", sc->sc_dev.dv_xname,
364 (int) intr_id);
365 return (0);
366 }
367 #endif
368
369 /* Get number of device whose intr this was */
370 devno = (isr & 0xe0) >> 5;
371
372 /*
373 * Get Status block. Higher byte always says how long the status
374 * block is, rest is device number and command code.
375 * Check the status block length against our supported maximum length
376 * and fetch the data.
377 */
378 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh,BSR) & BSR_SIFR_FULL
379 && intr_id != ISR_RESET_COMPLETED) {
380 size_t len;
381 int i;
382
383 sifr = le16toh(bus_space_read_2(sc->sc_iot, sc->sc_ioh, SIFR));
384 len = (sifr & 0xff00) >> 8;
385 if (len > DASD_MAX_CMD_RES_LEN) {
386 printf("%s: maximum Status Length exceeded: %d > %d\n",
387 sc->sc_dev.dv_xname,
388 len, DASD_MAX_CMD_RES_LEN);
389 goto attn_eoi;
390 }
391
392 /* Get command code */
393 cmd = sifr & SIFR_CMD_MASK;
394
395 /* Read whole status block */
396 ed = sc->sc_ed[devno];
397 ed->sc_status_block[0] = sifr;
398 for(i=1; i < len; i++) {
399 while((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR)
400 & BSR_SIFR_FULL) == 0)
401 delay(1);
402
403 ed->sc_status_block[i] = le16toh(
404 bus_space_read_2(sc->sc_iot, sc->sc_ioh, SIFR));
405 }
406 }
407
408 switch (intr_id) {
409 case ISR_DATA_TRANSFER_RDY:
410 /*
411 * Ready to do DMA, setup DMA controller and kick DASD
412 * controller to do the transfer.
413 */
414 ed = sc->sc_ed[devno];
415 if (!edc_setup_dma(sc, ed->sc_bp,
416 ed->dmamap_xfer->dm_segs[0].ds_addr,
417 ed->dmamap_xfer->dm_segs[0].ds_len)) {
418 /* XXX bail out? */
419 printf("%s: edc_setup_dma() failed\n",
420 ed->sc_dev.dv_xname);
421 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR,
422 BCR_INT_ENABLE);
423 } else {
424 /* OK, proceed with DMA */
425 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR,
426 BCR_INT_ENABLE|BCR_DMA_ENABLE);
427 }
428 break;
429 case ISR_COMPLETED:
430 case ISR_COMPLETED_WITH_ECC:
431 case ISR_COMPLETED_RETRIES:
432 case ISR_COMPLETED_WARNING:
433 bioerror = 0;
434 break;
435 case ISR_RESET_COMPLETED:
436 case ISR_ABORT_COMPLETED:
437 /* nothing to do */
438 break;
439 default:
440 if ((sc->sc_flags & DASD_QUIET) == 0)
441 edc_dump_status_block(sc, devno, intr_id);
442
443 bioerror = EIO;
444 break;
445 }
446
447 attn_eoi:
448 /*
449 * Unless the interrupt is for Data Transfer Ready or
450 * Attention Error, finish by assertion EOI. This makes
451 * attachment aware the interrupt is processed and system
452 * is ready to accept another one.
453 */
454 if (intr_id != ISR_DATA_TRANSFER_RDY && intr_id != ISR_ATTN_ERROR)
455 edc_do_attn(sc, ATN_END_INT, devno, intr_id);
456
457 /* If Read or Write Data, wakeup worker thread to finish it */
458 if (intr_id != ISR_DATA_TRANSFER_RDY
459 && (cmd == CMD_READ_DATA || cmd == CMD_WRITE_DATA)) {
460 sc->sc_ed[devno]->sc_error = bioerror;
461 sc->sc_ed[devno]->sc_flags |= EDF_IODONE;
462 wakeup_one(&sc->sc_ed[devno]->edc_softc);
463 }
464
465 return (1);
466 }
467
468 /*
469 * This follows the exact order for Attention Request as
470 * written in DASD Storage Interface Specification MC (Rev 2.2).
471 */
472 static int
473 edc_do_attn(sc, attn_type, devno, intr_id)
474 struct edc_mca_softc *sc;
475 int attn_type, devno, intr_id;
476 {
477 int tries;
478
479 /* 1. Disable interrupts in BCR. */
480 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR, 0);
481
482 /* 2. Assure NOT BUSY and NO INTERRUPT PENDING, unless acknowledging
483 * a RESET COMPLETED interrupt. */
484 if (intr_id != ISR_RESET_COMPLETED) {
485 for(tries=0; tries < 1000; tries++) {
486 if ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR)
487 & (BSR_INT_PENDING|BSR_BUSY)) == 0)
488 break;
489 }
490
491 if (tries == 1000) {
492 printf("%s: edc_do_attn: timeout waiting for attachment to become available\n",
493 (devno == DASD_DEVNO_CONTROLLER)
494 ? sc->sc_dev.dv_xname
495 : sc->sc_ed[devno]->sc_dev.dv_xname);
496 return (EAGAIN);
497 }
498 }
499
500 /*
501 * 3. Write proper DEVICE NUMBER and Attention number to ATN.
502 */
503 bus_space_write_1(sc->sc_iot, sc->sc_ioh, ATN,
504 attn_type | (devno << 5));
505
506 /*
507 * 4. Enable interrupts via BCR.
508 */
509 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR, BCR_INT_ENABLE);
510
511 return (0);
512 }
513
514 /*
515 * Wait until command is processed, timeout after 'secs' seconds.
516 * We use mono_time, since we don't need actual RTC, just time
517 * interval.
518 */
519 int
520 edc_cmd_wait(sc, devno, secs)
521 struct edc_mca_softc *sc;
522 int devno, secs;
523 {
524 struct timeval start, now;
525 int s;
526
527 s = splclock();
528 start = mono_time;
529 splx(s);
530
531 while((bus_space_read_1(sc->sc_iot,sc->sc_ioh,BSR)&BSR_CMD_INPROGRESS)){
532 s = splclock();
533 now = mono_time;
534 splx(s);
535 if (now.tv_sec - start.tv_sec > secs)
536 break;
537
538 delay(1);
539 }
540
541 if (now.tv_sec - start.tv_sec >= secs &&
542 bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_CMD_INPROGRESS){
543 printf("%s: timed out waiting for previous cmd to finish\n",
544 sc->sc_ed[devno]->sc_dev.dv_xname);
545 return (EAGAIN);
546 }
547
548 return (0);
549 }
550
551 int
552 edc_run_cmd(sc, cmd, devno, cmd_args, cmd_len, async)
553 struct edc_mca_softc *sc;
554 int cmd;
555 int devno;
556 u_int16_t cmd_args[];
557 int cmd_len;
558 int async;
559 {
560 int i, error;
561 u_int16_t cmd0;
562
563 /*
564 * If there has been an asynchronous command executed, first wait for it
565 * to finish.
566 */
567 if (sc->sc_cmd_async) {
568 /* Wait maximum 15s */
569 if (edc_cmd_wait(sc, devno, 15))
570 return (EAGAIN); /* Busy */
571
572 sc->sc_cmd_async = 0;
573 }
574
575 /* Do Attention Request for Command Request. */
576 if ((error = edc_do_attn(sc, ATN_CMD_REQ, devno, 0)))
577 return (error);
578
579 /*
580 * Construct the command. The bits are like this:
581 *
582 * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
583 * \_/ 0 0 1 0 \__/ \_____/
584 * \ \__________/ \ \_ Command Code (see CMD_*)
585 * \ \ \__ Device: 0 common, 7 controller
586 * \ \__ Options: reserved, bit 10=cache bypass bit
587 * \_ Type: 00=2B, 01=4B, 10 and 11 reserved
588 *
589 * We always use device 0 or 1, so difference is made only by Command
590 * Code, Command Options and command length.
591 */
592 cmd0 = ((cmd_len == 4) ? (CIFR_LONG_CMD) : 0)
593 | (devno << 5)
594 | (cmd_args[0] << 8) | cmd;
595 cmd_args[0] = cmd0;
596
597 /*
598 * Write word of CMD to the CIFR. This sets "Command
599 * Interface Register Full (CMD IN)" in BSR. Once the attachment
600 * detects it, it reads the word and clears CMD IN.
601 */
602 for(i=0; i < cmd_len; i++) {
603 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CIFR,
604 htole16(cmd_args[i]));
605
606 /* wait until CMD IN is cleared */
607 while(bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_CIFR_FULL)
608 delay(1);
609 }
610
611 /*
612 * Attachment is now executing the command. Unless we are executing
613 * command asynchronously, wait until it finishes.
614 */
615 if (async) {
616 sc->sc_cmd_async = 1;
617 return (0);
618 }
619
620 /* Wait for command to complete, but maximum 15 seconds. */
621 if (edc_cmd_wait(sc, devno, 15))
622 return (EAGAIN);
623
624 /* Check if the command completed successfully; if not, return error */
625 switch(SB_GET_CMD_STATUS(sc->sc_ed[devno]->sc_status_block)) {
626 case ISR_COMPLETED:
627 case ISR_COMPLETED_WITH_ECC:
628 case ISR_COMPLETED_RETRIES:
629 case ISR_COMPLETED_WARNING:
630 return (0);
631 default:
632 return (EIO);
633 }
634 }
635
636 static int
637 edc_setup_dma(sc, bp, phys, cnt)
638 struct edc_mca_softc *sc;
639 struct buf *bp;
640 bus_addr_t phys;
641 bus_size_t cnt;
642 {
643 /* XXX magic constants, should be moved to device-independant location*/
644 /* The exact sequence to setup MCA DMA controller is taken from Minix */
645
646 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0,
647 0x90 + sc->sc_drq);
648 /* Disable access to dma channel */
649 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0,
650 0x20 + sc->sc_drq);
651 /* Clear the address byte pointer */
652 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
653 (phys >> 0) & 0xff); /* address bits 0..7 */
654 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
655 (phys >> 8) & 0xff); /* address bits 8..15 */
656 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
657 (phys >> 16) & 0xff); /* address bits 16..23 */
658 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0,
659 0x40 + sc->sc_drq);
660 /* Clear the count byte pointer */
661 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
662 ((cnt - 1) >> 0) & 0xff); /* count bits 0..7 */
663 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
664 ((cnt - 1) >> 8) & 0xff); /* count bits 8..15 */
665 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0,
666 0x70 + sc->sc_drq);
667 /* Set the transfer mode */
668 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
669 (bp->b_flags & B_READ) ? 0x4C : 0x44);
670 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0,
671 0xA0 + sc->sc_drq);
672 /* Enable access to dma channel */
673
674 return (1);
675 }
676
677 static const char * const edc_commands[] = {
678 "Invalid Command",
679 "Read Data",
680 "Write Data",
681 "Read Verify",
682 "Write with Verify",
683 "Seek",
684 "Park Head",
685 "Get Command Complete Status",
686 "Get Device Status",
687 "Get Device Configuration",
688 "Get POS Information",
689 "Translate RBA",
690 "Write Attachment Buffer",
691 "Read Attachment Buffer",
692 "Run Diagnostic Test",
693 "Get Diagnostic Status Block",
694 "Get MFG Header",
695 "Format Unit",
696 "Format Prepare",
697 "Set MAX RBA",
698 "Set Power Saving Mode",
699 "Power Conservation Command",
700 };
701
702 static const char * const edc_cmd_status[256] = {
703 "Reserved",
704 "Command completed successfully",
705 "Reserved",
706 "Command completed successfully with ECC applied",
707 "Reserved",
708 "Command completed successfully with retries",
709 "Format Command partially completed", /* Status available */
710 "Command completed successfully with ECC and retries",
711 "Command completed with Warning", /* Command Error is available */
712 "Aborted",
713 "Reset completed",
714 "Data Transfer Ready", /* No Status Block available */
715 "Command terminated with failure", /* Device Error is available */
716 "DMA Error", /* Retry entire command as recovery */
717 "Command Block Error",
718 "Attention Error (Illegal Attention Code)",
719 /* 0x14 - 0xff reserved */
720 };
721
722 static const char * const edc_cmd_error[256] = {
723 "No Error",
724 "Invalid parameter in the command block",
725 "Reserved",
726 "Command not supported",
727 "Command Aborted per request",
728 "Reserved",
729 "Command rejected", /* Attachment diagnostic failure */
730 "Format Rejected", /* Prepare Format command is required */
731 "Format Error (Primary Map is not readable)",
732 "Format Error (Secondary map is not readable)",
733 "Format Error (Diagnostic Failure)",
734 "Format Warning (Secondary Map Overflow)",
735 "Reserved"
736 "Format Error (Host Checksum Error)",
737 "Reserved",
738 "Format Warning (Push table overflow)",
739 "Format Warning (More pushes than allowed)",
740 "Reserved",
741 "Format Warning (Error during verifying)",
742 "Invalid device number for the command",
743 /* 0x14-0xff reserved */
744 };
745
746 static const char * const edc_dev_errors[] = {
747 "No Error",
748 "Seek Fault", /* Device report */
749 "Interface Fault (Parity, Attn, or Cmd Complete Error)",
750 "Block not found (ID not found)",
751 "Block not found (AM not found)",
752 "Data ECC Error (hard error)",
753 "ID CRC Error",
754 "RBA Out of Range",
755 "Reserved",
756 "Defective Block",
757 "Reserved",
758 "Selection Error",
759 "Reserved",
760 "Write Fault",
761 "No index or sector pulse",
762 "Device Not Ready",
763 "Seek Error", /* Attachment report */
764 "Bad Format",
765 "Volume Overflow",
766 "No Data AM Found",
767 "Block not found (No ID AM or ID CRC error occured)",
768 "Reserved",
769 "Reserved",
770 "No ID found on track (ID search)",
771 /* 0x19 - 0xff reserved */
772 };
773
774 static void
775 edc_dump_status_block(sc, devno, intr_id)
776 struct edc_mca_softc *sc;
777 int devno, intr_id;
778 {
779 struct ed_softc *ed = sc->sc_ed[devno];
780 printf("%s: Command: %s, Status: %s\n",
781 ed->sc_dev.dv_xname,
782 edc_commands[ed->sc_status_block[0] & 0x1f],
783 edc_cmd_status[SB_GET_CMD_STATUS(ed->sc_status_block)]
784 );
785 printf("%s: # left blocks: %u, last processed RBA: %u\n",
786 ed->sc_dev.dv_xname,
787 ed->sc_status_block[SB_RESBLKCNT_IDX],
788 (ed->sc_status_block[5] << 16) | ed->sc_status_block[4]);
789
790 if (intr_id == ISR_COMPLETED_WARNING) {
791 printf("%s: Command Error Code: %s\n",
792 ed->sc_dev.dv_xname,
793 edc_cmd_error[ed->sc_status_block[1] & 0xff]);
794 }
795
796 if (intr_id == ISR_CMD_FAILED) {
797 char buf[100];
798
799 printf("%s: Device Error Code: %s\n",
800 ed->sc_dev.dv_xname,
801 edc_dev_errors[ed->sc_status_block[2] & 0xff]);
802 bitmask_snprintf((ed->sc_status_block[2] & 0xff00) >> 8,
803 "\20"
804 "\01SeekOrCmdComplete"
805 "\02Track0Flag"
806 "\03WriteFault"
807 "\04Selected"
808 "\05Ready"
809 "\06Reserved0"
810 "\07STANDBY"
811 "\010Reserved0",
812 buf, sizeof(buf));
813 printf("%s: Device Status: %s\n",
814 ed->sc_dev.dv_xname, buf);
815 }
816 }
817