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