FreeBSD/Linux Kernel Cross Reference
sys/dev/mca/edc_mca.c
1 /* $NetBSD: edc_mca.c,v 1.23 2003/11/10 08:51:52 wiz 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@epcc.ed.ac.uk>.
42 *
43 * TODO:
44 * - improve error recovery
45 * Issue soft reset on error or timeout?
46 * - test with > 1 disk (this is supported by some controllers)
47 * - test with > 1 ESDI controller in machine; shared interrupts
48 * necessary for this to work should be supported - edc_intr() specifically
49 * checks if the interrupt is for this controller
50 */
51
52 #include <sys/cdefs.h>
53 __KERNEL_RCSID(0, "$NetBSD: edc_mca.c,v 1.23 2003/11/10 08:51:52 wiz Exp $");
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 #include <sys/kthread.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 EDC_ATTN_MAXTRIES 10000 /* How many times check for unbusy */
86 #define EDC_MAX_CMD_RES_LEN 8
87
88 struct edc_mca_softc {
89 struct device sc_dev;
90
91 bus_space_tag_t sc_iot;
92 bus_space_handle_t sc_ioh;
93
94 /* DMA related stuff */
95 bus_dma_tag_t sc_dmat; /* DMA tag as passed by parent */
96 bus_dmamap_t sc_dmamap_xfer; /* transfer dma map */
97
98 void *sc_ih; /* interrupt handle */
99
100 int sc_flags;
101 #define DASD_QUIET 0x01 /* don't dump cmd error info */
102
103 #define DASD_MAXDEVS 8
104 struct ed_softc *sc_ed[DASD_MAXDEVS];
105 int sc_maxdevs; /* max number of disks attached to this
106 * controller */
107
108 /* I/O results variables */
109 volatile int sc_stat;
110 #define STAT_START 0
111 #define STAT_ERROR 1
112 #define STAT_DONE 2
113 volatile int sc_resblk; /* residual block count */
114
115 /* CMD status block - only set & used in edc_intr() */
116 u_int16_t status_block[EDC_MAX_CMD_RES_LEN];
117 };
118
119 int edc_mca_probe __P((struct device *, struct cfdata *, void *));
120 void edc_mca_attach __P((struct device *, struct device *, void *));
121
122 CFATTACH_DECL(edc_mca, sizeof(struct edc_mca_softc),
123 edc_mca_probe, edc_mca_attach, NULL, NULL);
124
125 static int edc_intr __P((void *));
126 static void edc_dump_status_block __P((struct edc_mca_softc *,
127 u_int16_t *, int));
128 static int edc_do_attn __P((struct edc_mca_softc *, int, int, int));
129 static void edc_cmd_wait __P((struct edc_mca_softc *, int, int));
130 static void edcworker __P((void *));
131 static void edc_spawn_worker __P((void *));
132
133 int
134 edc_mca_probe(parent, match, aux)
135 struct device *parent;
136 struct cfdata *match;
137 void *aux;
138 {
139 struct mca_attach_args *ma = aux;
140
141 switch (ma->ma_id) {
142 case MCA_PRODUCT_IBM_ESDIC:
143 case MCA_PRODUCT_IBM_ESDIC_IG:
144 return (1);
145 default:
146 return (0);
147 }
148 }
149
150 void
151 edc_mca_attach(parent, self, aux)
152 struct device *parent, *self;
153 void *aux;
154 {
155 struct edc_mca_softc *sc = (void *) self;
156 struct mca_attach_args *ma = aux;
157 struct ed_attach_args eda;
158 int pos2, pos3, pos4;
159 int irq, drq, iobase;
160 const char *typestr;
161 int devno, error;
162
163 pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2);
164 pos3 = mca_conf_read(ma->ma_mc, ma->ma_slot, 3);
165 pos4 = mca_conf_read(ma->ma_mc, ma->ma_slot, 4);
166
167 /*
168 * POS register 2: (adf pos0)
169 *
170 * 7 6 5 4 3 2 1 0
171 * \ \____/ \ \__ enable: 0=adapter disabled, 1=adapter enabled
172 * \ \ \___ Primary/Alternate Port Addresses:
173 * \ \ 0=0x3510-3517 1=0x3518-0x351f
174 * \ \_____ DMA Arbitration Level: 0101=5 0110=6 0111=7
175 * \ 0000=0 0001=1 0011=3 0100=4
176 * \_________ Fairness On/Off: 1=On 0=Off
177 *
178 * POS register 3: (adf pos1)
179 *
180 * 7 6 5 4 3 2 1 0
181 * 0 0 \_/
182 * \__________ DMA Burst Pacing Interval: 10=24ms 11=31ms
183 * 01=16ms 00=Burst Disabled
184 *
185 * POS register 4: (adf pos2)
186 *
187 * 7 6 5 4 3 2 1 0
188 * \_/ \__ DMA Pacing Control: 1=Disabled 0=Enabled
189 * \____ Time to Release: 1X=6ms 01=3ms 00=Immediate
190 *
191 * IRQ is fixed to 14 (0x0e).
192 */
193
194 switch (ma->ma_id) {
195 case MCA_PRODUCT_IBM_ESDIC:
196 typestr = "IBM ESDI Fixed Disk Controller";
197 break;
198 case MCA_PRODUCT_IBM_ESDIC_IG:
199 typestr = "IBM Integ. ESDI Fixed Disk & Controller";
200 break;
201 default:
202 typestr = NULL;
203 break;
204 }
205
206 irq = ESDIC_IRQ;
207 iobase = (pos2 & IO_IS_ALT) ? ESDIC_IOALT : ESDIC_IOPRM;
208 drq = (pos2 & DRQ_MASK) >> 2;
209
210 printf(" slot %d irq %d drq %d: %s\n", ma->ma_slot+1,
211 irq, drq, typestr);
212
213 #ifdef DIAGNOSTIC
214 /*
215 * It's not strictly necessary to check this, machine configuration
216 * utility uses only valid addresses.
217 */
218 if (drq == 2 || drq >= 8) {
219 printf("%s: invalid DMA Arbitration Level %d\n",
220 sc->sc_dev.dv_xname, drq);
221 return;
222 }
223 #endif
224
225 printf("%s: Fairness %s, Release %s, ",
226 sc->sc_dev.dv_xname,
227 (pos2 & FAIRNESS_ENABLE) ? "On" : "Off",
228 (pos4 & RELEASE_1) ? "6ms"
229 : ((pos4 & RELEASE_2) ? "3ms" : "Immediate")
230 );
231 if ((pos4 & PACING_CTRL_DISABLE) == 0) {
232 static const char * const pacint[] =
233 { "disabled", "16ms", "24ms", "31ms"};
234 printf("DMA burst pacing interval %s\n",
235 pacint[(pos3 & PACING_INT_MASK) >> 4]);
236 } else
237 printf("DMA pacing control disabled\n");
238
239 sc->sc_iot = ma->ma_iot;
240
241 if (bus_space_map(sc->sc_iot, iobase,
242 ESDIC_REG_NPORTS, 0, &sc->sc_ioh)) {
243 printf("%s: couldn't map registers\n",
244 sc->sc_dev.dv_xname);
245 return;
246 }
247
248 sc->sc_ih = mca_intr_establish(ma->ma_mc, irq, IPL_BIO, edc_intr, sc);
249 if (sc->sc_ih == NULL) {
250 printf("%s: couldn't establish interrupt handler\n",
251 sc->sc_dev.dv_xname);
252 return;
253 }
254
255 /* Create a MCA DMA map, used for data transfer */
256 sc->sc_dmat = ma->ma_dmat;
257 if ((error = mca_dmamap_create(sc->sc_dmat, MAXPHYS,
258 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW | MCABUS_DMA_16BIT,
259 &sc->sc_dmamap_xfer, drq)) != 0){
260 printf("%s: couldn't create DMA map - error %d\n",
261 sc->sc_dev.dv_xname, error);
262 return;
263 }
264
265 /*
266 * Integrated ESDI controller supports only one disk, other
267 * controllers support two disks.
268 */
269 if (ma->ma_id == MCA_PRODUCT_IBM_ESDIC_IG)
270 sc->sc_maxdevs = 1;
271 else
272 sc->sc_maxdevs = 2;
273
274 /*
275 * Reset controller and attach individual disks. ed attach routine
276 * uses polling so that this works with interrupts disabled.
277 */
278
279 /* Do a reset to ensure sane state after warm boot. */
280 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_BUSY) {
281 /* hard reset */
282 printf("%s: controller busy, performing hardware reset ...\n",
283 sc->sc_dev.dv_xname);
284 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR,
285 BCR_INT_ENABLE|BCR_RESET);
286 } else {
287 /* "SOFT" reset */
288 edc_do_attn(sc, ATN_RESET_ATTACHMENT, DASD_DEVNO_CONTROLLER,0);
289 }
290
291 /*
292 * Since interrupts are disabled, it's necessary
293 * to detect the interrupt request and call edc_intr()
294 * explicitly. See also edc_run_cmd().
295 */
296 while(bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_BUSY) {
297 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_INTR)
298 edc_intr(sc);
299
300 delay(100);
301 }
302
303 /* be quiet during probes */
304 sc->sc_flags |= DASD_QUIET;
305
306 /* check for attached disks */
307 for(devno=0; devno < sc->sc_maxdevs; devno++) {
308 eda.edc_drive = devno;
309 sc->sc_ed[devno] =
310 (void *) config_found_sm(self, &eda, NULL, NULL);
311
312 /* If initialization did not succeed, NULL the pointer. */
313 if (sc->sc_ed[devno]
314 && (sc->sc_ed[devno]->sc_flags & EDF_INIT) == 0)
315 sc->sc_ed[devno] = NULL;
316 }
317
318 /* enable full error dumps again */
319 sc->sc_flags &= ~DASD_QUIET;
320
321 /*
322 * Check if there are any disks attached. If not, disestablish
323 * the interrupt.
324 */
325 for(devno=0; devno < sc->sc_maxdevs; devno++) {
326 if (sc->sc_ed[devno])
327 break;
328 }
329
330 if (devno == sc->sc_maxdevs) {
331 printf("%s: disabling controller (no drives attached)\n",
332 sc->sc_dev.dv_xname);
333 mca_intr_disestablish(ma->ma_mc, sc->sc_ih);
334 return;
335 }
336
337 /*
338 * Run the worker thread.
339 */
340 config_pending_incr();
341 kthread_create(edc_spawn_worker, (void *) sc);
342 }
343
344 void
345 edc_add_disk(sc, ed)
346 struct edc_mca_softc *sc;
347 struct ed_softc *ed;
348 {
349 sc->sc_ed[ed->sc_devno] = ed;
350 }
351
352 static int
353 edc_intr(arg)
354 void *arg;
355 {
356 struct edc_mca_softc *sc = arg;
357 u_int8_t isr, intr_id;
358 u_int16_t sifr;
359 int cmd=-1, devno;
360
361 /*
362 * Check if the interrupt was for us.
363 */
364 if ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR) & BSR_INTR) == 0)
365 return (0);
366
367 /*
368 * Read ISR to find out interrupt type. This also clears the interrupt
369 * condition and BSR_INTR flag. Accordings to docs interrupt ID of 0, 2
370 * and 4 are reserved and not used.
371 */
372 isr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ISR);
373 intr_id = isr & ISR_INTR_ID_MASK;
374
375 #ifdef EDC_DEBUG
376 if (intr_id == 0 || intr_id == 2 || intr_id == 4) {
377 printf("%s: bogus interrupt id %d\n", sc->sc_dev.dv_xname,
378 (int) intr_id);
379 return (0);
380 }
381 #endif
382
383 /* Get number of device whose intr this was */
384 devno = (isr & 0xe0) >> 5;
385
386 /*
387 * Get Status block. Higher byte always says how long the status
388 * block is, rest is device number and command code.
389 * Check the status block length against our supported maximum length
390 * and fetch the data.
391 */
392 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh,BSR) & BSR_SIFR_FULL) {
393 size_t len;
394 int i;
395
396 sifr = le16toh(bus_space_read_2(sc->sc_iot, sc->sc_ioh, SIFR));
397 len = (sifr & 0xff00) >> 8;
398 #ifdef DEBUG
399 if (len > EDC_MAX_CMD_RES_LEN)
400 panic("%s: maximum Status Length exceeded: %d > %d",
401 sc->sc_dev.dv_xname,
402 len, EDC_MAX_CMD_RES_LEN);
403 #endif
404
405 /* Get command code */
406 cmd = sifr & SIFR_CMD_MASK;
407
408 /* Read whole status block */
409 sc->status_block[0] = sifr;
410 for(i=1; i < len; i++) {
411 while((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR)
412 & BSR_SIFR_FULL) == 0)
413 ;
414
415 sc->status_block[i] = le16toh(
416 bus_space_read_2(sc->sc_iot, sc->sc_ioh, SIFR));
417 }
418 /* zero out rest */
419 if (i < EDC_MAX_CMD_RES_LEN) {
420 memset(&sc->status_block[i], 0,
421 (EDC_MAX_CMD_RES_LEN-i)*sizeof(u_int16_t));
422 }
423 }
424
425 switch (intr_id) {
426 case ISR_DATA_TRANSFER_RDY:
427 /*
428 * Ready to do DMA. The DMA controller has already been
429 * setup, now just kick disk controller to do the transfer.
430 */
431 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR,
432 BCR_INT_ENABLE|BCR_DMA_ENABLE);
433 break;
434
435 case ISR_COMPLETED:
436 case ISR_COMPLETED_WITH_ECC:
437 case ISR_COMPLETED_RETRIES:
438 case ISR_COMPLETED_WARNING:
439 /*
440 * Copy device config data if appropriate. sc->sc_ed[]
441 * entry might be NULL during probe.
442 */
443 if (cmd == CMD_GET_DEV_CONF && sc->sc_ed[devno]) {
444 memcpy(sc->sc_ed[devno]->sense_data, sc->status_block,
445 sizeof(sc->sc_ed[devno]->sense_data));
446 }
447
448 sc->sc_stat = STAT_DONE;
449 break;
450
451 case ISR_RESET_COMPLETED:
452 case ISR_ABORT_COMPLETED:
453 /* nothing to do */
454 break;
455
456 case ISR_ATTN_ERROR:
457 /*
458 * Basically, this means driver bug or something seriously
459 * hosed. panic rather than extending the lossage.
460 * No status block available, so no further info.
461 */
462 panic("%s: dev %d: attention error",
463 sc->sc_dev.dv_xname,
464 devno);
465 /* NOTREACHED */
466 break;
467
468 default:
469 if ((sc->sc_flags & DASD_QUIET) == 0)
470 edc_dump_status_block(sc, sc->status_block, intr_id);
471
472 sc->sc_stat = STAT_ERROR;
473 break;
474 }
475
476 /*
477 * Unless the interrupt is for Data Transfer Ready or
478 * Attention Error, finish by assertion EOI. This makes
479 * attachment aware the interrupt is processed and system
480 * is ready to accept another one.
481 */
482 if (intr_id != ISR_DATA_TRANSFER_RDY && intr_id != ISR_ATTN_ERROR)
483 edc_do_attn(sc, ATN_END_INT, devno, intr_id);
484
485 /* If Read or Write Data, wakeup worker thread to finish it */
486 if (intr_id != ISR_DATA_TRANSFER_RDY) {
487 if (cmd == CMD_READ_DATA || cmd == CMD_WRITE_DATA)
488 sc->sc_resblk = sc->status_block[SB_RESBLKCNT_IDX];
489 wakeup_one(sc);
490 }
491
492 return (1);
493 }
494
495 /*
496 * This follows the exact order for Attention Request as
497 * written in DASD Storage Interface Specification MC (Rev 2.2).
498 */
499 static int
500 edc_do_attn(sc, attn_type, devno, intr_id)
501 struct edc_mca_softc *sc;
502 int attn_type, devno, intr_id;
503 {
504 int tries;
505
506 /* 1. Disable interrupts in BCR. */
507 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR, 0);
508
509 /*
510 * 2. Assure NOT BUSY and NO INTERRUPT PENDING, unless acknowledging
511 * a RESET COMPLETED interrupt.
512 */
513 if (intr_id != ISR_RESET_COMPLETED) {
514 #ifdef EDC_DEBUG
515 if (attn_type == ATN_CMD_REQ
516 && (bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR)
517 & BSR_INT_PENDING))
518 panic("%s: edc int pending", sc->sc_dev.dv_xname);
519 #endif
520
521 for(tries=1; tries < EDC_ATTN_MAXTRIES; tries++) {
522 if ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR)
523 & BSR_BUSY) == 0)
524 break;
525 }
526
527 if (tries == EDC_ATTN_MAXTRIES) {
528 printf("%s: edc_do_attn: timeout waiting for attachment to become available\n",
529 sc->sc_ed[devno]->sc_dev.dv_xname);
530 return (EIO);
531 }
532 }
533
534 /*
535 * 3. Write proper DEVICE NUMBER and Attention number to ATN.
536 */
537 bus_space_write_1(sc->sc_iot, sc->sc_ioh, ATN, attn_type | (devno<<5));
538
539 /*
540 * 4. Enable interrupts via BCR.
541 */
542 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BCR, BCR_INT_ENABLE);
543
544 return (0);
545 }
546
547 /*
548 * Wait until command is processed, timeout after 'secs' seconds.
549 * We use mono_time, since we don't need actual RTC, just time
550 * interval.
551 */
552 static void
553 edc_cmd_wait(sc, secs, poll)
554 struct edc_mca_softc *sc;
555 int secs, poll;
556 {
557 int val;
558
559 if (!poll) {
560 int s;
561
562 /* Not polling, can sleep. Sleep until we are awakened,
563 * but maximum secs seconds.
564 */
565 s = splbio();
566 if (sc->sc_stat != STAT_DONE)
567 (void) tsleep(sc, PRIBIO, "edcwcmd", secs * hz);
568 splx(s);
569 }
570
571 /* Wait until the command is completely finished */
572 while((val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR))
573 & BSR_CMD_INPROGRESS) {
574 if (poll && (val & BSR_INTR))
575 edc_intr(sc);
576 }
577 }
578
579 /*
580 * Command controller to execute specified command on a device.
581 */
582 int
583 edc_run_cmd(sc, cmd, devno, cmd_args, cmd_len, poll)
584 struct edc_mca_softc *sc;
585 int cmd;
586 int devno;
587 u_int16_t cmd_args[];
588 int cmd_len, poll;
589 {
590 int i, error, tries;
591 u_int16_t cmd0;
592
593 sc->sc_stat = STAT_START;
594
595 /* Do Attention Request for Command Request. */
596 if ((error = edc_do_attn(sc, ATN_CMD_REQ, devno, 0)))
597 return (error);
598
599 /*
600 * Construct the command. The bits are like this:
601 *
602 * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
603 * \_/ 0 0 1 0 \__/ \_____/
604 * \ \__________/ \ \_ Command Code (see CMD_*)
605 * \ \ \__ Device: 0 common, 7 controller
606 * \ \__ Options: reserved, bit 10=cache bypass bit
607 * \_ Type: 00=2B, 01=4B, 10 and 11 reserved
608 *
609 * We always use device 0 or 1, so difference is made only by Command
610 * Code, Command Options and command length.
611 */
612 cmd0 = ((cmd_len == 4) ? (CIFR_LONG_CMD) : 0)
613 | (devno << 5)
614 | (cmd_args[0] << 8) | cmd;
615 cmd_args[0] = cmd0;
616
617 /*
618 * Write word of CMD to the CIFR. This sets "Command
619 * Interface Register Full (CMD IN)" in BSR. Once the attachment
620 * detects it, it reads the word and clears CMD IN. This all should
621 * be quite fast, so don't sleep in !poll case neither.
622 */
623 for(i=0; i < cmd_len; i++) {
624 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CIFR,
625 htole16(cmd_args[i]));
626
627 /* Wait until CMD IN is cleared. */
628 tries = 0;
629 for(; (bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR)
630 & BSR_CIFR_FULL) && tries < 10000 ; tries++)
631 delay(poll ? 1000 : 1);
632 ;
633
634 if (tries == 10000
635 && bus_space_read_1(sc->sc_iot, sc->sc_ioh, BSR)
636 & BSR_CIFR_FULL) {
637 printf("%s: device too slow to accept command %d\n",
638 sc->sc_dev.dv_xname, cmd);
639 return (EIO);
640 }
641 }
642
643 /* Wait for command to complete, but maximum 15 seconds. */
644 edc_cmd_wait(sc, 15, poll);
645
646 return ((sc->sc_stat != STAT_DONE) ? EIO : 0);
647 }
648
649 #ifdef EDC_DEBUG
650 static const char * const edc_commands[] = {
651 "Invalid Command",
652 "Read Data",
653 "Write Data",
654 "Read Verify",
655 "Write with Verify",
656 "Seek",
657 "Park Head",
658 "Get Command Complete Status",
659 "Get Device Status",
660 "Get Device Configuration",
661 "Get POS Information",
662 "Translate RBA",
663 "Write Attachment Buffer",
664 "Read Attachment Buffer",
665 "Run Diagnostic Test",
666 "Get Diagnostic Status Block",
667 "Get MFG Header",
668 "Format Unit",
669 "Format Prepare",
670 "Set MAX RBA",
671 "Set Power Saving Mode",
672 "Power Conservation Command",
673 };
674
675 static const char * const edc_cmd_status[256] = {
676 "Reserved",
677 "Command completed successfully",
678 "Reserved",
679 "Command completed successfully with ECC applied",
680 "Reserved",
681 "Command completed successfully with retries",
682 "Format Command partially completed", /* Status available */
683 "Command completed successfully with ECC and retries",
684 "Command completed with Warning", /* Command Error is available */
685 "Aborted",
686 "Reset completed",
687 "Data Transfer Ready", /* No Status Block available */
688 "Command terminated with failure", /* Device Error is available */
689 "DMA Error", /* Retry entire command as recovery */
690 "Command Block Error",
691 "Attention Error (Illegal Attention Code)",
692 /* 0x14 - 0xff reserved */
693 };
694
695 static const char * const edc_cmd_error[256] = {
696 "No Error",
697 "Invalid parameter in the command block",
698 "Reserved",
699 "Command not supported",
700 "Command Aborted per request",
701 "Reserved",
702 "Command rejected", /* Attachment diagnostic failure */
703 "Format Rejected", /* Prepare Format command is required */
704 "Format Error (Primary Map is not readable)",
705 "Format Error (Secondary map is not readable)",
706 "Format Error (Diagnostic Failure)",
707 "Format Warning (Secondary Map Overflow)",
708 "Reserved"
709 "Format Error (Host Checksum Error)",
710 "Reserved",
711 "Format Warning (Push table overflow)",
712 "Format Warning (More pushes than allowed)",
713 "Reserved",
714 "Format Warning (Error during verifying)",
715 "Invalid device number for the command",
716 /* 0x14-0xff reserved */
717 };
718
719 static const char * const edc_dev_errors[] = {
720 "No Error",
721 "Seek Fault", /* Device report */
722 "Interface Fault (Parity, Attn, or Cmd Complete Error)",
723 "Block not found (ID not found)",
724 "Block not found (AM not found)",
725 "Data ECC Error (hard error)",
726 "ID CRC Error",
727 "RBA Out of Range",
728 "Reserved",
729 "Defective Block",
730 "Reserved",
731 "Selection Error",
732 "Reserved",
733 "Write Fault",
734 "No index or sector pulse",
735 "Device Not Ready",
736 "Seek Error", /* Attachment report */
737 "Bad Format",
738 "Volume Overflow",
739 "No Data AM Found",
740 "Block not found (No ID AM or ID CRC error occurred)",
741 "Reserved",
742 "Reserved",
743 "No ID found on track (ID search)",
744 /* 0x19 - 0xff reserved */
745 };
746 #endif /* EDC_DEBUG */
747
748 static void
749 edc_dump_status_block(sc, status_block, intr_id)
750 struct edc_mca_softc *sc;
751 u_int16_t *status_block;
752 int intr_id;
753 {
754 #ifdef EDC_DEBUG
755 printf("%s: Command: %s, Status: %s (intr %d)\n",
756 sc->sc_dev.dv_xname,
757 edc_commands[status_block[0] & 0x1f],
758 edc_cmd_status[SB_GET_CMD_STATUS(status_block)],
759 intr_id
760 );
761 #else
762 printf("%s: Command: %d, Status: %d (intr %d)\n",
763 sc->sc_dev.dv_xname,
764 status_block[0] & 0x1f,
765 SB_GET_CMD_STATUS(status_block),
766 intr_id
767 );
768 #endif
769 printf("%s: # left blocks: %u, last processed RBA: %u\n",
770 sc->sc_dev.dv_xname,
771 status_block[SB_RESBLKCNT_IDX],
772 (status_block[5] << 16) | status_block[4]);
773
774 if (intr_id == ISR_COMPLETED_WARNING) {
775 #ifdef EDC_DEBUG
776 printf("%s: Command Error Code: %s\n",
777 sc->sc_dev.dv_xname,
778 edc_cmd_error[status_block[1] & 0xff]);
779 #else
780 printf("%s: Command Error Code: %d\n",
781 sc->sc_dev.dv_xname,
782 status_block[1] & 0xff);
783 #endif
784 }
785
786 if (intr_id == ISR_CMD_FAILED) {
787 #ifdef EDC_DEBUG
788 char buf[100];
789
790 printf("%s: Device Error Code: %s\n",
791 sc->sc_dev.dv_xname,
792 edc_dev_errors[status_block[2] & 0xff]);
793 bitmask_snprintf((status_block[2] & 0xff00) >> 8,
794 "\2"
795 "\01SeekOrCmdComplete"
796 "\02Track0Flag"
797 "\03WriteFault"
798 "\04Selected"
799 "\05Ready"
800 "\06Reserved0"
801 "\07STANDBY"
802 "\010Reserved0",
803 buf, sizeof(buf));
804 printf("%s: Device Status: %s\n",
805 sc->sc_dev.dv_xname, buf);
806 #else
807 printf("%s: Device Error Code: %d, Device Status: %d\n",
808 sc->sc_dev.dv_xname,
809 status_block[2] & 0xff,
810 (status_block[2] & 0xff00) >> 8);
811 #endif
812 }
813 }
814
815 static void
816 edc_spawn_worker(arg)
817 void *arg;
818 {
819 struct edc_mca_softc *sc = (struct edc_mca_softc *) arg;
820 int error;
821 struct proc *wrk;
822
823 /* Now, everything is ready, start a kthread */
824 if ((error = kthread_create1(edcworker, sc, &wrk,
825 "%s", sc->sc_dev.dv_xname))) {
826 printf("%s: cannot spawn worker thread: errno=%d\n",
827 sc->sc_dev.dv_xname, error);
828 panic("edc_spawn_worker");
829 }
830 }
831
832 /*
833 * Main worker thread function.
834 */
835 void
836 edcworker(arg)
837 void *arg;
838 {
839 struct edc_mca_softc *sc = (struct edc_mca_softc *) arg;
840 struct ed_softc *ed;
841 struct buf *bp;
842 int i, error;
843
844 config_pending_decr();
845
846 for(;;) {
847 /* Wait until awakened */
848 (void) tsleep(sc, PRIBIO, "edcidle", 0);
849
850 for(i=0; i<sc->sc_maxdevs; ) {
851 if ((ed = sc->sc_ed[i]) == NULL) {
852 i++;
853 continue;
854 }
855
856 /* Is there a buf for us ? */
857 simple_lock(&ed->sc_q_lock);
858 if ((bp = BUFQ_GET(&ed->sc_q)) == NULL) {
859 simple_unlock(&ed->sc_q_lock);
860 i++;
861 continue;
862 }
863 simple_unlock(&ed->sc_q_lock);
864
865 /* Instrumentation. */
866 disk_busy(&ed->sc_dk);
867
868 error = edc_bio(sc, ed, bp->b_data, bp->b_bcount,
869 bp->b_rawblkno, (bp->b_flags & B_READ), 0);
870
871 if (error) {
872 bp->b_error = error;
873 bp->b_flags |= B_ERROR;
874 } else {
875 /* Set resid, most commonly to zero. */
876 bp->b_resid = sc->sc_resblk * DEV_BSIZE;
877 }
878
879 disk_unbusy(&ed->sc_dk, (bp->b_bcount - bp->b_resid),
880 (bp->b_flags & B_READ));
881 #if NRND > 0
882 rnd_add_uint32(&ed->rnd_source, bp->b_blkno);
883 #endif
884 biodone(bp);
885 }
886 }
887 }
888
889 int
890 edc_bio(struct edc_mca_softc *sc, struct ed_softc *ed, void *data,
891 size_t bcount, daddr_t rawblkno, int isread, int poll)
892 {
893 u_int16_t cmd_args[4];
894 int error=0, fl;
895 u_int16_t track;
896 u_int16_t cyl;
897 u_int8_t head;
898 u_int8_t sector;
899
900 mca_disk_busy();
901
902 /* set WAIT and R/W flag appropriately for the DMA transfer */
903 fl = ((poll) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK)
904 | ((isread) ? BUS_DMA_READ : BUS_DMA_WRITE);
905
906 /* Load the buffer for DMA transfer. */
907 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_xfer, data,
908 bcount, NULL, BUS_DMA_STREAMING|fl))) {
909 printf("%s: ed_bio: unable to load DMA buffer - error %d\n",
910 ed->sc_dev.dv_xname, error);
911 goto out;
912 }
913
914 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_xfer, 0,
915 bcount, (isread) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
916
917 track = rawblkno / ed->sectors;
918 head = track % ed->heads;
919 cyl = track / ed->heads;
920 sector = rawblkno % ed->sectors;
921
922 /* Read or Write Data command */
923 cmd_args[0] = 2; /* Options 0000010 */
924 cmd_args[1] = bcount / DEV_BSIZE;
925 cmd_args[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
926 cmd_args[3] = ((cyl & 0x3E0) >> 5);
927 error = edc_run_cmd(sc,
928 (isread) ? CMD_READ_DATA : CMD_WRITE_DATA,
929 ed->sc_devno, cmd_args, 4, poll);
930
931 /* Sync the DMA memory */
932 if (!error) {
933 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_xfer, 0, bcount,
934 (isread)? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
935 }
936
937 /* We are done, unload buffer from DMA map */
938 bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap_xfer);
939
940 out:
941 mca_disk_unbusy();
942
943 return (error);
944 }
Cache object: f4d41f02f8838251b101f34d81c5621c
|