edc_mca.c revision 1.2 1 /* $NetBSD: edc_mca.c,v 1.2 2001/04/22 11:32:49 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
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 printf(" slot %d: %s\n", ma->ma_slot+1, typestr);
196
197 irq = ESDIC_IRQ;
198 iobase = (pos2 & IO_IS_ALT) ? ESDIC_IOALT : ESDIC_IOPRM;
199 drq = (pos2 & DRQ_MASK) >> 2;
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 printf("%s: interrupting at irq %d\n", sc->sc_dev.dv_xname, irq);
257
258 /*
259 * Integrated ESDI controller supports only one disk, other
260 * controllers support two disks.
261 */
262 if (ma->ma_id == MCA_PRODUCT_IBM_ESDIC_IG)
263 sc->sc_maxdevs = 1;
264 else
265 sc->sc_maxdevs = 2;
266
267 /* Defer probe for individual disks until interrupts are enabled. */
268 config_interrupts(self, edc_attach_ed);
269 }
270
271 /*
272 * Try to attach ed* at edc? if any configured and installed now
273 * that interrupts are enabled.
274 */
275 static void
276 edc_attach_ed(self)
277 struct device *self;
278 {
279 struct edc_mca_softc *sc = (void *) self;
280 struct ed_softc *ed;
281 struct ed_attach_args eda;
282 int devno;
283
284 /* Do a reset to ensure sane state after warm boot. */
285 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_BUSY) {
286 /* hard reset */
287 printf("%s: controller busy, performing hardware reset ...\n",
288 sc->sc_dev.dv_xname);
289 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR,
290 BCR_INT_ENABLE|BCR_RESET);
291 } else {
292 /* "SOFT" reset */
293 edc_do_attn(sc, ATN_RESET_ATTACHMENT, DASD_DEVNO_CONTROLLER,0);
294 }
295
296 /* Wait until the reset completes. */
297 while(bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_BUSY)
298 delay(1);
299
300 /*
301 * Get dummy ed_softc to be used during probe. Once a disk is
302 * found, ed_mca_attach() calls edc_add_disk() to insert the
303 * right pointer into sc->sc_ed[] array.
304 */
305 MALLOC(ed, struct ed_softc *, sizeof(struct ed_softc),
306 M_TEMP, M_WAITOK);
307
308 /* be quiet duting probes */
309 sc->sc_flags |= DASD_QUIET;
310
311 /* check for attached disks */
312 for(devno=0; devno < sc->sc_maxdevs; devno++) {
313 eda.sc_devno = devno;
314 eda.sc_dmat = sc->sc_dmat;
315 sc->sc_ed[devno] = ed;
316 sc->sc_ed[devno] =
317 (void *) config_found_sm(self, &eda, NULL, NULL);
318 }
319
320 /* enable full error dumps again */
321 sc->sc_flags &= ~DASD_QUIET;
322
323 /* cleanup */
324 FREE(ed, M_TEMP);
325
326 /* XXX disestablish interrupt if no disks found ? */
327 }
328
329 void
330 edc_add_disk(sc, ed, devno)
331 struct edc_mca_softc *sc;
332 struct ed_softc *ed;
333 int devno;
334 {
335 sc->sc_ed[devno] = ed;
336 }
337
338 static int
339 edc_intr(arg)
340 void *arg;
341 {
342 struct edc_mca_softc *sc = arg;
343 u_int8_t isr, intr_id;
344 u_int16_t sifr;
345 int cmd=-1, devno, bioerror=0;
346 struct ed_softc *ed=NULL;
347
348 /*
349 * Check if the interrupt was for us.
350 */
351 if ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_INTR) == 0)
352 return (0);
353
354 /*
355 * Read ISR to find out interrupt type. This also clears the interrupt
356 * condition and BSR_INTR flag. Accordings to docs interrupt ID of 0, 2
357 * and 4 are reserved and not used.
358 */
359 isr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ISR);
360 intr_id = isr & ISR_INTR_ID_MASK;
361
362 #ifdef DEBUG
363 if (intr_id == 0 || intr_id == 2 || intr_id == 4) {
364 printf("%s: bogus interrupt id %d\n", sc->sc_dev.dv_xname,
365 (int) intr_id);
366 return (0);
367 }
368 #endif
369
370 /* Get number of device whose intr this was */
371 devno = (isr & 0xe0) >> 5;
372
373 /*
374 * Get Status block. Higher byte always says how long the status
375 * block is, rest is device number and command code.
376 * Check the status block length against our supported maximum length
377 * and fetch the data.
378 */
379 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh,BSR) & BSR_SIFR_FULL
380 && intr_id != ISR_RESET_COMPLETED) {
381 size_t len;
382 int i;
383
384 sifr = le16toh(bus_space_read_2(sc->sc_iot, sc->sc_ioh, SIFR));
385 len = (sifr & 0xff00) >> 8;
386 if (len > DASD_MAX_CMD_RES_LEN) {
387 printf("%s: maximum Status Length exceeded: %d > %d\n",
388 sc->sc_dev.dv_xname,
389 len, DASD_MAX_CMD_RES_LEN);
390 goto attn_eoi;
391 }
392
393 /* Get command code */
394 cmd = sifr & SIFR_CMD_MASK;
395
396 /* Read whole status block */
397 ed = sc->sc_ed[devno];
398 ed->sc_status_block[0] = sifr;
399 for(i=1; i < len; i++) {
400 while((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR)
401 & BSR_SIFR_FULL) == 0)
402 delay(1);
403
404 ed->sc_status_block[i] = le16toh(
405 bus_space_read_2(sc->sc_iot, sc->sc_ioh, SIFR));
406 }
407 }
408
409 switch (intr_id) {
410 case ISR_DATA_TRANSFER_RDY:
411 /*
412 * Ready to do DMA, setup DMA controller and kick DASD
413 * controller to do the transfer.
414 */
415 ed = sc->sc_ed[devno];
416 if (!edc_setup_dma(sc, ed->sc_bp,
417 ed->dmamap_xfer->dm_segs[0].ds_addr,
418 ed->dmamap_xfer->dm_segs[0].ds_len)) {
419 /* XXX bail out? */
420 printf("%s: edc_setup_dma() failed\n",
421 ed->sc_dev.dv_xname);
422 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR,
423 BCR_INT_ENABLE);
424 } else {
425 /* OK, proceed with DMA */
426 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR,
427 BCR_INT_ENABLE|BCR_DMA_ENABLE);
428 }
429 break;
430 case ISR_COMPLETED:
431 case ISR_COMPLETED_WITH_ECC:
432 case ISR_COMPLETED_RETRIES:
433 case ISR_COMPLETED_WARNING:
434 bioerror = 0;
435 break;
436 case ISR_RESET_COMPLETED:
437 case ISR_ABORT_COMPLETED:
438 /* nothing to do */
439 break;
440 default:
441 if ((sc->sc_flags & DASD_QUIET) == 0)
442 edc_dump_status_block(sc, devno, cmd, intr_id);
443
444 bioerror = EIO;
445 break;
446 }
447
448 attn_eoi:
449 /*
450 * Unless the interrupt is for Data Transfer Ready or
451 * Attention Error, finish by assertion EOI. This makes
452 * attachment aware the interrupt is processed and system
453 * is ready to accept another one.
454 */
455 if (intr_id != ISR_DATA_TRANSFER_RDY && intr_id != ISR_ATTN_ERROR)
456 edc_do_attn(sc, ATN_END_INT, devno, intr_id);
457
458 /* If Read or Write Data, wakeup worker thread to finish it */
459 if (intr_id != ISR_DATA_TRANSFER_RDY
460 && (cmd == CMD_READ_DATA || cmd == CMD_WRITE_DATA)) {
461 sc->sc_ed[devno]->sc_error = bioerror;
462 sc->sc_ed[devno]->sc_flags |= EDF_IODONE;
463 wakeup_one(&sc->sc_ed[devno]->edc_softc);
464 }
465
466 return (1);
467 }
468
469 /*
470 * This follows the exact order for Attention Request as
471 * written in DASD Storage Interface Specification MC (Rev 2.2).
472 */
473 static int
474 edc_do_attn(sc, attn_type, devno, intr_id)
475 struct edc_mca_softc *sc;
476 int attn_type, devno, intr_id;
477 {
478 int tries;
479
480 /* 1. Disable interrupts in BCR. */
481 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR, 0);
482
483 /* 2. Assure NOT BUSY and NO INTERRUPT PENDING, unless acknowledging
484 * a RESET COMPLETED interrupt. */
485 if (intr_id != ISR_RESET_COMPLETED) {
486 for(tries=0; tries < 1000; tries++) {
487 if ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR)
488 & (BSR_INT_PENDING|BSR_BUSY)) == 0)
489 break;
490 }
491
492 if (tries == 1000) {
493 printf("%s: edc_do_attn: timeout waiting for attachment to become available\n",
494 (devno == DASD_DEVNO_CONTROLLER)
495 ? sc->sc_dev.dv_xname
496 : sc->sc_ed[devno]->sc_dev.dv_xname);
497 return (EAGAIN);
498 }
499 }
500
501 /*
502 * 3. Write proper DEVICE NUMBER and Attention number to ATN.
503 */
504 bus_space_write_1(sc->sc_iot, sc->sc_ioh, ATN,
505 attn_type | (devno << 5));
506
507 /*
508 * 4. Enable interrupts via BCR.
509 */
510 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR, BCR_INT_ENABLE);
511
512 return (0);
513 }
514
515 /*
516 * Wait until command is processed, timeout after 'secs' seconds.
517 * We use mono_time, since we don't need actual RTC, just time
518 * interval.
519 */
520 int
521 edc_cmd_wait(sc, devno, secs)
522 struct edc_mca_softc *sc;
523 int devno, secs;
524 {
525 struct timeval start, now;
526 int s;
527
528 s = splclock();
529 start = mono_time;
530 splx(s);
531
532 while((bus_space_read_1(sc->sc_iot,sc->sc_ioh,BSR)&BSR_CMD_INPROGRESS)){
533 s = splclock();
534 now = mono_time;
535 splx(s);
536 if (now.tv_sec - start.tv_sec > secs)
537 break;
538
539 delay(1);
540 }
541
542 if (now.tv_sec - start.tv_sec >= secs &&
543 bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_CMD_INPROGRESS){
544 printf("%s: timed out waiting for previous cmd to finish\n",
545 sc->sc_ed[devno]->sc_dev.dv_xname);
546 return (EAGAIN);
547 }
548
549 return (0);
550 }
551
552 int
553 edc_run_cmd(sc, cmd, devno, cmd_args, cmd_len, async)
554 struct edc_mca_softc *sc;
555 int cmd;
556 int devno;
557 u_int16_t cmd_args[];
558 int cmd_len;
559 int async;
560 {
561 int i, error;
562 u_int16_t cmd0;
563
564 /*
565 * If there has been an asynchronous command executed, first wait for it
566 * to finish.
567 */
568 if (sc->sc_cmd_async) {
569 /* Wait maximum 15s */
570 if (edc_cmd_wait(sc, devno, 15))
571 return (EAGAIN); /* Busy */
572
573 sc->sc_cmd_async = 0;
574 }
575
576 /* Do Attention Request for Command Request. */
577 if ((error = edc_do_attn(sc, ATN_CMD_REQ, devno, 0)))
578 return (error);
579
580 /*
581 * Construct the command. The bits are like this:
582 *
583 * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
584 * \_/ 0 0 1 0 \__/ \_____/
585 * \ \__________/ \ \_ Command Code (see CMD_*)
586 * \ \ \__ Device: 0 common, 7 controller
587 * \ \__ Options: reserved, bit 10=cache bypass bit
588 * \_ Type: 00=2B, 01=4B, 10 and 11 reserved
589 *
590 * We always use device 0 or 1, so difference is made only by Command
591 * Code, Command Options and command length.
592 */
593 cmd0 = ((cmd_len == 4) ? (CIFR_LONG_CMD) : 0)
594 | (devno << 5)
595 | (cmd_args[0] << 8) | cmd;
596 cmd_args[0] = cmd0;
597
598 /*
599 * Write word of CMD to the CIFR. This sets "Command
600 * Interface Register Full (CMD IN)" in BSR. Once the attachment
601 * detects it, it reads the word and clears CMD IN.
602 */
603 for(i=0; i < cmd_len; i++) {
604 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CIFR,
605 htole16(cmd_args[i]));
606
607 /* wait until CMD IN is cleared */
608 while(bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_CIFR_FULL)
609 delay(1);
610 }
611
612 /*
613 * Attachment is now executing the command. Unless we are executing
614 * command asynchronously, wait until it finishes.
615 */
616 if (async) {
617 sc->sc_cmd_async = 1;
618 return (0);
619 }
620
621 /* Wait for command to complete, but maximum 15 seconds. */
622 if (edc_cmd_wait(sc, devno, 15))
623 return (EAGAIN);
624
625 /* Check if the command completed successfully; if not, return error */
626 switch(SB_GET_CMD_STATUS(sc->sc_ed[devno]->sc_status_block)) {
627 case ISR_COMPLETED:
628 case ISR_COMPLETED_WITH_ECC:
629 case ISR_COMPLETED_RETRIES:
630 case ISR_COMPLETED_WARNING:
631 return (0);
632 default:
633 return (EIO);
634 }
635 }
636
637 static int
638 edc_setup_dma(sc, bp, phys, cnt)
639 struct edc_mca_softc *sc;
640 struct buf *bp;
641 bus_addr_t phys;
642 bus_size_t cnt;
643 {
644 /* XXX magic constants, should be moved to device-independant location*/
645 /* The exact sequence to setup MCA DMA controller is taken from Minix */
646
647 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0,
648 0x90 + sc->sc_drq);
649 /* Disable access to dma channel */
650 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0,
651 0x20 + sc->sc_drq);
652 /* Clear the address byte pointer */
653 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
654 (phys >> 0) & 0xff); /* address bits 0..7 */
655 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
656 (phys >> 8) & 0xff); /* address bits 8..15 */
657 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
658 (phys >> 16) & 0xff); /* address bits 16..23 */
659 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0,
660 0x40 + sc->sc_drq);
661 /* Clear the count byte pointer */
662 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
663 ((cnt - 1) >> 0) & 0xff); /* count bits 0..7 */
664 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
665 ((cnt - 1) >> 8) & 0xff); /* count bits 8..15 */
666 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0,
667 0x70 + sc->sc_drq);
668 /* Set the transfer mode */
669 bus_space_write_1(sc->sc_iot, sc->sc_dmaexech, 0,
670 (bp->b_flags & B_READ) ? 0x4C : 0x44);
671 bus_space_write_1(sc->sc_iot, sc->sc_dmaextcmdh, 0,
672 0xA0 + sc->sc_drq);
673 /* Enable access to dma channel */
674
675 return (1);
676 }
677
678 static const char * const edc_commands[] = {
679 "Invalid Command",
680 "Read Data",
681 "Write Data",
682 "Read Verify",
683 "Write with Verify",
684 "Seek",
685 "Park Head",
686 "Get Command Complete Status",
687 "Get Device Status",
688 "Get Device Configuration",
689 "Get POS Information",
690 "Translate RBA",
691 "Write Attachment Buffer",
692 "Read Attachment Buffer",
693 "Run Diagnostic Test",
694 "Get Diagnostic Status Block",
695 "Get MFG Header",
696 "Format Unit",
697 "Format Prepare",
698 "Set MAX RBA",
699 "Set Power Saving Mode",
700 "Power Conservation Command",
701 };
702
703 static const char * const edc_cmd_status[256] = {
704 "Reserved",
705 "Command completed successfully",
706 "Reserved",
707 "Command completed successfully with ECC applied",
708 "Reserved",
709 "Command completed successfully with retries",
710 "Format Command partially completed", /* Status available */
711 "Command completed successfully with ECC and retries",
712 "Command completed with Warning", /* Command Error is available */
713 "Aborted",
714 "Reset completed",
715 "Data Transfer Ready", /* No Status Block available */
716 "Command terminated with failure", /* Device Error is available */
717 "DMA Error", /* Retry entire command as recovery */
718 "Command Block Error",
719 "Attention Error (Illegal Attention Code)",
720 /* 0x14 - 0xff reserved */
721 };
722
723 static const char * const edc_cmd_error[256] = {
724 "No Error",
725 "Invalid parameter in the command block",
726 "Reserved",
727 "Command not supported",
728 "Command Aborted per request",
729 "Reserved",
730 "Command rejected", /* Attachment diagnostic failure */
731 "Format Rejected", /* Prepare Format command is required */
732 "Format Error (Primary Map is not readable)",
733 "Format Error (Secondary map is not readable)",
734 "Format Error (Diagnostic Failure)",
735 "Format Warning (Secondary Map Overflow)",
736 "Reserved"
737 "Format Error (Host Checksum Error)",
738 "Reserved",
739 "Format Warning (Push table overflow)",
740 "Format Warning (More pushes than allowed)",
741 "Reserved",
742 "Format Warning (Error during verifying)",
743 "Invalid device number for the command",
744 /* 0x14-0xff reserved */
745 };
746
747 static const char * const edc_dev_status[] = {
748 "Seek or Command complete",
749 "Track 0 Flag (emulated)",
750 "Write Fault (emulated)",
751 "Selected",
752 "Ready",
753 "Reserved (0)",
754 "STANDBY",
755 "Reserved (0)",
756 };
757
758 static const char * const edc_dev_errors[] = {
759 "No Error",
760 "Seek Fault", /* Device report */
761 "Interface Fault (Parity, Attn, or Cmd Complete Error)",
762 "Block not found (ID not found)",
763 "Block not found (AM not found)",
764 "Data ECC Error (hard error)",
765 "ID CRC Error",
766 "RBA Out of Range",
767 "Reserved",
768 "Defective Block",
769 "Reserved",
770 "Selection Error",
771 "Reserved",
772 "Write Fault",
773 "No index or sector pulse",
774 "Device Not Ready",
775 "Seek Error", /* Attachment report */
776 "Bad Format",
777 "Volume Overflow",
778 "No Data AM Found",
779 "(Block not found) No ID AM or ID CRC error occured",
780 "Reserved",
781 "Reserved",
782 "No ID found on track (ID search)",
783 /* 0x19 - 0xff reserved */
784 };
785
786 static void
787 edc_dump_status_block(sc, devno, cmd, intr_id)
788 struct edc_mca_softc *sc;
789 int devno, cmd, intr_id;
790 {
791 struct ed_softc *ed = sc->sc_ed[devno];
792 printf("%s: Command: %s, Status: %s\n",
793 ed->sc_dev.dv_xname,
794 edc_commands[ed->sc_status_block[0] & 0x1f],
795 edc_cmd_status[SB_GET_CMD_STATUS(ed->sc_status_block)]
796 );
797 printf("%s: IntrId: %s\n", ed->sc_dev.dv_xname,
798 edc_cmd_status[intr_id]);
799 printf("%s: # left blocks: %d, last processed RBA: %d\n",
800 ed->sc_dev.dv_xname,
801 ed->sc_status_block[SB_RESBLKCNT_IDX],
802 (ed->sc_status_block[4] << 16) | ed->sc_status_block[5]);
803
804 if (cmd == ISR_COMPLETED_WARNING) {
805 printf("%s: Command Error Code: %s\n",
806 ed->sc_dev.dv_xname,
807 edc_cmd_error[ed->sc_status_block[1] & 0xff]);
808 }
809
810 if (cmd == ISR_CMD_FAILED) {
811 printf("%s: Device: Status: %s, Error Code: %s\n",
812 ed->sc_dev.dv_xname,
813 edc_dev_status[(ed->sc_status_block[2] & 0xff00) >> 8],
814 edc_dev_errors[ed->sc_status_block[2] & 0xff]);
815 }
816 }
817