xref: /minix/minix/drivers/storage/at_wini/at_wini.c (revision 2a404668)
1 /* This file contains the device dependent part of a driver for the IBM-AT
2  * winchester controller.  Written by Adri Koppes.
3  *
4  * Changes:
5  *   Oct  2, 2013   drop non-PCI support; one controller per instance  (David)
6  *   Aug 19, 2005   ATA PCI support, supports SATA  (Ben Gras)
7  *   Nov 18, 2004   moved AT disk driver to user-space  (Jorrit N. Herder)
8  *   Aug 20, 2004   watchdogs replaced by sync alarms  (Jorrit N. Herder)
9  *   Mar 23, 2000   added ATAPI CDROM support  (Michael Temari)
10  *   May 14, 2000   d-d/i rewrite  (Kees J. Bot)
11  *   Apr 13, 1992   device dependent/independent split  (Kees J. Bot)
12  */
13 
14 #include "at_wini.h"
15 
16 #include <minix/sysutil.h>
17 #include <minix/type.h>
18 #include <minix/endpoint.h>
19 #include <sys/ioc_disk.h>
20 #include <machine/pci.h>
21 #include <sys/mman.h>
22 
23 /* Variables. */
24 
25 /* Common command block */
26 struct command {
27   u8_t	precomp;	/* REG_PRECOMP, etc. */
28   u8_t	count;
29   u8_t	sector;
30   u8_t	cyl_lo;
31   u8_t	cyl_hi;
32   u8_t	ldh;
33   u8_t	command;
34 
35   /* The following at for LBA48 */
36   u8_t	count_prev;
37   u8_t	sector_prev;
38   u8_t	cyl_lo_prev;
39   u8_t	cyl_hi_prev;
40 };
41 
42 /* Timeouts and max retries. */
43 static int timeout_usecs = DEF_TIMEOUT_USECS;
44 static int max_errors = MAX_ERRORS;
45 static long w_standard_timeouts = 0;
46 static long w_pci_debug = 0;
47 static long w_instance = 0;
48 static long disable_dma = 0;
49 static long atapi_debug = 0;
50 static long w_identify_wakeup_ticks;
51 static long wakeup_ticks;
52 static long w_atapi_dma;
53 
54 static int w_testing = 0;
55 static int w_silent = 0;
56 
57 static u32_t system_hz;
58 
59 /* The struct wini is indexed by drive (0-3). */
60 static struct wini {		/* main drive struct, one entry per drive */
61   unsigned state;		/* drive state: deaf, initialized, dead */
62   unsigned short w_status;	/* device status register */
63   unsigned base_cmd;		/* command base register */
64   unsigned base_ctl;		/* control base register */
65   unsigned base_dma;		/* dma base register */
66   unsigned char native;		/* if set, drive is native (not compat.) */
67   unsigned char lba48;		/* if set, drive supports lba48 */
68   unsigned char dma;		/* if set, drive supports dma */
69   unsigned char dma_intseen;	/* if set, drive has seen an interrupt */
70   int irq_hook_id;		/* id of irq hook at the kernel */
71   unsigned cylinders;		/* physical number of cylinders */
72   unsigned heads;		/* physical number of heads */
73   unsigned sectors;		/* physical number of sectors per track */
74   unsigned ldhpref;		/* top four bytes of the LDH (head) register */
75   unsigned max_count;		/* max request for this drive */
76   unsigned open_ct;		/* in-use count */
77   struct device part[DEV_PER_DRIVE];	/* disks and partitions */
78   struct device subpart[SUB_PER_DRIVE];	/* subpartitions */
79 } wini[MAX_DRIVES], *w_wn;
80 
81 static int w_device = -1;
82 
83 int w_command;			/* current command in execution */
84 static int w_drive;			/* selected drive */
85 static struct device *w_dv;		/* device's base and size */
86 
87 static u8_t *tmp_buf;
88 
89 #define ATA_DMA_SECTORS	64
90 #define ATA_DMA_BUF_SIZE	(ATA_DMA_SECTORS*SECTOR_SIZE)
91 
92 static char *dma_buf;
93 static phys_bytes dma_buf_phys;
94 
95 #define N_PRDTE	1024	/* Should be enough for large requests */
96 
97 struct prdte
98 {
99 	phys_bytes prdte_base;
100 	u16_t prdte_count;
101 	u8_t prdte_reserved;
102 	u8_t prdte_flags;
103 };
104 
105 #define PRDT_BYTES (sizeof(struct prdte) * N_PRDTE)
106 static struct prdte *prdt;
107 static phys_bytes prdt_phys;
108 
109 #define PRDTE_FL_EOT	0x80	/* End of table */
110 
111 static int w_probe(int skip, u16_t *vidp, u16_t *didp);
112 static void w_init(int devind, u16_t vid, u16_t did);
113 static int init_params(void);
114 static int w_do_open(devminor_t minor, int access);
115 static struct device *w_prepare(devminor_t dev);
116 static struct device *w_part(devminor_t minor);
117 static int w_identify(void);
118 static char *w_name(void);
119 static int w_specify(void);
120 static int w_io_test(void);
121 static ssize_t w_transfer(devminor_t minor, int do_write, u64_t position,
122 	endpoint_t proc_nr, iovec_t *iov, unsigned int nr_req, int flags);
123 static int com_out(struct command *cmd);
124 static int com_out_ext(struct command *cmd);
125 static int setup_dma(unsigned *sizep, endpoint_t proc_nr, iovec_t *iov,
126 	size_t addr_offset, int do_write);
127 static void w_need_reset(void);
128 static int w_do_close(devminor_t minor);
129 static int w_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
130 	cp_grant_id_t grant, endpoint_t user_endpt);
131 static void w_hw_int(unsigned int irqs);
132 static int com_simple(struct command *cmd);
133 static void w_timeout(void);
134 static int w_reset(void);
135 static void w_intr_wait(void);
136 static int at_intr_wait(void);
137 static int w_waitfor(int mask, int value);
138 static int w_waitfor_dma(unsigned int mask, unsigned int value);
139 static void w_geometry(devminor_t minor, struct part_geom *entry);
140 static int atapi_sendpacket(u8_t *packet, unsigned cnt, int do_dma);
141 static int atapi_intr_wait(int dma, size_t max);
142 static int atapi_open(void);
143 static void atapi_close(void);
144 static int atapi_transfer(int do_write, u64_t position, endpoint_t
145 	endpt, iovec_t *iov, unsigned int nr_req);
146 
147 /* Entry points to this driver. */
148 static struct blockdriver w_dtab = {
149   .bdr_type	= BLOCKDRIVER_TYPE_DISK,	/* handle partition requests */
150   .bdr_open	= w_do_open,	/* open or mount request, initialize device */
151   .bdr_close	= w_do_close,	/* release device */
152   .bdr_transfer	= w_transfer,	/* do the I/O */
153   .bdr_ioctl	= w_ioctl,	/* I/O control requests */
154   .bdr_part	= w_part,	/* return partition information */
155   .bdr_geometry	= w_geometry,	/* tell the geometry of the disk */
156   .bdr_intr	= w_hw_int,	/* leftover hardware interrupts */
157 };
158 
159 /* SEF functions and variables. */
160 static void sef_local_startup(void);
161 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
162 
163 /*===========================================================================*
164  *				at_winchester_task			     *
165  *===========================================================================*/
166 int main(int argc, char *argv[])
167 {
168   /* SEF local startup. */
169   env_setargs(argc, argv);
170   sef_local_startup();
171 
172   /* Call the generic receive loop. */
173   blockdriver_task(&w_dtab);
174 
175   return(OK);
176 }
177 
178 /*===========================================================================*
179  *			       sef_local_startup			     *
180  *===========================================================================*/
181 static void sef_local_startup(void)
182 {
183   /* Register init callbacks. */
184   sef_setcb_init_fresh(sef_cb_init_fresh);
185 
186   /* Register live update callbacks. */
187   sef_setcb_lu_prepare(sef_cb_lu_prepare);
188   sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid);
189   sef_setcb_lu_state_dump(sef_cb_lu_state_dump);
190 
191   /* Let SEF perform startup. */
192   sef_startup();
193 }
194 
195 /*===========================================================================*
196  *		            sef_cb_init_fresh                                *
197  *===========================================================================*/
198 static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
199 {
200 /* Initialize the at_wini driver. */
201   int skip, devind;
202   u16_t vid, did;
203 
204   system_hz = sys_hz();
205 
206   if (!(tmp_buf = alloc_contig(2*DMA_BUF_SIZE, AC_ALIGN4K, NULL)))
207 	panic("unable to allocate temporary buffer");
208 
209   w_identify_wakeup_ticks = WAKEUP_TICKS;
210   wakeup_ticks = WAKEUP_TICKS;
211 
212   /* Set special disk parameters. */
213   skip = init_params();
214 
215   /* Find the PCI device to use. If none found, terminate immediately. */
216   devind = w_probe(skip, &vid, &did);
217   if (devind < 0) {
218 	/* For now, complain only if even the first at_wini instance cannot
219 	 * find a device. There may be only one IDE controller after all,
220 	 * but if there are none, the system should probably be booted with
221 	 * another driver, and that's something the user might want to know.
222 	 */
223 	if (w_instance == 0)
224 		panic("no matching device found");
225 	return ENODEV;	/* the actual error code doesn't matter */
226   }
227 
228   /* Initialize the device. */
229   w_init(devind, vid, did);
230 
231   /* Announce we are up! */
232   blockdriver_announce(type);
233 
234   return(OK);
235 }
236 
237 /*===========================================================================*
238  *				init_params				     *
239  *===========================================================================*/
240 static int init_params(void)
241 {
242 /* This routine is called at startup to initialize the drive parameters. */
243   int drive;
244   long wakeup_secs = WAKEUP_SECS;
245 
246   /* Boot variables. */
247   env_parse("instance", "d", 0, &w_instance, 0, 8);
248   env_parse("ata_std_timeout", "d", 0, &w_standard_timeouts, 0, 1);
249   env_parse("ata_pci_debug", "d", 0, &w_pci_debug, 0, 1);
250   env_parse(NO_DMA_VAR, "d", 0, &disable_dma, 0, 1);
251   env_parse("ata_id_timeout", "d", 0, &wakeup_secs, 1, 60);
252   env_parse("atapi_debug", "d", 0, &atapi_debug, 0, 1);
253   env_parse("atapi_dma", "d", 0, &w_atapi_dma, 0, 1);
254 
255   w_identify_wakeup_ticks = wakeup_secs * system_hz;
256 
257   if(atapi_debug)
258 	panic("atapi_debug");
259 
260   if(w_identify_wakeup_ticks <= 0) {
261 	printf("changing wakeup from %ld to %d ticks.\n",
262 		w_identify_wakeup_ticks, WAKEUP_TICKS);
263 	w_identify_wakeup_ticks = WAKEUP_TICKS;
264   }
265 
266   if (disable_dma) {
267 	printf("at_wini%ld: DMA for ATA devices is disabled.\n", w_instance);
268   } else {
269 	/* Ask for anonymous memory for DMA, that is physically contiguous. */
270 	dma_buf = alloc_contig(ATA_DMA_BUF_SIZE, 0, &dma_buf_phys);
271 	prdt = alloc_contig(PRDT_BYTES, 0, &prdt_phys);
272 	if(!dma_buf || !prdt) {
273 		disable_dma = 1;
274 		printf("at_wini%ld: no dma\n", w_instance);
275 	}
276   }
277 
278   for (drive = 0; drive < MAX_DRIVES; drive++)
279 	wini[drive].state = IGNORING;
280 
281   return (int) w_instance;
282 }
283 
284 /*===========================================================================*
285  *				init_drive				     *
286  *===========================================================================*/
287 static void init_drive(int drive, int base_cmd, int base_ctl, int base_dma,
288 	int native, int hook)
289 {
290   struct wini *w;
291 
292   w = &wini[drive];
293 
294   w->state = 0;
295   w->w_status = 0;
296   w->base_cmd = base_cmd;
297   w->base_ctl = base_ctl;
298   w->base_dma = base_dma;
299   if (w_pci_debug)
300 	printf("at_wini%ld: drive %d: base_cmd 0x%x, base_ctl 0x%x, "
301 		"base_dma 0x%x\n", w_instance, drive, w->base_cmd, w->base_ctl,
302 		w->base_dma);
303   w->native = native;
304   w->irq_hook_id = hook;
305   w->ldhpref = ldh_init(drive);
306   w->max_count = MAX_SECS << SECTOR_SHIFT;
307   w->lba48 = 0;
308   w->dma = 0;
309 }
310 
311 /*===========================================================================*
312  *				w_probe					     *
313  *===========================================================================*/
314 static int w_probe(int skip, u16_t *vidp, u16_t *didp)
315 {
316 /* Go through the PCI devices that have been made visible to us, skipping as
317  * many as requested and then reserving the first one after that. We assume
318  * that all visible devices are in fact devices we can handle.
319  */
320   int r, devind;
321 
322   pci_init();
323 
324   r = pci_first_dev(&devind, vidp, didp);
325   if (r <= 0)
326 	return -1;
327 
328   while (skip--) {
329 	r = pci_next_dev(&devind, vidp, didp);
330 	if (r <= 0)
331 		return -1;
332   }
333 
334   pci_reserve(devind);
335 
336   return devind;
337 }
338 
339 /*===========================================================================*
340  *				w_init					     *
341  *===========================================================================*/
342 static void w_init(int devind, u16_t vid, u16_t did)
343 {
344 /* Initialize drives on the controller that we found and reserved. Each
345  * controller has two channels, each of which may have up to two disks
346  * attached, so the maximum number of disks per controller is always four.
347  * In this function, we always initialize the slots for all four disks; later,
348  * during normal operation, we determine whether the disks are actually there.
349  * For pure IDE devices (as opposed to e.g. RAID devices), each of the two
350  * channels on the controller may be in native or compatibility mode. The PCI
351  * interface field tells us which channel is in which mode. For native
352  * channels, we get the IRQ and the channel's base control and command
353  * addresses from the PCI slot, and we manually acknowledge interrupts. For
354  * compatibility channels, we use the hardcoded legacy IRQs and addresses, and
355  * enable automatic IRQ reenabling. In both cases, we get the base DMA address
356  * from the PCI slot if it is there.
357  */
358   int r, irq, native_hook, compat_hook, is_ide, nhooks;
359   u8_t bcr, scr, interface;
360   u16_t cr;
361   u32_t base_cmd, base_ctl, base_dma;
362 
363   bcr= pci_attr_r8(devind, PCI_BCR);
364   scr= pci_attr_r8(devind, PCI_SCR);
365   interface= pci_attr_r8(devind, PCI_PIFR);
366 
367   is_ide = (bcr == PCI_BCR_MASS_STORAGE && scr == PCI_MS_IDE);
368 
369   irq = pci_attr_r8(devind, PCI_ILR);
370   base_dma = pci_attr_r32(devind, PCI_BAR_5) & PCI_BAR_IO_MASK;
371 
372   nhooks = 0;	/* we don't care about notify IDs, but they must be unique */
373 
374   /* Any native drives? Then register their native IRQ first. */
375   if (!is_ide || (interface & (ATA_IF_NATIVE0 | ATA_IF_NATIVE1))) {
376 	native_hook = nhooks++;
377 	if ((r = sys_irqsetpolicy(irq, 0, &native_hook)) != OK)
378 		panic("couldn't set native IRQ policy %d: %d", irq, r);
379 	if ((r = sys_irqenable(&native_hook)) != OK)
380 		panic("couldn't enable native IRQ line %d: %d", irq, r);
381   }
382 
383   /* Add drives on the primary channel. */
384   if (!is_ide || (interface & ATA_IF_NATIVE0)) {
385 	base_cmd = pci_attr_r32(devind, PCI_BAR) & PCI_BAR_IO_MASK;
386 	base_ctl = pci_attr_r32(devind, PCI_BAR_2) & PCI_BAR_IO_MASK;
387 
388 	init_drive(0, base_cmd, base_ctl+PCI_CTL_OFF, base_dma, TRUE,
389 		native_hook);
390 	init_drive(1, base_cmd, base_ctl+PCI_CTL_OFF, base_dma, TRUE,
391 		native_hook);
392 
393 	if (w_pci_debug)
394 		printf("at_wini%ld: native 0 on %d: 0x%x 0x%x irq %d\n",
395 			w_instance, devind, base_cmd, base_ctl, irq);
396   } else {
397 	/* Register first compatibility IRQ. */
398 	compat_hook = nhooks++;
399 	if ((r = sys_irqsetpolicy(AT_WINI_0_IRQ, IRQ_REENABLE,
400 		&compat_hook)) != OK)
401 		panic("couldn't set compat(0) IRQ policy: %d", r);
402 	if ((r = sys_irqenable(&compat_hook)) != OK)
403 		panic("couldn't enable compat(0) IRQ line: %d", r);
404 
405 	init_drive(0, REG_CMD_BASE0, REG_CTL_BASE0, base_dma, FALSE,
406 		compat_hook);
407 	init_drive(1, REG_CMD_BASE0, REG_CTL_BASE0, base_dma, FALSE,
408 		compat_hook);
409 
410 	if (w_pci_debug)
411 		printf("at_wini%ld: compat 0 on %d\n", w_instance, devind);
412   }
413 
414   /* Add drives on the secondary channel. */
415   if (base_dma != 0)
416 	base_dma += PCI_DMA_2ND_OFF;
417   if (!is_ide || (interface & ATA_IF_NATIVE1)) {
418 	base_cmd = pci_attr_r32(devind, PCI_BAR_3) & PCI_BAR_IO_MASK;
419 	base_ctl = pci_attr_r32(devind, PCI_BAR_4) & PCI_BAR_IO_MASK;
420 	init_drive(2, base_cmd, base_ctl+PCI_CTL_OFF, base_dma, TRUE,
421 		native_hook);
422 	init_drive(3, base_cmd, base_ctl+PCI_CTL_OFF, base_dma, TRUE,
423 		native_hook);
424 	if (w_pci_debug)
425 		printf("at_wini%ld: native 1 on %d: 0x%x 0x%x irq %d\n",
426 			w_instance, devind, base_cmd, base_ctl, irq);
427   } else {
428 	/* Register secondary compatibility IRQ. */
429 	compat_hook = nhooks++;
430 	if ((r = sys_irqsetpolicy(AT_WINI_1_IRQ, IRQ_REENABLE,
431 		&compat_hook)) != OK)
432 		panic("couldn't set compat(1) IRQ policy: %d", r);
433 	if ((r = sys_irqenable(&compat_hook)) != OK)
434 		panic("couldn't enable compat(1) IRQ line: %d", r);
435 
436 	init_drive(2, REG_CMD_BASE1, REG_CTL_BASE1, base_dma, FALSE,
437 		compat_hook);
438 	init_drive(3, REG_CMD_BASE1, REG_CTL_BASE1, base_dma, FALSE,
439 		compat_hook);
440 
441 	if (w_pci_debug)
442 		printf("at_wini%ld: compat 1 on %d\n", w_instance, devind);
443   }
444 
445   /* Enable busmastering if necessary. */
446   cr = pci_attr_r16(devind, PCI_CR);
447   if (!(cr & PCI_CR_MAST_EN))
448 	pci_attr_w16(devind, PCI_CR, cr | PCI_CR_MAST_EN);
449 }
450 
451 /*===========================================================================*
452  *				w_do_open				     *
453  *===========================================================================*/
454 static int w_do_open(devminor_t minor, int access)
455 {
456 /* Device open: Initialize the controller and read the partition table. */
457 
458   struct wini *wn;
459 
460   if (w_prepare(minor) == NULL) return(ENXIO);
461 
462   wn = w_wn;
463 
464   /* If we've probed it before and it failed, don't probe it again. */
465   if (wn->state & IGNORING) return ENXIO;
466 
467   /* If we haven't identified it yet, or it's gone deaf,
468    * (re-)identify it.
469    */
470   if (!(wn->state & IDENTIFIED) || (wn->state & DEAF)) {
471 	/* Try to identify the device. */
472 	if (w_identify() != OK) {
473 #if VERBOSE
474 		printf("%s: identification failed\n", w_name());
475 #endif
476 		if (wn->state & DEAF){
477 			int err = w_reset();
478 			if( err != OK ){
479 				return err;
480 			}
481 		}
482 		wn->state = IGNORING;
483 		return(ENXIO);
484 	}
485 	  /* Do a test transaction unless it's a CD drive (then
486 	   * we can believe the controller, and a test may fail
487 	   * due to no CD being in the drive). If it fails, ignore
488 	   * the device forever.
489 	   */
490 	  if (!(wn->state & ATAPI) && w_io_test() != OK) {
491   		wn->state |= IGNORING;
492 	  	return(ENXIO);
493 	  }
494   }
495 
496    if ((wn->state & ATAPI) && (access & BDEV_W_BIT))
497 	return(EACCES);
498 
499   /* Partition the drive if it's being opened for the first time,
500    * or being opened after being closed.
501    */
502   if (wn->open_ct == 0) {
503 	if (wn->state & ATAPI) {
504 		int r;
505 		if ((r = atapi_open()) != OK) return(r);
506 	}
507 
508 	/* Partition the disk. */
509 	partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY,
510 		wn->state & ATAPI);
511   }
512   wn->open_ct++;
513   return(OK);
514 }
515 
516 /*===========================================================================*
517  *				w_prepare				     *
518  *===========================================================================*/
519 static struct device *w_prepare(devminor_t device)
520 {
521   /* Prepare for I/O on a device. */
522   w_device = (int) device;
523 
524   if (device >= 0 && device < NR_MINORS) {	/* d0, d0p[0-3], d1, ... */
525 	w_drive = device / DEV_PER_DRIVE;	/* save drive number */
526 	if (w_drive >= MAX_DRIVES) return(NULL);
527 	w_wn = &wini[w_drive];
528 	w_dv = &w_wn->part[device % DEV_PER_DRIVE];
529   } else
530   if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/
531 	w_drive = device / SUB_PER_DRIVE;
532 	if (w_drive >= MAX_DRIVES) return(NULL);
533 	w_wn = &wini[w_drive];
534 	w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
535   } else {
536   	w_device = -1;
537 	return(NULL);
538   }
539   return(w_dv);
540 }
541 
542 /*===========================================================================*
543  *				w_part					     *
544  *===========================================================================*/
545 static struct device *w_part(devminor_t device)
546 {
547 /* Return a pointer to the partition information of the given minor device. */
548 
549   return w_prepare(device);
550 }
551 
552 #define id_byte(n)	(&tmp_buf[2 * (n)])
553 #define id_word(n)	(((u16_t) id_byte(n)[0] <<  0) \
554 			|((u16_t) id_byte(n)[1] <<  8))
555 #define id_longword(n)	(((u32_t) id_byte(n)[0] <<  0) \
556 			|((u32_t) id_byte(n)[1] <<  8) \
557 			|((u32_t) id_byte(n)[2] << 16) \
558 			|((u32_t) id_byte(n)[3] << 24))
559 
560 /*===========================================================================*
561  *				check_dma				     *
562  *===========================================================================*/
563 static void
564 check_dma(struct wini *wn)
565 {
566 	u32_t dma_status, dma_base;
567 	int id_dma, ultra_dma;
568 	u16_t w;
569 
570 	wn->dma= 0;
571 
572 	if (disable_dma)
573 		return;
574 
575 	w= id_word(ID_CAPABILITIES);
576 	id_dma= !!(w & ID_CAP_DMA);
577 	w= id_byte(ID_FIELD_VALIDITY)[0];
578 	ultra_dma= !!(w & ID_FV_88);
579 	dma_base= wn->base_dma;
580 
581 	if (dma_base) {
582 		if (sys_inb(dma_base + DMA_STATUS, &dma_status) != OK) {
583 			panic("unable to read DMA status register");
584 		}
585 	}
586 
587 	if (id_dma && dma_base) {
588 		w= id_word(ID_MULTIWORD_DMA);
589 		if (w_pci_debug &&
590 		(w & (ID_MWDMA_2_SUP|ID_MWDMA_1_SUP|ID_MWDMA_0_SUP))) {
591 			printf(
592 			"%s: multiword DMA modes supported:%s%s%s\n",
593 				w_name(),
594 				(w & ID_MWDMA_0_SUP) ? " 0" : "",
595 				(w & ID_MWDMA_1_SUP) ? " 1" : "",
596 				(w & ID_MWDMA_2_SUP) ? " 2" : "");
597 		}
598 		if (w_pci_debug &&
599 		(w & (ID_MWDMA_0_SEL|ID_MWDMA_1_SEL|ID_MWDMA_2_SEL))) {
600 			printf(
601 			"%s: multiword DMA mode selected:%s%s%s\n",
602 				w_name(),
603 				(w & ID_MWDMA_0_SEL) ? " 0" : "",
604 				(w & ID_MWDMA_1_SEL) ? " 1" : "",
605 				(w & ID_MWDMA_2_SEL) ? " 2" : "");
606 		}
607 		if (w_pci_debug && ultra_dma) {
608 			w= id_word(ID_ULTRA_DMA);
609 			if (w & (ID_UDMA_0_SUP|ID_UDMA_1_SUP|
610 				ID_UDMA_2_SUP|ID_UDMA_3_SUP|
611 				ID_UDMA_4_SUP|ID_UDMA_5_SUP)) {
612 				printf(
613 			"%s: Ultra DMA modes supported:%s%s%s%s%s%s\n",
614 				w_name(),
615 				(w & ID_UDMA_0_SUP) ? " 0" : "",
616 				(w & ID_UDMA_1_SUP) ? " 1" : "",
617 				(w & ID_UDMA_2_SUP) ? " 2" : "",
618 				(w & ID_UDMA_3_SUP) ? " 3" : "",
619 				(w & ID_UDMA_4_SUP) ? " 4" : "",
620 				(w & ID_UDMA_5_SUP) ? " 5" : "");
621 			}
622 			if (w & (ID_UDMA_0_SEL|ID_UDMA_1_SEL|
623 				ID_UDMA_2_SEL|ID_UDMA_3_SEL|
624 				ID_UDMA_4_SEL|ID_UDMA_5_SEL)) {
625 				printf(
626 			"%s: Ultra DMA mode selected:%s%s%s%s%s%s\n",
627 				w_name(),
628 				(w & ID_UDMA_0_SEL) ? " 0" : "",
629 				(w & ID_UDMA_1_SEL) ? " 1" : "",
630 				(w & ID_UDMA_2_SEL) ? " 2" : "",
631 				(w & ID_UDMA_3_SEL) ? " 3" : "",
632 				(w & ID_UDMA_4_SEL) ? " 4" : "",
633 				(w & ID_UDMA_5_SEL) ? " 5" : "");
634 			}
635 		}
636 		wn->dma= 1;
637 	} else if (id_dma || dma_base) {
638 		printf("id_dma %d, dma_base 0x%x\n", id_dma, dma_base);
639 	} else
640 		printf("no DMA support\n");
641 }
642 
643 /*===========================================================================*
644  *				w_identify				     *
645  *===========================================================================*/
646 static int w_identify(void)
647 {
648 /* Find out if a device exists, if it is an old AT disk, or a newer ATA
649  * drive, a removable media device, etc.
650  */
651 
652   struct wini *wn = w_wn;
653   struct command cmd;
654   int s;
655   u16_t w;
656   unsigned long size;
657   int prev_wakeup;
658   int r;
659 
660   /* Try to identify the device. */
661   cmd.ldh     = wn->ldhpref;
662   cmd.command = ATA_IDENTIFY;
663 
664   /* In testing mode, a drive will get ignored at the first timeout. */
665   w_testing = 1;
666 
667   /* Execute *_IDENTIFY with configured *_IDENTIFY timeout. */
668   prev_wakeup = wakeup_ticks;
669   wakeup_ticks = w_identify_wakeup_ticks;
670   r = com_simple(&cmd);
671 
672   if (r == OK && w_waitfor(STATUS_DRQ, STATUS_DRQ) &&
673 	!(wn->w_status & (STATUS_ERR|STATUS_WF))) {
674 
675 	/* Device information. */
676 	if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, SECTOR_SIZE)) != OK)
677 		panic("Call to sys_insw() failed: %d", s);
678 
679 	/* This is an ATA device. */
680 	wn->state |= SMART;
681 
682 	/* Preferred CHS translation mode. */
683 	wn->cylinders = id_word(1);
684 	wn->heads = id_word(3);
685 	wn->sectors = id_word(6);
686 	size = (u32_t) wn->cylinders * wn->heads * wn->sectors;
687 
688 	w= id_word(ID_CAPABILITIES);
689 	if ((w & ID_CAP_LBA) && size > 512L*1024*2) {
690 		/* Drive is LBA capable and is big enough to trust it to
691 		 * not make a mess of it.
692 		 */
693 		wn->ldhpref |= LDH_LBA;
694 		size = id_longword(60);
695 
696 		w= id_word(ID_CSS);
697 		if (size < LBA48_CHECK_SIZE)
698 		{
699 			/* No need to check for LBA48 */
700 		}
701 		else if (w & ID_CSS_LBA48) {
702 			/* Drive is LBA48 capable (and LBA48 is turned on). */
703 			if (id_longword(102)) {
704 				/* If no. of sectors doesn't fit in 32 bits,
705 				 * trunacte to this. So it's LBA32 for now.
706 				 * This can still address devices up to 2TB
707 				 * though.
708 				 */
709 				size = ULONG_MAX;
710 			} else {
711 				/* Actual number of sectors fits in 32 bits. */
712 				size = id_longword(100);
713 			}
714 			wn->lba48 = 1;
715 		}
716 
717 		check_dma(wn);
718 	}
719   } else if (cmd.command = ATAPI_IDENTIFY,
720 	com_simple(&cmd) == OK && w_waitfor(STATUS_DRQ, STATUS_DRQ) &&
721 	!(wn->w_status & (STATUS_ERR|STATUS_WF))) {
722 	/* An ATAPI device. */
723 	wn->state |= ATAPI;
724 
725 	/* Device information. */
726 	if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, 512)) != OK)
727 		panic("Call to sys_insw() failed: %d", s);
728 
729 	size = 0;	/* Size set later. */
730 	check_dma(wn);
731   } else {
732 	/* Not an ATA device; no translations, no special features.  Don't
733 	 * touch it.
734 	 */
735 	wakeup_ticks = prev_wakeup;
736 	w_testing = 0;
737 	return(ERR);
738   }
739 
740   /* Restore wakeup_ticks and unset testing mode. */
741   wakeup_ticks = prev_wakeup;
742   w_testing = 0;
743 
744   /* Size of the whole drive */
745   wn->part[0].dv_size = (u64_t)size * SECTOR_SIZE;
746 
747   /* Reset/calibrate (where necessary) */
748   if (w_specify() != OK && w_specify() != OK) {
749   	return(ERR);
750   }
751 
752   wn->state |= IDENTIFIED;
753   return(OK);
754 }
755 
756 /*===========================================================================*
757  *				w_name					     *
758  *===========================================================================*/
759 static char *w_name(void)
760 {
761 /* Return a name for the current device. */
762   static char name[] = "AT0-D0";
763 
764   name[2] = '0' + w_instance;
765   name[5] = '0' + w_drive;
766   return name;
767 }
768 
769 /*===========================================================================*
770  *				w_io_test				     *
771  *===========================================================================*/
772 static int w_io_test(void)
773 {
774 	int save_dev;
775 	int save_timeout, save_errors, save_wakeup;
776 	iovec_t iov;
777 	static char *buf;
778 	ssize_t r;
779 
780 #define BUFSIZE CD_SECTOR_SIZE
781 	STATICINIT(buf, BUFSIZE);
782 
783 	iov.iov_addr = (vir_bytes) buf;
784 	iov.iov_size = BUFSIZE;
785 	save_dev = w_device;
786 
787 	/* Reduce timeout values for this test transaction. */
788 	save_timeout = timeout_usecs;
789 	save_errors = max_errors;
790 	save_wakeup = wakeup_ticks;
791 
792 	if (!w_standard_timeouts) {
793 		timeout_usecs = 4000000;
794 		wakeup_ticks = system_hz * 6;
795 		max_errors = 3;
796 	}
797 
798 	w_testing = 1;
799 
800 	/* Try I/O on the actual drive (not any (sub)partition). */
801 	r = w_transfer(w_drive * DEV_PER_DRIVE, FALSE /*do_write*/, 0,
802 		SELF, &iov, 1, BDEV_NOFLAGS);
803 
804 	/* Switch back. */
805  	if (w_prepare(save_dev) == NULL)
806  		panic("Couldn't switch back devices");
807 
808  	/* Restore parameters. */
809 	timeout_usecs = save_timeout;
810 	max_errors = save_errors;
811 	wakeup_ticks = save_wakeup;
812 	w_testing = 0;
813 
814  	/* Test if everything worked. */
815 	if (r != BUFSIZE) {
816 		return ERR;
817 	}
818 
819 	/* Everything worked. */
820 	return OK;
821 }
822 
823 /*===========================================================================*
824  *				w_specify				     *
825  *===========================================================================*/
826 static int w_specify(void)
827 {
828 /* Routine to initialize the drive after boot or when a reset is needed. */
829 
830   struct wini *wn = w_wn;
831   struct command cmd;
832 
833   if ((wn->state & DEAF) && w_reset() != OK) {
834   	return(ERR);
835   }
836 
837   if (!(wn->state & ATAPI)) {
838 	/* Specify parameters: precompensation, number of heads and sectors. */
839 	cmd.precomp = 0;
840 	cmd.count   = wn->sectors;
841 	cmd.ldh     = w_wn->ldhpref | (wn->heads - 1);
842 	cmd.command = CMD_SPECIFY;		/* Specify some parameters */
843 
844 	/* Output command block and see if controller accepts the parameters. */
845 	if (com_simple(&cmd) != OK) return(ERR);
846 
847 	if (!(wn->state & SMART)) {
848 		/* Calibrate an old disk. */
849 		cmd.sector  = 0;
850 		cmd.cyl_lo  = 0;
851 		cmd.cyl_hi  = 0;
852 		cmd.ldh     = w_wn->ldhpref;
853 		cmd.command = CMD_RECALIBRATE;
854 
855 		if (com_simple(&cmd) != OK) return(ERR);
856 	}
857   }
858   wn->state |= INITIALIZED;
859   return(OK);
860 }
861 
862 /*===========================================================================*
863  *				do_transfer				     *
864  *===========================================================================*/
865 static int do_transfer(const struct wini *wn, unsigned int count,
866 	unsigned int sector, unsigned int do_write, int do_dma)
867 {
868   	struct command cmd;
869 	unsigned int sector_high;
870 	unsigned secspcyl = wn->heads * wn->sectors;
871 	int do_lba48;
872 
873 	sector_high= 0;	/* For future extensions */
874 
875 	do_lba48= 0;
876 	if (sector >= LBA48_CHECK_SIZE || sector_high != 0)
877 	{
878 		if (wn->lba48)
879 			do_lba48= 1;
880 		else if (sector > LBA_MAX_SIZE || sector_high != 0)
881 		{
882 			/* Strange sector count for LBA device */
883 			return EIO;
884 		}
885 	}
886 
887 	cmd.precomp = 0;
888 	cmd.count   = count;
889 	if (do_dma)
890 	{
891 		cmd.command = do_write ? CMD_WRITE_DMA : CMD_READ_DMA;
892 	}
893 	else
894 		cmd.command = do_write ? CMD_WRITE : CMD_READ;
895 
896 	if (do_lba48) {
897 		if (do_dma)
898 		{
899 			cmd.command = (do_write ?
900 				CMD_WRITE_DMA_EXT : CMD_READ_DMA_EXT);
901 		}
902 		else
903 		{
904 			cmd.command = (do_write ?
905 				CMD_WRITE_EXT : CMD_READ_EXT);
906 		}
907 		cmd.count_prev= (count >> 8);
908 		cmd.sector  = (sector >>  0) & 0xFF;
909 		cmd.cyl_lo  = (sector >>  8) & 0xFF;
910 		cmd.cyl_hi  = (sector >> 16) & 0xFF;
911 		cmd.sector_prev= (sector >> 24) & 0xFF;
912 		cmd.cyl_lo_prev= (sector_high) & 0xFF;
913 		cmd.cyl_hi_prev= (sector_high >> 8) & 0xFF;
914 		cmd.ldh     = wn->ldhpref;
915 
916 		return com_out_ext(&cmd);
917 	} else if (wn->ldhpref & LDH_LBA) {
918 		cmd.sector  = (sector >>  0) & 0xFF;
919 		cmd.cyl_lo  = (sector >>  8) & 0xFF;
920 		cmd.cyl_hi  = (sector >> 16) & 0xFF;
921 		cmd.ldh     = wn->ldhpref | ((sector >> 24) & 0xF);
922 	} else {
923   		int cylinder, head, sec;
924 		cylinder = sector / secspcyl;
925 		head = (sector % secspcyl) / wn->sectors;
926 		sec = sector % wn->sectors;
927 		cmd.sector  = sec + 1;
928 		cmd.cyl_lo  = cylinder & BYTE;
929 		cmd.cyl_hi  = (cylinder >> 8) & BYTE;
930 		cmd.ldh     = wn->ldhpref | head;
931 	}
932 
933 	return com_out(&cmd);
934 }
935 
936 static void stop_dma(const struct wini *wn)
937 {
938 	int r;
939 
940 	/* Stop bus master operation */
941 	r= sys_outb(wn->base_dma + DMA_COMMAND, 0);
942 	if (r != 0) panic("stop_dma: sys_outb failed: %d", r);
943 }
944 
945 static void start_dma(const struct wini *wn, int do_write)
946 {
947 	u32_t v;
948 	int r;
949 
950 	/* Assume disk reads. Start DMA */
951 	v= DMA_CMD_START;
952 	if (!do_write)
953 	{
954 		/* Disk reads generate PCI write cycles. */
955 		v |= DMA_CMD_WRITE;
956 	}
957 	r= sys_outb(wn->base_dma + DMA_COMMAND, v);
958 	if (r != 0) panic("start_dma: sys_outb failed: %d", r);
959 }
960 
961 static int error_dma(const struct wini *wn)
962 {
963 	int r;
964 	u32_t v;
965 
966 #define DMAERR(msg) \
967 	printf("at_wini%ld: bad DMA: %s. Disabling DMA for drive %d.\n",	\
968 		w_instance, msg, wn - wini);				\
969 	printf("at_wini%ld: workaround: set %s=1 in boot monitor.\n", \
970 		w_instance, NO_DMA_VAR); \
971 	return 1;	\
972 
973 	r= sys_inb(wn->base_dma + DMA_STATUS, &v);
974 	if (r != 0) panic("w_transfer: sys_inb failed: %d", r);
975 
976 	if (!wn->dma_intseen) {
977 		/* DMA did not complete successfully */
978 		if (v & DMA_ST_BM_ACTIVE) {
979 			DMAERR("DMA did not complete");
980 		} else if (v & DMA_ST_ERROR) {
981 			DMAERR("DMA error");
982 		} else {
983 			DMAERR("DMA buffer too small");
984 		}
985 	} else if ((v & DMA_ST_BM_ACTIVE)) {
986 		DMAERR("DMA buffer too large");
987 	}
988 
989 	return 0;
990 }
991 
992 
993 /*===========================================================================*
994  *				w_transfer				     *
995  *===========================================================================*/
996 static ssize_t w_transfer(
997   devminor_t minor,		/* minor device to perform the transfer on */
998   int do_write,			/* read or write? */
999   u64_t position,		/* offset on device to read or write */
1000   endpoint_t proc_nr,		/* process doing the request */
1001   iovec_t *iov,			/* pointer to read or write request vector */
1002   unsigned int nr_req,		/* length of request vector */
1003   int UNUSED(flags)		/* transfer flags */
1004 )
1005 {
1006   struct wini *wn;
1007   iovec_t *iop, *iov_end = iov + nr_req;
1008   int r, s, errors, do_dma;
1009   unsigned long block;
1010   u32_t w_status;
1011   u64_t dv_size;
1012   unsigned int n, nbytes;
1013   unsigned dma_buf_offset;
1014   ssize_t total = 0;
1015   size_t addr_offset = 0;
1016 
1017   if (w_prepare(minor) == NULL) return(ENXIO);
1018 
1019   wn = w_wn;
1020   dv_size = w_dv->dv_size;
1021 
1022   if (w_wn->state & ATAPI) {
1023 	return atapi_transfer(do_write, position, proc_nr, iov, nr_req);
1024   }
1025 
1026   /* Check disk address. */
1027   if ((unsigned)(position % SECTOR_SIZE) != 0) return(EINVAL);
1028 
1029   errors = 0;
1030 
1031   while (nr_req > 0) {
1032 	/* How many bytes to transfer? */
1033 	nbytes = 0;
1034 	for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size;
1035 	if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
1036 
1037 	/* Which block on disk and how close to EOF? */
1038 	if (position >= dv_size) return(total);	/* At EOF */
1039 	if (position + nbytes > dv_size)
1040 		nbytes = (unsigned)(dv_size - position);
1041 	block = (unsigned long)((w_dv->dv_base + position) / SECTOR_SIZE);
1042 
1043 	do_dma= wn->dma;
1044 
1045 	if (nbytes >= wn->max_count) {
1046 		/* The drive can't do more then max_count at once. */
1047 		nbytes = wn->max_count;
1048 	}
1049 
1050 	/* First check to see if a reinitialization is needed. */
1051 	if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
1052 
1053 	if (do_dma) {
1054 		stop_dma(wn);
1055 		if (!setup_dma(&nbytes, proc_nr, iov, addr_offset, do_write)) {
1056 			do_dma = 0;
1057 		}
1058 #if 0
1059 		printf("nbytes = %d\n", nbytes);
1060 #endif
1061 	}
1062 
1063 	/* Tell the controller to transfer nbytes bytes. */
1064 	r = do_transfer(wn, (nbytes >> SECTOR_SHIFT), block, do_write, do_dma);
1065 
1066 	if (do_dma)
1067 		start_dma(wn, do_write);
1068 
1069 	if (do_write) {
1070 		/* The specs call for a 400 ns wait after issuing the command.
1071 		 * Reading the alternate status register is the suggested
1072 		 * way to implement this wait.
1073 		 */
1074 		if (sys_inb((wn->base_ctl+REG_CTL_ALTSTAT), &w_status) != OK)
1075 			panic("couldn't get status");
1076 	}
1077 
1078 	if (do_dma) {
1079 		/* Wait for the interrupt, check DMA status and optionally
1080 		 * copy out.
1081 		 */
1082 
1083 		wn->dma_intseen = 0;
1084 		if ((r = at_intr_wait()) != OK)
1085 		{
1086 			/* Don't retry if sector marked bad or too many
1087 			 * errors.
1088 			 */
1089 			if (r == ERR_BAD_SECTOR || ++errors == max_errors) {
1090 				w_command = CMD_IDLE;
1091 				return(EIO);
1092 			}
1093 			continue;
1094 		}
1095 
1096 		/* Wait for DMA_ST_INT to get set */
1097 		if (!wn->dma_intseen) {
1098 			if(w_waitfor_dma(DMA_ST_INT, DMA_ST_INT))
1099 				wn->dma_intseen = 1;
1100 		}
1101 
1102 		if (error_dma(wn)) {
1103 			wn->dma = 0;
1104 			continue;
1105 		}
1106 
1107 		stop_dma(wn);
1108 
1109 		dma_buf_offset= 0;
1110 		while (r == OK && nbytes > 0)
1111 		{
1112 			n= iov->iov_size;
1113 			if (n > nbytes)
1114 				n= nbytes;
1115 
1116 			/* Book the bytes successfully transferred. */
1117 			nbytes -= n;
1118 			position= position + n;
1119 			total += n;
1120 			addr_offset += n;
1121 			if ((iov->iov_size -= n) == 0) {
1122 				iov++; nr_req--; addr_offset = 0;
1123 			}
1124 			dma_buf_offset += n;
1125 		}
1126 	}
1127 
1128 	while (r == OK && nbytes > 0) {
1129 		/* For each sector, wait for an interrupt and fetch the data
1130 		 * (read), or supply data to the controller and wait for an
1131 		 * interrupt (write).
1132 		 */
1133 
1134 		if (!do_write) {
1135 			/* First an interrupt, then data. */
1136 			if ((r = at_intr_wait()) != OK) {
1137 				/* An error, send data to the bit bucket. */
1138 				if (w_wn->w_status & STATUS_DRQ) {
1139 					if ((s=sys_insw(wn->base_cmd+REG_DATA,
1140 						SELF, tmp_buf,
1141 						SECTOR_SIZE)) != OK) {
1142 						panic("Call to sys_insw() failed: %d", s);
1143 					}
1144 				}
1145 				break;
1146 			}
1147 		}
1148 
1149 		/* Wait for busy to clear. */
1150 		if (!w_waitfor(STATUS_BSY, 0)) { r = ERR; break; }
1151 
1152 		/* Wait for data transfer requested. */
1153 		if (!w_waitfor(STATUS_DRQ, STATUS_DRQ)) { r = ERR; break; }
1154 
1155 		/* Copy bytes to or from the device's buffer. */
1156 		if (!do_write) {
1157 		   if(proc_nr != SELF) {
1158 			s=sys_safe_insw(wn->base_cmd + REG_DATA, proc_nr,
1159 				(void *) (iov->iov_addr), addr_offset,
1160 					SECTOR_SIZE);
1161 		   } else {
1162 			s=sys_insw(wn->base_cmd + REG_DATA, proc_nr,
1163 				(void *) (iov->iov_addr + addr_offset),
1164 					SECTOR_SIZE);
1165 		   }
1166 		   if(s != OK) {
1167 			panic("Call to sys_insw() failed: %d", s);
1168 		   }
1169 		} else {
1170 		   if(proc_nr != SELF) {
1171 			s=sys_safe_outsw(wn->base_cmd + REG_DATA, proc_nr,
1172 				(void *) (iov->iov_addr), addr_offset,
1173 				SECTOR_SIZE);
1174 		   } else {
1175 			s=sys_outsw(wn->base_cmd + REG_DATA, proc_nr,
1176 				(void *) (iov->iov_addr + addr_offset),
1177 				SECTOR_SIZE);
1178 		   }
1179 
1180 		   if(s != OK) {
1181 		  	panic("Call to sys_outsw() failed: %d", s);
1182 		   }
1183 
1184 		   /* Data sent, wait for an interrupt. */
1185 		   if ((r = at_intr_wait()) != OK) break;
1186 		}
1187 
1188 		/* Book the bytes successfully transferred. */
1189 		nbytes -= SECTOR_SIZE;
1190 		position = position + SECTOR_SIZE;
1191 		addr_offset += SECTOR_SIZE;
1192 		total += SECTOR_SIZE;
1193 		if ((iov->iov_size -= SECTOR_SIZE) == 0) {
1194 			iov++;
1195 			nr_req--;
1196 			addr_offset = 0;
1197 		}
1198 	}
1199 
1200 	/* Any errors? */
1201 	if (r != OK) {
1202 		/* Don't retry if sector marked bad or too many errors. */
1203 		if (r == ERR_BAD_SECTOR || ++errors == max_errors) {
1204 			w_command = CMD_IDLE;
1205 			return(EIO);
1206 		}
1207 	}
1208   }
1209 
1210   w_command = CMD_IDLE;
1211   return(total);
1212 }
1213 
1214 /*===========================================================================*
1215  *				com_out					     *
1216  *===========================================================================*/
1217 static int com_out(cmd)
1218 struct command *cmd;		/* Command block */
1219 {
1220 /* Output the command block to the winchester controller and return status */
1221 
1222   struct wini *wn = w_wn;
1223   unsigned base_cmd = wn->base_cmd;
1224   unsigned base_ctl = wn->base_ctl;
1225   pvb_pair_t outbyte[7];		/* vector for sys_voutb() */
1226   int s;				/* status for sys_(v)outb() */
1227 
1228   if (w_wn->state & IGNORING) return ERR;
1229 
1230   if (!w_waitfor(STATUS_BSY, 0)) {
1231 	printf("%s: controller not ready\n", w_name());
1232 	return(ERR);
1233   }
1234 
1235   /* Select drive. */
1236   if ((s=sys_outb(base_cmd + REG_LDH, cmd->ldh)) != OK)
1237   	panic("Couldn't write register to select drive: %d", s);
1238 
1239   if (!w_waitfor(STATUS_BSY, 0)) {
1240 	printf("%s: com_out: drive not ready\n", w_name());
1241 	return(ERR);
1242   }
1243 
1244   /* Schedule a wakeup call, some controllers are flaky. This is done with a
1245    * synchronous alarm. If a timeout occurs a notify from CLOCK is sent, so that
1246    * w_intr_wait() can call w_timeout() in case the controller was not able to
1247    * execute the command. Leftover timeouts are simply ignored by the main loop.
1248    */
1249   sys_setalarm(wakeup_ticks, 0);
1250 
1251   wn->w_status = STATUS_ADMBSY;
1252   w_command = cmd->command;
1253   pv_set(outbyte[0], base_ctl + REG_CTL, wn->heads >= 8 ? CTL_EIGHTHEADS : 0);
1254   pv_set(outbyte[1], base_cmd + REG_PRECOMP, cmd->precomp);
1255   pv_set(outbyte[2], base_cmd + REG_COUNT, cmd->count);
1256   pv_set(outbyte[3], base_cmd + REG_SECTOR, cmd->sector);
1257   pv_set(outbyte[4], base_cmd + REG_CYL_LO, cmd->cyl_lo);
1258   pv_set(outbyte[5], base_cmd + REG_CYL_HI, cmd->cyl_hi);
1259   pv_set(outbyte[6], base_cmd + REG_COMMAND, cmd->command);
1260   if ((s=sys_voutb(outbyte,7)) != OK)
1261   	panic("Couldn't write registers with sys_voutb(): %d", s);
1262   return(OK);
1263 }
1264 
1265 /*===========================================================================*
1266  *				com_out_ext				     *
1267  *===========================================================================*/
1268 static int com_out_ext(cmd)
1269 struct command *cmd;		/* Command block */
1270 {
1271 /* Output the command block to the winchester controller and return status */
1272 
1273   struct wini *wn = w_wn;
1274   unsigned base_cmd = wn->base_cmd;
1275   unsigned base_ctl = wn->base_ctl;
1276   pvb_pair_t outbyte[11];		/* vector for sys_voutb() */
1277   int s;				/* status for sys_(v)outb() */
1278 
1279   if (w_wn->state & IGNORING) return ERR;
1280 
1281   if (!w_waitfor(STATUS_BSY, 0)) {
1282 	printf("%s: controller not ready\n", w_name());
1283 	return(ERR);
1284   }
1285 
1286   /* Select drive. */
1287   if ((s=sys_outb(base_cmd + REG_LDH, cmd->ldh)) != OK)
1288   	panic("Couldn't write register to select drive: %d", s);
1289 
1290   if (!w_waitfor(STATUS_BSY, 0)) {
1291 	printf("%s: com_out: drive not ready\n", w_name());
1292 	return(ERR);
1293   }
1294 
1295   /* Schedule a wakeup call, some controllers are flaky. This is done with a
1296    * synchronous alarm. If a timeout occurs a notify from CLOCK is sent, so that
1297    * w_intr_wait() can call w_timeout() in case the controller was not able to
1298    * execute the command. Leftover timeouts are simply ignored by the main loop.
1299    */
1300   sys_setalarm(wakeup_ticks, 0);
1301 
1302   wn->w_status = STATUS_ADMBSY;
1303   w_command = cmd->command;
1304   pv_set(outbyte[0], base_ctl + REG_CTL, 0);
1305   pv_set(outbyte[1], base_cmd + REG_COUNT, cmd->count_prev);
1306   pv_set(outbyte[2], base_cmd + REG_SECTOR, cmd->sector_prev);
1307   pv_set(outbyte[3], base_cmd + REG_CYL_LO, cmd->cyl_lo_prev);
1308   pv_set(outbyte[4], base_cmd + REG_CYL_HI, cmd->cyl_hi_prev);
1309   pv_set(outbyte[5], base_cmd + REG_COUNT, cmd->count);
1310   pv_set(outbyte[6], base_cmd + REG_SECTOR, cmd->sector);
1311   pv_set(outbyte[7], base_cmd + REG_CYL_LO, cmd->cyl_lo);
1312   pv_set(outbyte[8], base_cmd + REG_CYL_HI, cmd->cyl_hi);
1313   pv_set(outbyte[9], base_cmd + REG_COMMAND, cmd->command);
1314   if ((s=sys_voutb(outbyte, 10)) != OK)
1315   	panic("Couldn't write registers with sys_voutb(): %d", s);
1316 
1317   return(OK);
1318 }
1319 /*===========================================================================*
1320  *				setup_dma				     *
1321  *===========================================================================*/
1322 static int setup_dma(
1323   unsigned *sizep,
1324   endpoint_t proc_nr,
1325   iovec_t *iov,
1326   size_t addr_offset,
1327   int UNUSED(do_write)
1328 )
1329 {
1330 	phys_bytes user_phys;
1331 	unsigned n, offset, size;
1332 	int i, j, r;
1333 	u32_t v;
1334 	struct wini *wn = w_wn;
1335 
1336 	/* First try direct scatter/gather to the supplied buffers */
1337 	size= *sizep;
1338 	i= 0;	/* iov index */
1339 	j= 0;	/* prdt index */
1340 	offset= 0;	/* Offset in current iov */
1341 
1342 #if VERBOSE_DMA
1343 	printf("at_wini: setup_dma: proc_nr %d\n", proc_nr);
1344 #endif
1345 
1346 	while (size > 0)
1347 	{
1348 #if VERBOSE_DMA
1349 		printf(
1350 	"at_wini: setup_dma: iov[%d]: addr 0x%lx, size %ld offset %d, size %d\n",
1351 			i, iov[i].iov_addr, iov[i].iov_size, offset, size);
1352 #endif
1353 
1354 		n= iov[i].iov_size-offset;
1355 		if (n > size)
1356 			n= size;
1357 		if (n == 0 || (n & 1))
1358 			panic("bad size in iov: 0x%lx", iov[i].iov_size);
1359 		if(proc_nr != SELF) {
1360 			r= sys_umap(proc_nr, VM_GRANT, iov[i].iov_addr, n,
1361 				&user_phys);
1362 			if (r != 0)
1363 				panic("can't map user buffer (VM_GRANT): %d", r);
1364 			user_phys += offset + addr_offset;
1365 		} else {
1366 			r= sys_umap(proc_nr, VM_D,
1367 				iov[i].iov_addr+offset+addr_offset, n,
1368 				&user_phys);
1369 			if (r != 0)
1370 				panic("can't map user buffer (VM_D): %d", r);
1371 		}
1372 		if (user_phys & 1)
1373 		{
1374 			/* Buffer is not aligned */
1375 			printf("setup_dma: user buffer is not aligned\n");
1376 			return 0;
1377 		}
1378 
1379 		/* vector is not allowed to cross a 64K boundary */
1380 		if (user_phys/0x10000 != (user_phys+n-1)/0x10000)
1381 			n= ((user_phys/0x10000)+1)*0x10000 - user_phys;
1382 
1383 		/* vector is not allowed to be bigger than 64K, but we get that
1384 		 * for free.
1385 		 */
1386 
1387 		if (j >= N_PRDTE)
1388 		{
1389 			/* Too many entries */
1390 			printf("setup_dma: user buffer has too many entries\n");
1391 			return 0;
1392 		}
1393 
1394 		prdt[j].prdte_base= user_phys;
1395 		prdt[j].prdte_count= n;
1396 		prdt[j].prdte_reserved= 0;
1397 		prdt[j].prdte_flags= 0;
1398 		j++;
1399 
1400 		offset += n;
1401 		if (offset >= iov[i].iov_size)
1402 		{
1403 			i++;
1404 			offset= 0;
1405 			addr_offset= 0;
1406 		}
1407 
1408 		size -= n;
1409 	}
1410 
1411 	if (j <= 0 || j > N_PRDTE)
1412 		panic("bad prdt index: %d", j);
1413 	prdt[j-1].prdte_flags |= PRDTE_FL_EOT;
1414 
1415 #if VERBOSE_DMA
1416 	printf("dma not bad\n");
1417 	for (i= 0; i<j; i++) {
1418 		printf("prdt[%d]: base 0x%lx, size %d, flags 0x%x\n",
1419 			i, prdt[i].prdte_base, prdt[i].prdte_count,
1420 			prdt[i].prdte_flags);
1421 	}
1422 #endif
1423 
1424 	/* Verify that the bus master is not active */
1425 	r= sys_inb(wn->base_dma + DMA_STATUS, &v);
1426 	if (r != 0) panic("setup_dma: sys_inb failed: %d", r);
1427 	if (v & DMA_ST_BM_ACTIVE)
1428 		panic("Bus master IDE active");
1429 
1430 	if (prdt_phys & 3)
1431 		panic("prdt not aligned: 0x%lx", prdt_phys);
1432 	r= sys_outl(wn->base_dma + DMA_PRDTP, prdt_phys);
1433 	if (r != 0) panic("setup_dma: sys_outl failed: %d", r);
1434 
1435 	/* Clear interrupt and error flags */
1436 	r= sys_outb(wn->base_dma + DMA_STATUS, DMA_ST_INT | DMA_ST_ERROR);
1437 	if (r != 0) panic("setup_dma: sys_outb failed: %d", r);
1438 
1439 	return 1;
1440 }
1441 
1442 
1443 /*===========================================================================*
1444  *				w_need_reset				     *
1445  *===========================================================================*/
1446 static void w_need_reset(void)
1447 {
1448 /* The controller needs to be reset. */
1449   struct wini *wn;
1450 
1451   for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
1452 	if (wn->base_cmd == w_wn->base_cmd) {
1453 		wn->state |= DEAF;
1454 		wn->state &= ~INITIALIZED;
1455 	}
1456   }
1457 }
1458 
1459 /*===========================================================================*
1460  *				w_do_close				     *
1461  *===========================================================================*/
1462 static int w_do_close(devminor_t minor)
1463 {
1464 /* Device close: Release a device. */
1465   if (w_prepare(minor) == NULL)
1466   	return(ENXIO);
1467   w_wn->open_ct--;
1468   if (w_wn->open_ct == 0 && (w_wn->state & ATAPI)) atapi_close();
1469   return(OK);
1470 }
1471 
1472 /*===========================================================================*
1473  *				com_simple				     *
1474  *===========================================================================*/
1475 static int com_simple(cmd)
1476 struct command *cmd;		/* Command block */
1477 {
1478 /* A simple controller command, only one interrupt and no data-out phase. */
1479   int r;
1480 
1481   if (w_wn->state & IGNORING) return ERR;
1482 
1483   if ((r = com_out(cmd)) == OK) r = at_intr_wait();
1484   w_command = CMD_IDLE;
1485   return(r);
1486 }
1487 
1488 /*===========================================================================*
1489  *				w_timeout				     *
1490  *===========================================================================*/
1491 static void w_timeout(void)
1492 {
1493   struct wini *wn = w_wn;
1494 
1495   switch (w_command) {
1496   case CMD_IDLE:
1497 	break;		/* fine */
1498   case CMD_READ:
1499   case CMD_READ_EXT:
1500   case CMD_WRITE:
1501   case CMD_WRITE_EXT:
1502 	/* Impossible, but not on PC's:  The controller does not respond. */
1503 
1504 	/* Limiting multisector I/O seems to help. */
1505 	if (wn->max_count > 8 * SECTOR_SIZE) {
1506 		wn->max_count = 8 * SECTOR_SIZE;
1507 	} else {
1508 		wn->max_count = SECTOR_SIZE;
1509 	}
1510 	/*FALL THROUGH*/
1511   default:
1512 	/* Some other command. */
1513 	if (w_testing)  wn->state |= IGNORING;	/* Kick out this drive. */
1514 	else if (!w_silent) printf("%s: timeout on command 0x%02x\n",
1515 		w_name(), w_command);
1516 	w_need_reset();
1517 	wn->w_status = 0;
1518   }
1519 }
1520 
1521 /*===========================================================================*
1522  *				w_reset					     *
1523  *===========================================================================*/
1524 static int w_reset(void)
1525 {
1526 /* Issue a reset to the controller.  This is done after any catastrophe,
1527  * like the controller refusing to respond.
1528  */
1529   int s;
1530   struct wini *wn = w_wn;
1531 
1532   /* Don't bother if this drive is forgotten. */
1533   if (w_wn->state & IGNORING) return ERR;
1534 
1535   /* Wait for any internal drive recovery. */
1536   tickdelay(RECOVERY_TICKS);
1537 
1538   /* Strobe reset bit */
1539   if ((s=sys_outb(wn->base_ctl + REG_CTL, CTL_RESET)) != OK)
1540   	panic("Couldn't strobe reset bit: %d", s);
1541   tickdelay(DELAY_TICKS);
1542   if ((s=sys_outb(wn->base_ctl + REG_CTL, 0)) != OK)
1543   	panic("Couldn't strobe reset bit: %d", s);
1544   tickdelay(DELAY_TICKS);
1545 
1546   /* Wait for controller ready */
1547   if (!w_waitfor(STATUS_BSY, 0)) {
1548 	printf("%s: reset failed, drive busy\n", w_name());
1549 	return(ERR);
1550   }
1551 
1552   /* The error register should be checked now, but some drives mess it up. */
1553 
1554   for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
1555 	if (wn->base_cmd == w_wn->base_cmd) {
1556 		wn->state &= ~DEAF;
1557 		if (w_wn->native) {
1558 		    	/* Make sure irq is actually enabled.. */
1559 	  		sys_irqenable(&w_wn->irq_hook_id);
1560 		}
1561 	}
1562   }
1563 
1564   return(OK);
1565 }
1566 
1567 /*===========================================================================*
1568  *				w_intr_wait				     *
1569  *===========================================================================*/
1570 static void w_intr_wait(void)
1571 {
1572 /* Wait for a task completion interrupt. */
1573 
1574   int r;
1575   u32_t w_status;
1576   message m;
1577   int ipc_status;
1578 
1579   if (w_wn->state & IDENTIFIED) {
1580 	/* Wait for an interrupt that sets w_status to "not busy".
1581 	 * (w_timeout() also clears w_status.)
1582 	 */
1583 	while (w_wn->w_status & (STATUS_ADMBSY|STATUS_BSY)) {
1584 		if ((r=driver_receive(ANY, &m, &ipc_status)) != OK)
1585 			panic("driver_receive failed: %d", r);
1586 		if (is_ipc_notify(ipc_status)) {
1587 			switch (_ENDPOINT_P(m.m_source)) {
1588 				case CLOCK:
1589 					/* Timeout. */
1590 					w_timeout(); /* a.o. set w_status */
1591 					break;
1592 				case HARDWARE:
1593 					/* Interrupt. */
1594 					r= sys_inb(w_wn->base_cmd +
1595 							REG_STATUS, &w_status);
1596 					if (r != 0)
1597 						panic("sys_inb failed: %d", r);
1598 					w_wn->w_status= w_status;
1599 					w_hw_int(m.m_notify.interrupts);
1600 					break;
1601 				default:
1602 					/*
1603 					 * unhandled message.  queue it and
1604 					 * handle it in the blockdriver loop.
1605 					 */
1606 					blockdriver_mq_queue(&m, ipc_status);
1607 			}
1608 		}
1609 		else {
1610 			/*
1611 			 * unhandled message.  queue it and handle it in the
1612 			 * blockdriver loop.
1613 			 */
1614 			blockdriver_mq_queue(&m, ipc_status);
1615 		}
1616 	}
1617   } else {
1618 	/* Device not yet identified; use polling. */
1619 	(void) w_waitfor(STATUS_BSY, 0);
1620   }
1621 }
1622 
1623 /*===========================================================================*
1624  *				at_intr_wait				     *
1625  *===========================================================================*/
1626 static int at_intr_wait(void)
1627 {
1628 /* Wait for an interrupt, study the status bits and return error/success. */
1629   int r, s;
1630   u32_t inbval;
1631 
1632   w_intr_wait();
1633   if ((w_wn->w_status & (STATUS_BSY | STATUS_WF | STATUS_ERR)) == 0) {
1634 	r = OK;
1635   } else {
1636   	if ((s=sys_inb(w_wn->base_cmd + REG_ERROR, &inbval)) != OK)
1637   		panic("Couldn't read register: %d", s);
1638   	if ((w_wn->w_status & STATUS_ERR) && (inbval & ERROR_BB)) {
1639   		r = ERR_BAD_SECTOR;	/* sector marked bad, retries won't help */
1640   	} else {
1641   		r = ERR;		/* any other error */
1642   	}
1643   }
1644   w_wn->w_status |= STATUS_ADMBSY;	/* assume still busy with I/O */
1645   return(r);
1646 }
1647 
1648 /*===========================================================================*
1649  *				w_waitfor				     *
1650  *===========================================================================*/
1651 static int w_waitfor(mask, value)
1652 int mask;			/* status mask */
1653 int value;			/* required status */
1654 {
1655 /* Wait until controller is in the required state.  Return zero on timeout.
1656  */
1657   u32_t w_status;
1658   spin_t spin;
1659   int s;
1660 
1661   SPIN_FOR(&spin, timeout_usecs) {
1662 	if ((s=sys_inb(w_wn->base_cmd + REG_STATUS, &w_status)) != OK)
1663 		panic("Couldn't read register: %d", s);
1664 	w_wn->w_status= w_status;
1665 	if ((w_wn->w_status & mask) == value) {
1666         	return 1;
1667 	}
1668   }
1669 
1670   w_need_reset();			/* controller gone deaf */
1671   return(0);
1672 }
1673 
1674 /*===========================================================================*
1675  *				w_waitfor_dma				     *
1676  *===========================================================================*/
1677 static int w_waitfor_dma(mask, value)
1678 unsigned int mask;		/* status mask */
1679 unsigned value;			/* required status */
1680 {
1681 /* Wait until controller is in the required state.  Return zero on timeout.
1682  */
1683   u32_t w_status;
1684   spin_t spin;
1685   int s;
1686 
1687   SPIN_FOR(&spin, timeout_usecs) {
1688 	if ((s=sys_inb(w_wn->base_dma + DMA_STATUS, &w_status)) != OK)
1689 		panic("Couldn't read register: %d", s);
1690 	if ((w_status & mask) == value) {
1691         	return 1;
1692 	}
1693   }
1694 
1695   return(0);
1696 }
1697 
1698 /*===========================================================================*
1699  *				w_geometry				     *
1700  *===========================================================================*/
1701 static void w_geometry(devminor_t minor, struct part_geom *entry)
1702 {
1703   struct wini *wn;
1704 
1705   if (w_prepare(minor) == NULL) return;
1706 
1707   wn = w_wn;
1708 
1709   if (wn->state & ATAPI) {		/* Make up some numbers. */
1710 	entry->cylinders = (unsigned long)(wn->part[0].dv_size / SECTOR_SIZE) / (64*32);
1711 	entry->heads = 64;
1712 	entry->sectors = 32;
1713   } else {				/* Return logical geometry. */
1714 	entry->cylinders = wn->cylinders;
1715 	entry->heads = wn->heads;
1716 	entry->sectors = wn->sectors;
1717 	while (entry->cylinders > 1024) {
1718 		entry->heads *= 2;
1719 		entry->cylinders /= 2;
1720 	}
1721   }
1722 }
1723 
1724 /*===========================================================================*
1725  *				atapi_open				     *
1726  *===========================================================================*/
1727 static int atapi_open(void)
1728 {
1729 /* Should load and lock the device and obtain its size.  For now just set the
1730  * size of the device to something big.  What is really needed is a generic
1731  * SCSI layer that does all this stuff for ATAPI and SCSI devices (kjb). (XXX)
1732  * .."something big" is now the maximum size of the largest type of DVD.
1733  */
1734   w_wn->part[0].dv_size = (u64_t)(8500L*1024) * 1024;
1735   return(OK);
1736 }
1737 
1738 /*===========================================================================*
1739  *				atapi_close				     *
1740  *===========================================================================*/
1741 static void atapi_close(void)
1742 {
1743 /* Should unlock the device.  For now do nothing.  (XXX) */
1744 }
1745 
1746 static void sense_request(void)
1747 {
1748 	int r, i;
1749 	static u8_t sense[100], packet[ATAPI_PACKETSIZE];
1750 
1751 	packet[0] = SCSI_SENSE;
1752 	packet[1] = 0;
1753 	packet[2] = 0;
1754 	packet[3] = 0;
1755 	packet[4] = SENSE_PACKETSIZE;
1756 	packet[5] = 0;
1757 	packet[7] = 0;
1758 	packet[8] = 0;
1759 	packet[9] = 0;
1760 	packet[10] = 0;
1761 	packet[11] = 0;
1762 
1763 	for(i = 0; i < SENSE_PACKETSIZE; i++) sense[i] = 0xff;
1764 	r = atapi_sendpacket(packet, SENSE_PACKETSIZE, 0);
1765 	if (r != OK) { printf("request sense command failed\n"); return; }
1766 	if (atapi_intr_wait(0, 0) <= 0) { printf("WARNING: request response failed\n"); }
1767 
1768 	if (sys_insw(w_wn->base_cmd + REG_DATA, SELF, (void *) sense, SENSE_PACKETSIZE) != OK)
1769 		printf("WARNING: sense reading failed\n");
1770 
1771 	printf("sense data:");
1772 	for(i = 0; i < SENSE_PACKETSIZE; i++) printf(" %02x", sense[i]);
1773 	printf("\n");
1774 }
1775 
1776 /*===========================================================================*
1777  *				atapi_transfer				     *
1778  *===========================================================================*/
1779 static int atapi_transfer(
1780   int do_write,			/* read or write? */
1781   u64_t position,		/* offset on device to read or write */
1782   endpoint_t proc_nr,		/* process doing the request */
1783   iovec_t *iov,			/* pointer to read or write request vector */
1784   unsigned int nr_req		/* length of request vector */
1785 )
1786 {
1787   struct wini *wn = w_wn;
1788   iovec_t *iop, *iov_end = iov + nr_req;
1789   int r, s, errors, fresh;
1790   u64_t pos;
1791   unsigned long block;
1792   u64_t dv_size = w_dv->dv_size;
1793   unsigned nbytes, nblocks, before, chunk;
1794   static u8_t packet[ATAPI_PACKETSIZE];
1795   size_t addr_offset = 0;
1796   int dmabytes = 0, piobytes = 0;
1797   ssize_t total = 0;
1798 
1799   if (do_write) return(EINVAL);
1800 
1801   errors = fresh = 0;
1802 
1803   while (nr_req > 0 && !fresh) {
1804 	int do_dma = wn->dma && w_atapi_dma;
1805 	/* The Minix block size is smaller than the CD block size, so we
1806 	 * may have to read extra before or after the good data.
1807 	 */
1808 	pos = w_dv->dv_base + position;
1809 	block = (unsigned long)(pos / CD_SECTOR_SIZE);
1810 	before = (unsigned)(pos % CD_SECTOR_SIZE);
1811 
1812 	if (before)
1813 		do_dma = 0;
1814 
1815 	/* How many bytes to transfer? */
1816 	nbytes = 0;
1817 	for (iop = iov; iop < iov_end; iop++) {
1818 		nbytes += iop->iov_size;
1819 		if (iop->iov_size % CD_SECTOR_SIZE)
1820 			do_dma = 0;
1821 	}
1822 
1823 	/* Data comes in as words, so we have to enforce even byte counts. */
1824 	if ((before | nbytes) & 1) return(EINVAL);
1825 
1826 	/* Which block on disk and how close to EOF? */
1827 	if (position >= dv_size) return(total);	/* At EOF */
1828 	if (position + nbytes > dv_size)
1829 		nbytes = (unsigned)(dv_size - position);
1830 
1831 	nblocks = (before + nbytes + CD_SECTOR_SIZE - 1) / CD_SECTOR_SIZE;
1832 
1833 	/* First check to see if a reinitialization is needed. */
1834 	if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
1835 
1836 	/* Build an ATAPI command packet. */
1837 	packet[0] = SCSI_READ10;
1838 	packet[1] = 0;
1839 	packet[2] = (block >> 24) & 0xFF;
1840 	packet[3] = (block >> 16) & 0xFF;
1841 	packet[4] = (block >>  8) & 0xFF;
1842 	packet[5] = (block >>  0) & 0xFF;
1843 	packet[6] = 0;
1844 	packet[7] = (nblocks >> 8) & 0xFF;
1845 	packet[8] = (nblocks >> 0) & 0xFF;
1846 	packet[9] = 0;
1847 	packet[10] = 0;
1848 	packet[11] = 0;
1849 
1850 	if(do_dma) {
1851 		stop_dma(wn);
1852 		if (!setup_dma(&nbytes, proc_nr, iov, addr_offset, 0)) {
1853 			do_dma = 0;
1854 		} else if(nbytes != nblocks * CD_SECTOR_SIZE) {
1855 			stop_dma(wn);
1856 			do_dma = 0;
1857 		}
1858 	}
1859 
1860 	/* Tell the controller to execute the packet command. */
1861 	r = atapi_sendpacket(packet, nblocks * CD_SECTOR_SIZE, do_dma);
1862 	if (r != OK) goto err;
1863 
1864 	if(do_dma) {
1865 		wn->dma_intseen = 0;
1866 		start_dma(wn, 0);
1867 		w_intr_wait();
1868 		if(!wn->dma_intseen) {
1869 			if(w_waitfor_dma(DMA_ST_INT, DMA_ST_INT)) {
1870 				wn->dma_intseen = 1;
1871 			}
1872 		}
1873 		if(error_dma(wn)) {
1874 			printf("Disabling DMA (ATAPI)\n");
1875 			wn->dma = 0;
1876 		} else {
1877 			dmabytes += nbytes;
1878 			while (nbytes > 0) {
1879 				chunk = nbytes;
1880 
1881 				if (chunk > iov->iov_size)
1882 					chunk = iov->iov_size;
1883 				position = position + chunk;
1884 				nbytes -= chunk;
1885 				total += chunk;
1886 				if ((iov->iov_size -= chunk) == 0) {
1887 					iov++;
1888 					nr_req--;
1889 				}
1890 			}
1891 		}
1892 		continue;
1893 	}
1894 
1895 	/* Read chunks of data. */
1896 	while ((r = atapi_intr_wait(do_dma, nblocks * CD_SECTOR_SIZE)) > 0) {
1897 		size_t count;
1898 		count = r;
1899 
1900 		while (before > 0 && count > 0) {	/* Discard before. */
1901 			chunk = before;
1902 			if (chunk > count) chunk = count;
1903 			if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
1904 			if ((s=sys_insw(wn->base_cmd + REG_DATA,
1905 				SELF, tmp_buf, chunk)) != OK)
1906 				panic("Call to sys_insw() failed: %d", s);
1907 			before -= chunk;
1908 			count -= chunk;
1909 		}
1910 
1911 		while (nbytes > 0 && count > 0) {	/* Requested data. */
1912 			chunk = nbytes;
1913 			if (chunk > count) chunk = count;
1914 			if (chunk > iov->iov_size) chunk = iov->iov_size;
1915 			if(proc_nr != SELF) {
1916 				s=sys_safe_insw(wn->base_cmd + REG_DATA,
1917 					proc_nr, (void *) iov->iov_addr,
1918 					addr_offset, chunk);
1919 			} else {
1920 				s=sys_insw(wn->base_cmd + REG_DATA, proc_nr,
1921 					(void *) (iov->iov_addr + addr_offset),
1922 					chunk);
1923 			}
1924 			if (s != OK)
1925 				panic("Call to sys_insw() failed: %d", s);
1926 			position = position + chunk;
1927 			nbytes -= chunk;
1928 			count -= chunk;
1929 			addr_offset += chunk;
1930 			piobytes += chunk;
1931 			fresh = 0;
1932 			total += chunk;
1933 			if ((iov->iov_size -= chunk) == 0) {
1934 				iov++;
1935 				nr_req--;
1936 				fresh = 1;	/* new element is optional */
1937 				addr_offset = 0;
1938 			}
1939 
1940 		}
1941 
1942 		while (count > 0) {		/* Excess data. */
1943 			chunk = count;
1944 			if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
1945 			if ((s=sys_insw(wn->base_cmd + REG_DATA,
1946 				SELF, tmp_buf, chunk)) != OK)
1947 				panic("Call to sys_insw() failed: %d", s);
1948 			count -= chunk;
1949 		}
1950 	}
1951 
1952 	if (r < 0) {
1953   err:		/* Don't retry if too many errors. */
1954 		if (atapi_debug) sense_request();
1955 		if (++errors == max_errors) {
1956 			w_command = CMD_IDLE;
1957 			if (atapi_debug) printf("giving up (%d)\n", errors);
1958 			return(EIO);
1959 		}
1960 		if (atapi_debug) printf("retry (%d)\n", errors);
1961 	}
1962   }
1963 
1964 #if 0
1965   if(dmabytes) printf("dmabytes %d ", dmabytes);
1966   if(piobytes) printf("piobytes %d", piobytes);
1967   if(dmabytes || piobytes) printf("\n");
1968 #endif
1969 
1970   w_command = CMD_IDLE;
1971   return(total);
1972 }
1973 
1974 /*===========================================================================*
1975  *				atapi_sendpacket			     *
1976  *===========================================================================*/
1977 static int atapi_sendpacket(packet, cnt, do_dma)
1978 u8_t *packet;
1979 unsigned cnt;
1980 int do_dma;
1981 {
1982 /* Send an Atapi Packet Command */
1983   struct wini *wn = w_wn;
1984   pvb_pair_t outbyte[6];		/* vector for sys_voutb() */
1985   int s;
1986 
1987   if (wn->state & IGNORING) return ERR;
1988 
1989   /* Select Master/Slave drive */
1990   if ((s=sys_outb(wn->base_cmd + REG_DRIVE, wn->ldhpref)) != OK)
1991   	panic("Couldn't select master/ slave drive: %d", s);
1992 
1993   if (!w_waitfor(STATUS_BSY | STATUS_DRQ, 0)) {
1994 	printf("%s: atapi_sendpacket: drive not ready\n", w_name());
1995 	return(ERR);
1996   }
1997 
1998   /* Schedule a wakeup call, some controllers are flaky. This is done with
1999    * a synchronous alarm. If a timeout occurs a SYN_ALARM message is sent
2000    * from HARDWARE, so that w_intr_wait() can call w_timeout() in case the
2001    * controller was not able to execute the command. Leftover timeouts are
2002    * simply ignored by the main loop.
2003    */
2004   sys_setalarm(wakeup_ticks, 0);
2005 
2006   if (cnt > 0xFFFE) cnt = 0xFFFE;	/* Max data per interrupt. */
2007 
2008   w_command = ATAPI_PACKETCMD;
2009   pv_set(outbyte[0], wn->base_cmd + REG_FEAT, do_dma ? FEAT_DMA : 0);
2010   pv_set(outbyte[1], wn->base_cmd + REG_IRR, 0);
2011   pv_set(outbyte[2], wn->base_cmd + REG_SAMTAG, 0);
2012   pv_set(outbyte[3], wn->base_cmd + REG_CNT_LO, (cnt >> 0) & 0xFF);
2013   pv_set(outbyte[4], wn->base_cmd + REG_CNT_HI, (cnt >> 8) & 0xFF);
2014   pv_set(outbyte[5], wn->base_cmd + REG_COMMAND, w_command);
2015   if (atapi_debug) printf("cmd: %x  ", w_command);
2016   if ((s=sys_voutb(outbyte,6)) != OK)
2017   	panic("Couldn't write registers with sys_voutb(): %d", s);
2018 
2019   if (!w_waitfor(STATUS_BSY | STATUS_DRQ, STATUS_DRQ)) {
2020 	printf("%s: timeout (BSY|DRQ -> DRQ)\n", w_name());
2021 	return(ERR);
2022   }
2023   wn->w_status |= STATUS_ADMBSY;		/* Command not at all done yet. */
2024 
2025   /* Send the command packet to the device. */
2026   if ((s=sys_outsw(wn->base_cmd + REG_DATA, SELF, packet, ATAPI_PACKETSIZE)) != OK)
2027 	panic("sys_outsw() failed: %d", s);
2028 
2029   return(OK);
2030 }
2031 
2032 /*===========================================================================*
2033  *				w_ioctl					     *
2034  *===========================================================================*/
2035 static int w_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
2036 	cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
2037 {
2038 	int r, timeout, prev, count;
2039 	struct command cmd;
2040 
2041 	switch (request) {
2042 	case DIOCTIMEOUT:
2043 		r= sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&timeout,
2044 			sizeof(timeout));
2045 
2046 		if(r != OK)
2047 		    return r;
2048 
2049 		if (timeout == 0) {
2050 			/* Restore defaults. */
2051 			timeout_usecs = DEF_TIMEOUT_USECS;
2052 			max_errors = MAX_ERRORS;
2053 			wakeup_ticks = WAKEUP_TICKS;
2054 			w_silent = 0;
2055 		} else if (timeout < 0) {
2056 			return EINVAL;
2057 		} else  {
2058 			prev = wakeup_ticks;
2059 
2060 			if (!w_standard_timeouts) {
2061 				/* Set (lower) timeout, lower error
2062 				 * tolerance and set silent mode.
2063 				 */
2064 				wakeup_ticks = timeout;
2065 				max_errors = 3;
2066 				w_silent = 1;
2067 
2068 				timeout = timeout * 1000000 / sys_hz();
2069 
2070 				if (timeout_usecs > timeout)
2071 					timeout_usecs = timeout;
2072 			}
2073 
2074 			r= sys_safecopyto(endpt, grant, 0, (vir_bytes)&prev,
2075 				sizeof(prev));
2076 
2077 			if(r != OK)
2078 				return r;
2079 		}
2080 
2081 		return OK;
2082 
2083 	case DIOCOPENCT:
2084 		if (w_prepare(minor) == NULL) return ENXIO;
2085 		count = w_wn->open_ct;
2086 		r= sys_safecopyto(endpt, grant, 0, (vir_bytes)&count,
2087 			sizeof(count));
2088 
2089 		if(r != OK)
2090 			return r;
2091 
2092 		return OK;
2093 
2094 	case DIOCFLUSH:
2095 		if (w_prepare(minor) == NULL) return ENXIO;
2096 
2097 		if (w_wn->state & ATAPI) return EINVAL;
2098 
2099 		if (!(w_wn->state & INITIALIZED) && w_specify() != OK)
2100 			return EIO;
2101 
2102 		cmd.command = CMD_FLUSH_CACHE;
2103 
2104 		if (com_simple(&cmd) != OK || !w_waitfor(STATUS_BSY, 0))
2105 			return EIO;
2106 
2107 		return (w_wn->w_status & (STATUS_ERR|STATUS_WF)) ? EIO : OK;
2108 	}
2109 
2110 	return ENOTTY;
2111 }
2112 
2113 /*===========================================================================*
2114  *				w_hw_int				     *
2115  *===========================================================================*/
2116 static void w_hw_int(unsigned int UNUSED(irqs))
2117 {
2118   /* Leftover interrupt(s) received; ack it/them.  For native drives only. */
2119   unsigned int drive;
2120   u32_t w_status;
2121 
2122   for (drive = 0; drive < MAX_DRIVES; drive++) {
2123 	if (!(wini[drive].state & IGNORING) && wini[drive].native) {
2124 		if (sys_inb((wini[drive].base_cmd + REG_STATUS),
2125 			&w_status) != OK)
2126 		{
2127 		  	panic("couldn't ack irq on drive: %d", drive);
2128 		}
2129 		wini[drive].w_status= w_status;
2130   		sys_inb(wini[drive].base_dma + DMA_STATUS, &w_status);
2131   		if(w_status & DMA_ST_INT) {
2132 	  		sys_outb(wini[drive].base_dma + DMA_STATUS, DMA_ST_INT);
2133 	  		wini[drive].dma_intseen = 1;
2134   		}
2135 	 	if (sys_irqenable(&wini[drive].irq_hook_id) != OK)
2136 		  	printf("couldn't re-enable drive %d\n", drive);
2137 	}
2138   }
2139 }
2140 
2141 
2142 #define STSTR(a) if (status & STATUS_ ## a) strlcat(str, #a " ", sizeof(str));
2143 #define ERRSTR(a) if (e & ERROR_ ## a) strlcat(str, #a " ", sizeof(str));
2144 static char *strstatus(int status)
2145 {
2146 	static char str[200];
2147 	str[0] = '\0';
2148 
2149 	STSTR(BSY);
2150 	STSTR(DRDY);
2151 	STSTR(DMADF);
2152 	STSTR(SRVCDSC);
2153 	STSTR(DRQ);
2154 	STSTR(CORR);
2155 	STSTR(CHECK);
2156 	return str;
2157 }
2158 
2159 static char *strerr(int e)
2160 {
2161 	static char str[200];
2162 	str[0] = '\0';
2163 
2164 	ERRSTR(BB);
2165 	ERRSTR(ECC);
2166 	ERRSTR(ID);
2167 	ERRSTR(AC);
2168 	ERRSTR(TK);
2169 	ERRSTR(DM);
2170 
2171 	return str;
2172 }
2173 
2174 /*===========================================================================*
2175  *				atapi_intr_wait				     *
2176  *===========================================================================*/
2177 static int atapi_intr_wait(int UNUSED(do_dma), size_t UNUSED(max))
2178 {
2179 /* Wait for an interrupt and study the results.  Returns a number of bytes
2180  * that need to be transferred, or an error code.
2181  */
2182   struct wini *wn = w_wn;
2183   pvb_pair_t inbyte[4];		/* vector for sys_vinb() */
2184   int s;			/* status for sys_vinb() */
2185   int e;
2186   int len;
2187   int irr;
2188   int r;
2189   int phase;
2190 
2191   w_intr_wait();
2192 
2193   /* Request series of device I/O. */
2194   inbyte[0].port = wn->base_cmd + REG_ERROR;
2195   inbyte[1].port = wn->base_cmd + REG_CNT_LO;
2196   inbyte[2].port = wn->base_cmd + REG_CNT_HI;
2197   inbyte[3].port = wn->base_cmd + REG_IRR;
2198   if ((s=sys_vinb(inbyte, 4)) != OK)
2199   	panic("ATAPI failed sys_vinb(): %d", s);
2200   e = inbyte[0].value;
2201   len = inbyte[1].value;
2202   len |= inbyte[2].value << 8;
2203   irr = inbyte[3].value;
2204 
2205   if (wn->w_status & (STATUS_BSY | STATUS_CHECK)) {
2206 	if (atapi_debug) {
2207 		printf("atapi fail:  S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
2208 	}
2209   	return ERR;
2210   }
2211 
2212   phase = (wn->w_status & STATUS_DRQ) | (irr & (IRR_COD | IRR_IO));
2213 
2214   switch (phase) {
2215   case IRR_COD | IRR_IO:
2216 	if (ATAPI_DEBUG) printf("ACD: Phase Command Complete\n");
2217 	r = OK;
2218 	break;
2219   case 0:
2220 	if (ATAPI_DEBUG) printf("ACD: Phase Command Aborted\n");
2221 	r = ERR;
2222 	break;
2223   case STATUS_DRQ | IRR_COD:
2224 	if (ATAPI_DEBUG) printf("ACD: Phase Command Out\n");
2225 	r = ERR;
2226 	break;
2227   case STATUS_DRQ:
2228 	if (ATAPI_DEBUG) printf("ACD: Phase Data Out %d\n", len);
2229 	r = len;
2230 	break;
2231   case STATUS_DRQ | IRR_IO:
2232 	if (ATAPI_DEBUG) printf("ACD: Phase Data In %d\n", len);
2233 	r = len;
2234 	break;
2235   default:
2236 	if (ATAPI_DEBUG) printf("ACD: Phase Unknown\n");
2237 	r = ERR;
2238 	break;
2239   }
2240 
2241   wn->w_status |= STATUS_ADMBSY;	/* Assume not done yet. */
2242   return(r);
2243 }
2244