Home | History | Annotate | Line # | Download | only in boot
      1  1.12    andvar /*	$NetBSD: fd.c,v 1.12 2022/08/07 11:06:18 andvar Exp $	*/
      2   1.1  sakamoto 
      3   1.1  sakamoto /*-
      4   1.5    keihan  * Copyright (C) 1997-1998 Kazuki Sakamoto (sakamoto (at) NetBSD.org)
      5   1.1  sakamoto  * All rights reserved.
      6   1.1  sakamoto  *
      7   1.1  sakamoto  * Floppy Disk Drive standalone device driver
      8   1.1  sakamoto  *
      9   1.1  sakamoto  * Redistribution and use in source and binary forms, with or without
     10   1.1  sakamoto  * modification, are permitted provided that the following conditions
     11   1.1  sakamoto  * are met:
     12   1.1  sakamoto  * 1. Redistributions of source code must retain the above copyright
     13   1.1  sakamoto  *    notice, this list of conditions and the following disclaimer.
     14   1.1  sakamoto  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1  sakamoto  *    notice, this list of conditions and the following disclaimer in the
     16   1.1  sakamoto  *    documentation and/or other materials provided with the distribution.
     17   1.1  sakamoto  * 3. All advertising materials mentioning features or use of this software
     18   1.1  sakamoto  *    must display the following acknowledgement:
     19   1.1  sakamoto  *      This product includes software developed by Kazuki Sakamoto.
     20   1.1  sakamoto  * 4. The name of the author may not be used to endorse or promote products
     21   1.1  sakamoto  *    derived from this software without specific prior written permission.
     22   1.1  sakamoto  *
     23   1.1  sakamoto  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     24   1.1  sakamoto  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25   1.1  sakamoto  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26   1.1  sakamoto  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     27   1.1  sakamoto  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     28   1.1  sakamoto  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     29   1.1  sakamoto  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     30   1.1  sakamoto  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     31   1.1  sakamoto  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     32   1.1  sakamoto  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33   1.1  sakamoto  */
     34   1.1  sakamoto 
     35   1.1  sakamoto #include <sys/param.h>
     36   1.6  junyoung #include <lib/libsa/stand.h>
     37   1.3  sakamoto #include "boot.h"
     38   1.1  sakamoto 
     39   1.1  sakamoto /*---------------------------------------------------------------------------*
     40   1.1  sakamoto  *			Floppy Disk Controller Define			     *
     41   1.1  sakamoto  *---------------------------------------------------------------------------*/
     42   1.3  sakamoto /* Floppy Disk Controller Registers */
     43   1.1  sakamoto int FDC_PORT[] = {				/* fdc base I/O port */
     44   1.1  sakamoto 		0x3f0, /* primary */
     45   1.1  sakamoto 		};
     46   1.3  sakamoto #define	FDC_DOR(x)	(FDC_PORT[x] + 0x2)	/* motor drive control bits */
     47   1.3  sakamoto #define	FDC_STATUS(x)	(FDC_PORT[x] + 0x4)	/* fdc main status register */
     48   1.3  sakamoto #define	FDC_DATA(x)	(FDC_PORT[x] + 0x5)	/* fdc data register */
     49   1.3  sakamoto #define	FDC_RATE(x)	(FDC_PORT[x] + 0x7)	/* transfer rate register */
     50   1.1  sakamoto 
     51   1.1  sakamoto #define	FDC_IRQ		6
     52   1.1  sakamoto #define	FD_DMA_CHAN	2
     53   1.1  sakamoto 
     54   1.1  sakamoto /* fdc main status register */
     55   1.1  sakamoto #define	RQM	  0x80	/* the host can transfer data if set */
     56   1.1  sakamoto #define	DIO	  0x40	/* direction of data transfer. write required if set */
     57   1.3  sakamoto #define	NON_DMA   0x20  /* fdc have date for transfer in non dma mode */
     58   1.1  sakamoto #define	CMD_BUSY  0x10	/* command busy if set */
     59   1.1  sakamoto 
     60   1.1  sakamoto /* fdc result status */
     61   1.1  sakamoto #define	ST0_IC_MASK	0xc0	/* interrupt code  00:normal terminate */
     62   1.1  sakamoto #define	ST1_EN		0x80	/* end of cylinder */
     63   1.1  sakamoto 
     64   1.1  sakamoto /* fdc digtal output register */
     65   1.1  sakamoto #define	DOR_DMAEN	0x08	/* DRQ, nDACK, TC and FINTR output enable */
     66   1.1  sakamoto #define	DOR_RESET	0x04	/* fdc software reset */
     67   1.1  sakamoto 
     68   1.1  sakamoto /* fdc command */
     69   1.1  sakamoto #define	CMD_RECALIBRATE	0x07	/* recalibrate */
     70   1.1  sakamoto #define	CMD_SENSE_INT	0x08	/* sense interrupt status */
     71   1.1  sakamoto #define	CMD_DRV_SENSE	0x04	/* sense drive status */
     72   1.1  sakamoto #define	CMD_SEEK	0x0f	/* seek */
     73   1.1  sakamoto #define	CMD_FORMAT	0x4d	/* format */
     74   1.1  sakamoto #define	CMD_READ	0x46	/* read e6 */
     75   1.1  sakamoto #define	CMD_WRITE	0xc5	/* write */
     76   1.1  sakamoto #define	CMD_VERIFY	0xf6	/* verify */
     77   1.1  sakamoto #define	CMD_READID	0x4a	/* readID */
     78   1.1  sakamoto #define	CMD_SPECIFY	0x03	/* specify */
     79   1.1  sakamoto #define	CMD_CONFIG	0x13	/* config */
     80   1.1  sakamoto #define	CMD_VERSION	0x10	/* version */
     81   1.1  sakamoto 
     82   1.1  sakamoto /* command specify value */
     83   1.1  sakamoto #define	SPECIFY1	((0x0d<<4)|0x0f)
     84   1.1  sakamoto #define	SPECIFY2	((0x01<<1)|0)	/* DMA MODE */
     85   1.1  sakamoto 
     86   1.1  sakamoto /* fdc result */
     87   1.1  sakamoto #define	STATUS_MAX	16	/* result status max number */
     88   1.3  sakamoto #define	RESULT_VERSION	0x90	/* enhanced controller */
     89   1.1  sakamoto #define	RESULT_SEEK	0x20	/* seek & recalibrate complete flag on status0 */
     90   1.1  sakamoto 
     91   1.1  sakamoto /*---------------------------------------------------------------------------*
     92   1.1  sakamoto  *			     Floppy Disk Type Define	 		     *
     93   1.1  sakamoto  *---------------------------------------------------------------------------*/
     94   1.1  sakamoto struct	fdd_type {
     95   1.1  sakamoto 	int	seccount;	/* sector per track */
     96  1.12    andvar 	int	secsize;	/* byte per sector (uPD765 parameter) */
     97   1.1  sakamoto 	int	datalen;	/* data length */
     98   1.1  sakamoto 	int	gap;		/* gap */
     99   1.1  sakamoto 	int	gaplen;		/* gap length */
    100   1.1  sakamoto 	int	cylinder;	/* track per media */
    101   1.1  sakamoto 	int	maxseccount;	/* media max sector count */
    102   1.1  sakamoto 	int	step;		/* seek step */
    103   1.1  sakamoto 	int	rate;		/* drive rate (250 or 500kbps) */
    104   1.1  sakamoto 	int	heads;		/* heads */
    105   1.1  sakamoto 	int	f_gap;		/* format gap */
    106   1.1  sakamoto 	int	mselect;	/* drive mode select */
    107   1.1  sakamoto 	char	*type_name;	/* media type name */
    108   1.1  sakamoto };
    109   1.1  sakamoto typedef struct	fdd_type FDDTYPE;
    110   1.1  sakamoto 
    111   1.3  sakamoto #define	FDTYPE_MAX	5
    112   1.1  sakamoto FDDTYPE fdd_types[FDTYPE_MAX] = {
    113   1.1  sakamoto 	{ 18,2,0xff,0x1b,0x54,80,2880,1,0,2,0x6c,0,"2HQ" }, /* 2HD (PC/AT) */
    114   1.1  sakamoto 	{  8,3,0xff,0x35,0x74,77,1232,1,0,2,0x54,1,"2HD" }, /* 2HD (98) */
    115   1.1  sakamoto 	{ 15,2,0xff,0x1b,0x54,80,2400,1,0,2,0x54,1,"2HC" }, /* 2HC */
    116   1.1  sakamoto 	{  9,2,0xff,0x23,0x50,80,1440,1,2,2,0x50,1,"2DD9" },/* 2DD 9 sector */
    117   1.1  sakamoto 	{  8,2,0xff,0x3a,0x50,80,1280,1,2,2,0x50,1,"2DD8" },/* 2DD 8 sector */
    118   1.1  sakamoto };
    119   1.1  sakamoto 
    120   1.1  sakamoto int	fdsectors[] = {128, 256, 512, 1024, 2048, 4096};
    121   1.1  sakamoto #define	SECTOR_MAX	4096
    122   1.1  sakamoto #define	FDBLK	(fdsectors[un->un_type->secsize])
    123   1.1  sakamoto 
    124   1.1  sakamoto #define	START_CYL	0
    125   1.1  sakamoto #define	START_SECTOR	1
    126   1.1  sakamoto 
    127   1.1  sakamoto #define	DELAY(x)	delay(100000 * x)		/* about 100ms */
    128   1.3  sakamoto #define	INT_TIMEOUT	3000000
    129   1.1  sakamoto 
    130   1.1  sakamoto /*---------------------------------------------------------------------------*
    131   1.1  sakamoto  *			FDC Device Driver Define			     *
    132   1.1  sakamoto  *---------------------------------------------------------------------------*/
    133   1.1  sakamoto #define	CTLR_MAX	1
    134   1.1  sakamoto #define	UNIT_MAX	2
    135   1.1  sakamoto 
    136   1.1  sakamoto struct	fd_unit {
    137   1.1  sakamoto 	int	ctlr;
    138   1.1  sakamoto 	int	unit;
    139   1.1  sakamoto 	u_int	un_flags;		/* unit status flag */
    140   1.1  sakamoto 	int	stat[STATUS_MAX];	/* result code */
    141   1.1  sakamoto 	FDDTYPE	*un_type;		/* floppy type (pointer) */
    142   1.1  sakamoto };
    143   1.1  sakamoto typedef	struct fd_unit FD_UNIT;
    144   1.1  sakamoto FD_UNIT	fd_unit[CTLR_MAX][UNIT_MAX];
    145   1.1  sakamoto 
    146   1.3  sakamoto /*
    147   1.1  sakamoto  *	un_flags flags
    148   1.1  sakamoto  */
    149   1.3  sakamoto #define	INT_ALIVE	0x00000001	/* Device is Alive and Available */
    150   1.3  sakamoto #define	INT_READY	0x00000002	/* Device is Ready */
    151   1.3  sakamoto #define	INT_BUSY	0x00000004	/* Device is busy */
    152   1.1  sakamoto 
    153   1.1  sakamoto /*---------------------------------------------------------------------------*
    154   1.1  sakamoto  *				Misc define				     *
    155   1.1  sakamoto  *---------------------------------------------------------------------------*/
    156   1.1  sakamoto #define	TIMEOUT		10000000
    157   1.1  sakamoto #define	ND_TIMEOUT	10000000
    158   1.1  sakamoto 
    159   1.3  sakamoto #define	SUCCESS		0
    160   1.3  sakamoto #define	FAIL		-1
    161   1.1  sakamoto 
    162   1.1  sakamoto /*
    163   1.1  sakamoto  *	function declaration
    164   1.1  sakamoto  */
    165   1.8  kiyohara int fdinit(FD_UNIT *);
    166  1.10  kiyohara int fdopen(struct open_file *, int, int);
    167   1.8  kiyohara int fdclose(struct open_file *);
    168   1.8  kiyohara int fdioctl(struct open_file *, u_long, void *);
    169   1.8  kiyohara int fdstrategy(void *, int, daddr_t, size_t, void *, size_t *);
    170   1.8  kiyohara int fdc_out(int, int);
    171   1.8  kiyohara int fdc_in(int, u_char *);
    172   1.8  kiyohara int fdc_intr_wait(void);
    173   1.8  kiyohara int fd_check(FD_UNIT *);
    174   1.8  kiyohara void motor_on(int, int);
    175   1.8  kiyohara void motor_off(int, int);
    176   1.8  kiyohara void fdReset(int);
    177   1.8  kiyohara void fdRecalibrate(int, int);
    178   1.8  kiyohara void fdSpecify(int);
    179   1.8  kiyohara void fdDriveStatus(int, int, int, int *);
    180   1.8  kiyohara int fdSeek(int, int, int);
    181   1.8  kiyohara int fdSenseInt(int, int *);
    182   1.8  kiyohara int fdReadWrite(FD_UNIT *, int, int, int, int, u_char *);
    183   1.8  kiyohara void irq_init(void);
    184   1.8  kiyohara int irq_polling(int, int);
    185   1.8  kiyohara void dma_setup(u_char *, int, int, int);
    186   1.8  kiyohara int dma_finished(int);
    187   1.1  sakamoto 
    188   1.1  sakamoto /*===========================================================================*
    189   1.1  sakamoto  *				   fdinit				     *
    190   1.1  sakamoto  *===========================================================================*/
    191   1.3  sakamoto int
    192   1.8  kiyohara fdinit(FD_UNIT *un)
    193   1.1  sakamoto {
    194   1.1  sakamoto 	int ctlr = un->ctlr;
    195   1.3  sakamoto 	u_char result;
    196   1.1  sakamoto 
    197   1.1  sakamoto #if 0
    198   1.1  sakamoto 	irq_init();
    199   1.4    simonb #endif
    200   1.1  sakamoto 	fdReset(ctlr);
    201   1.3  sakamoto 
    202   1.1  sakamoto 	if (fdc_out(ctlr, CMD_VERSION) != SUCCESS) {  /* version check */
    203   1.3  sakamoto 		printf ("fdc%d:fatal error: CMD_VERSION cmd fail\n", ctlr);
    204   1.1  sakamoto 		return (FAIL);
    205   1.1  sakamoto 	}
    206   1.1  sakamoto 	if (fdc_in(ctlr, &result) != SUCCESS) {
    207   1.3  sakamoto 		printf ("fdc%d:fatal error: CMD_VERSION exec fail\n", ctlr);
    208   1.1  sakamoto 		return (FAIL);
    209   1.1  sakamoto 	}
    210   1.3  sakamoto 	if (result != (u_char)RESULT_VERSION) {
    211   1.3  sakamoto 		printf ("fdc%d:fatal error: unknown version fdc\n", ctlr);
    212   1.1  sakamoto 		return (FAIL);
    213   1.1  sakamoto 	}
    214   1.1  sakamoto 
    215   1.1  sakamoto 	un->un_flags = INT_ALIVE;
    216   1.1  sakamoto 	return (SUCCESS);
    217   1.1  sakamoto }
    218   1.1  sakamoto 
    219   1.1  sakamoto /*===========================================================================*
    220   1.1  sakamoto  *				   fdopen				     *
    221   1.1  sakamoto  *===========================================================================*/
    222   1.3  sakamoto int
    223  1.10  kiyohara fdopen(struct open_file *f, int ctlr, int unit)
    224   1.1  sakamoto {
    225   1.1  sakamoto 	FD_UNIT	*un;
    226   1.8  kiyohara 	int *stat;
    227   1.1  sakamoto 
    228   1.1  sakamoto 	if (ctlr >= CTLR_MAX)
    229   1.1  sakamoto 		return (ENXIO);
    230   1.1  sakamoto 	if (unit >= UNIT_MAX)
    231   1.1  sakamoto 		return (ENXIO);
    232   1.1  sakamoto 	un = &fd_unit[ctlr][unit];
    233   1.8  kiyohara 	stat = un->stat;
    234   1.1  sakamoto 
    235   1.1  sakamoto 	if (!(un->un_flags & INT_ALIVE)) {
    236   1.1  sakamoto 		if (fdinit(un) != SUCCESS)
    237   1.1  sakamoto 			return (ENXIO);
    238   1.1  sakamoto 	}
    239   1.1  sakamoto 
    240   1.1  sakamoto 	motor_on(ctlr, unit);
    241   1.1  sakamoto 
    242   1.1  sakamoto 	fdRecalibrate(ctlr, unit);
    243   1.1  sakamoto 	fdSenseInt(ctlr, stat);
    244   1.1  sakamoto 	if (stat[1] != START_CYL) {
    245   1.1  sakamoto 		printf("fdc%d: unit:%d recalibrate failed. status:0x%x cyl:%d\n",
    246   1.1  sakamoto 			ctlr, unit, stat[0], stat[1]);
    247   1.1  sakamoto 		motor_off(ctlr, unit);
    248   1.1  sakamoto 		return (EIO);
    249   1.1  sakamoto 	}
    250   1.1  sakamoto 
    251   1.1  sakamoto 	if (fd_check(un) != SUCCESS)	/* research disk type */
    252   1.1  sakamoto 		return (EIO);
    253   1.1  sakamoto 
    254   1.1  sakamoto 	f->f_devdata = (void *)un;
    255   1.1  sakamoto 	return (SUCCESS);
    256   1.1  sakamoto }
    257   1.1  sakamoto 
    258   1.1  sakamoto /*===========================================================================*
    259   1.1  sakamoto  *				   fdclose				     *
    260   1.1  sakamoto  *===========================================================================*/
    261   1.3  sakamoto int
    262   1.8  kiyohara fdclose(struct open_file *f)
    263   1.1  sakamoto {
    264   1.1  sakamoto 	FD_UNIT *un = f->f_devdata;
    265   1.1  sakamoto 
    266   1.1  sakamoto 	fdRecalibrate(un->ctlr, un->unit);
    267   1.1  sakamoto 	fdSenseInt(un->ctlr, un->stat);
    268   1.1  sakamoto 	motor_off(un->ctlr, un->unit);
    269   1.1  sakamoto 	un->un_flags = 0;
    270   1.1  sakamoto 	return (SUCCESS);
    271   1.1  sakamoto }
    272   1.1  sakamoto 
    273   1.1  sakamoto /*===========================================================================*
    274   1.1  sakamoto  *				   fdioctl				     *
    275   1.1  sakamoto  *===========================================================================*/
    276   1.3  sakamoto int
    277   1.8  kiyohara fdioctl(struct open_file *f, u_long cmd, void *arg)
    278   1.1  sakamoto {
    279   1.8  kiyohara 
    280   1.3  sakamoto 	switch (cmd) {
    281   1.1  sakamoto 	default:
    282   1.1  sakamoto 		return (EIO);
    283   1.1  sakamoto 	}
    284   1.1  sakamoto 
    285   1.1  sakamoto 	return (SUCCESS);
    286   1.1  sakamoto }
    287   1.1  sakamoto 
    288   1.1  sakamoto /*===========================================================================*
    289   1.1  sakamoto  *				   fdstrategy				     *
    290   1.1  sakamoto  *===========================================================================*/
    291   1.3  sakamoto int
    292   1.8  kiyohara fdstrategy(void *devdata, int func, daddr_t blk, size_t size, void *buf,
    293   1.8  kiyohara 	   size_t *rsize)
    294   1.1  sakamoto {
    295   1.1  sakamoto 	int sectrac, cyl, head, sec;
    296   1.1  sakamoto 	FD_UNIT *un = devdata;
    297   1.1  sakamoto 	int ctlr = un->ctlr;
    298   1.1  sakamoto 	int unit = un->unit;
    299   1.1  sakamoto 	int *stat = un->stat;
    300  1.11       phx 	long blknum;
    301   1.1  sakamoto 	int fd_skip = 0;
    302   1.8  kiyohara 	u_char *cbuf = (u_char *)buf;
    303   1.1  sakamoto 
    304   1.3  sakamoto 	if (un->un_flags & INT_BUSY) {
    305   1.1  sakamoto 		return (ENXIO);
    306   1.1  sakamoto 	}
    307   1.1  sakamoto 	fdDriveStatus(ctlr, unit, 0, stat);
    308   1.1  sakamoto 
    309   1.1  sakamoto 	sectrac = un->un_type->seccount;	/* sector per track */
    310   1.1  sakamoto 	*rsize = 0;
    311   1.1  sakamoto 
    312   1.1  sakamoto 	while (fd_skip < size) {
    313   1.1  sakamoto 		blknum = (u_long)blk * DEV_BSIZE/FDBLK + fd_skip/FDBLK;
    314   1.1  sakamoto 		cyl = blknum / (sectrac * 2);
    315   1.1  sakamoto 		fdSeek(ctlr, unit, cyl);
    316   1.1  sakamoto 		fdSenseInt(ctlr, stat);
    317   1.1  sakamoto 		if (!(stat[0] & RESULT_SEEK)) {
    318   1.1  sakamoto 			printf("fdc%d: unit:%d seek failed."
    319   1.1  sakamoto 				"status:0x%x cyl:%d pcyl:%d\n",
    320   1.1  sakamoto 				ctlr, unit, stat[0], cyl, stat[1]);
    321   1.1  sakamoto 			goto bad;
    322   1.1  sakamoto 		}
    323   1.1  sakamoto 
    324   1.1  sakamoto 		sec = blknum % (sectrac * 2);
    325   1.1  sakamoto 		head = sec / sectrac;
    326   1.1  sakamoto 		sec = sec % sectrac + 1;
    327   1.1  sakamoto 
    328   1.1  sakamoto 		if (fdReadWrite(un, func, cyl, head, sec, cbuf) == FAIL) {
    329   1.1  sakamoto 			printf("fdc%d: unit%d fdReadWrite error [%s]\n",
    330   1.1  sakamoto 			    ctlr, unit, (func==F_READ?"READ":"WRITE"));
    331   1.1  sakamoto 			goto bad;
    332   1.1  sakamoto 		}
    333   1.1  sakamoto 
    334   1.1  sakamoto 		*rsize += FDBLK;
    335   1.1  sakamoto 		cbuf += FDBLK;
    336   1.1  sakamoto 		fd_skip += FDBLK;
    337   1.1  sakamoto 	}
    338   1.1  sakamoto 	return (SUCCESS);
    339   1.1  sakamoto 
    340   1.1  sakamoto bad:
    341   1.3  sakamoto 	return (FAIL);
    342   1.1  sakamoto }
    343   1.1  sakamoto 
    344   1.1  sakamoto /*===========================================================================*
    345   1.1  sakamoto  *				   fd_check				     *
    346   1.1  sakamoto  *===========================================================================*/
    347   1.1  sakamoto /*
    348   1.1  sakamoto  *	this function is Check floppy disk Type
    349   1.1  sakamoto  */
    350   1.1  sakamoto int
    351   1.8  kiyohara fd_check(FD_UNIT *un)
    352   1.1  sakamoto {
    353   1.1  sakamoto 	int ctlr = un->ctlr;
    354   1.1  sakamoto 	int unit = un->unit;
    355   1.1  sakamoto 	int *stat = un->stat;
    356   1.1  sakamoto 	int type;
    357   1.1  sakamoto 	static u_char sec_buff[SECTOR_MAX];
    358   1.1  sakamoto 
    359   1.1  sakamoto 	un->un_type = (FDDTYPE *)FAIL;
    360   1.1  sakamoto 	for (type = 0; type < FDTYPE_MAX; type++) {
    361   1.1  sakamoto 		un->un_type = &fdd_types[type];
    362   1.1  sakamoto 
    363   1.1  sakamoto 		/* try read start sector */
    364   1.1  sakamoto 		outb(FDC_RATE(ctlr), un->un_type->rate);   /* rate set */
    365   1.1  sakamoto 		fdSpecify(ctlr);
    366   1.1  sakamoto 		fdSeek(ctlr, unit, START_CYL);
    367   1.1  sakamoto 		fdSenseInt(ctlr, stat);
    368   1.1  sakamoto 		if (!(stat[0] & RESULT_SEEK) || stat[1] != START_CYL) {
    369   1.1  sakamoto 			printf("fdc%d: unit:%d seek failed. status:0x%x\n",
    370   1.1  sakamoto 				ctlr, unit, stat[0]);
    371   1.1  sakamoto 			goto bad;
    372   1.1  sakamoto 		}
    373   1.1  sakamoto 		if (fdReadWrite(un, F_READ,
    374   1.1  sakamoto 		    START_CYL, 0, START_SECTOR, sec_buff) == FAIL) {
    375   1.1  sakamoto 			continue;	/* bad disk type */
    376   1.1  sakamoto 		}
    377   1.1  sakamoto 		break;
    378   1.1  sakamoto 	}
    379   1.1  sakamoto 	if (un->un_type == (FDDTYPE *)FAIL) {
    380   1.1  sakamoto 		printf("fdc%d: unit:%d check disk type failed.\n",
    381   1.1  sakamoto 		ctlr, unit);
    382   1.1  sakamoto 		goto bad;
    383   1.1  sakamoto 	}
    384   1.1  sakamoto 	return (SUCCESS);
    385   1.1  sakamoto bad:
    386   1.1  sakamoto 	return (FAIL);
    387   1.1  sakamoto }
    388   1.1  sakamoto 
    389   1.1  sakamoto /*
    390   1.1  sakamoto  * for FDC routines.
    391   1.1  sakamoto  */
    392   1.1  sakamoto /*===========================================================================*
    393   1.1  sakamoto  *				fdc_out					     *
    394   1.1  sakamoto  *===========================================================================*/
    395   1.1  sakamoto int
    396   1.8  kiyohara fdc_out(int ctlr, int cmd)
    397   1.1  sakamoto {
    398   1.1  sakamoto 	volatile int status;
    399   1.1  sakamoto 	int time_out;
    400   1.1  sakamoto 
    401   1.1  sakamoto 	time_out = TIMEOUT;
    402   1.1  sakamoto 	while (((status = inb(FDC_STATUS(ctlr))) & (RQM | DIO))
    403   1.1  sakamoto 		!= (RQM | 0) && time_out-- > 0);
    404   1.1  sakamoto 	if (time_out <= 0) {
    405   1.3  sakamoto 		printf("fdc_out: timeout  status = 0x%x\n", status);
    406   1.1  sakamoto 		return (FAIL);
    407   1.1  sakamoto 	}
    408   1.1  sakamoto 
    409   1.1  sakamoto 	outb(FDC_DATA(ctlr), cmd);
    410   1.1  sakamoto 
    411   1.1  sakamoto 	return (SUCCESS);
    412   1.1  sakamoto }
    413   1.1  sakamoto 
    414   1.1  sakamoto /*===========================================================================*
    415   1.1  sakamoto  *				fdc_in					     *
    416   1.1  sakamoto  *===========================================================================*/
    417   1.1  sakamoto int
    418   1.8  kiyohara fdc_in(int ctlr, u_char *data)
    419   1.1  sakamoto {
    420   1.1  sakamoto 	volatile int status;
    421   1.1  sakamoto 	int time_out;
    422   1.1  sakamoto 
    423   1.1  sakamoto 	time_out = TIMEOUT;
    424   1.1  sakamoto 	while ((status = inb(FDC_STATUS(ctlr)) & (RQM | DIO))
    425   1.1  sakamoto 	    != (RQM | DIO) && time_out-- > 0) {
    426   1.1  sakamoto 		if (status == RQM) {
    427   1.1  sakamoto 			printf("fdc_in:error:ready for output\n");
    428   1.1  sakamoto 			return (FAIL);
    429   1.1  sakamoto 		}
    430   1.1  sakamoto 	}
    431   1.1  sakamoto 
    432   1.1  sakamoto 	if (time_out <= 0) {
    433   1.1  sakamoto 		printf("fdc_in:input ready timeout\n");
    434   1.1  sakamoto 		return (FAIL);
    435   1.1  sakamoto 	}
    436   1.1  sakamoto 
    437   1.3  sakamoto 	if (data) *data = (u_char)inb(FDC_DATA(ctlr));
    438   1.1  sakamoto 
    439   1.1  sakamoto 	return (SUCCESS);
    440   1.1  sakamoto }
    441   1.1  sakamoto 
    442   1.1  sakamoto /*===========================================================================*
    443   1.1  sakamoto  *                              fdc_intr_wait                                *
    444   1.1  sakamoto  *===========================================================================*/
    445   1.1  sakamoto int
    446   1.9    cegger fdc_intr_wait(void)
    447   1.1  sakamoto {
    448   1.8  kiyohara 
    449   1.3  sakamoto 	return (irq_polling(FDC_IRQ, INT_TIMEOUT));	/* wait interrupt */
    450   1.1  sakamoto }
    451   1.1  sakamoto 
    452   1.1  sakamoto /*===========================================================================*
    453   1.1  sakamoto  *		   	     fdc command function	 	    	     *
    454   1.1  sakamoto  *===========================================================================*/
    455   1.1  sakamoto void
    456   1.8  kiyohara motor_on(int ctlr, int unit)
    457   1.1  sakamoto {
    458   1.8  kiyohara 
    459   1.1  sakamoto 	outb(FDC_DOR(ctlr), DOR_RESET | DOR_DMAEN | unit
    460   1.1  sakamoto 		| (1 << (unit + 4)));	/* reset & unit motor on */
    461   1.1  sakamoto 	DELAY(1);		/* wait 100msec */
    462   1.1  sakamoto }
    463   1.1  sakamoto 
    464   1.1  sakamoto void
    465   1.8  kiyohara motor_off(int ctlr, int unit)
    466   1.1  sakamoto {
    467   1.8  kiyohara 
    468   1.8  kiyohara 	outb(FDC_DOR(ctlr), DOR_RESET);		/* reset & motor off */
    469   1.3  sakamoto 	if (fdc_intr_wait() == FAIL)		/* wait interrupt */
    470   1.1  sakamoto 		printf("fdc: motor off failed.\n");
    471   1.1  sakamoto }
    472   1.1  sakamoto 
    473   1.1  sakamoto void
    474   1.8  kiyohara fdReset(int ctlr)
    475   1.1  sakamoto {
    476   1.8  kiyohara 
    477   1.1  sakamoto 	outb(FDC_DOR(ctlr), 0); /* fdc reset */
    478   1.1  sakamoto 	DELAY(3);
    479   1.1  sakamoto 	outb(FDC_DOR(ctlr), DOR_RESET);
    480   1.1  sakamoto 	DELAY(8);
    481   1.1  sakamoto }
    482   1.1  sakamoto 
    483   1.1  sakamoto void
    484   1.8  kiyohara fdRecalibrate(int ctlr, int unit)
    485   1.1  sakamoto {
    486   1.8  kiyohara 
    487   1.1  sakamoto 	fdc_out(ctlr, CMD_RECALIBRATE);
    488   1.1  sakamoto 	fdc_out(ctlr, unit);
    489   1.1  sakamoto 
    490   1.1  sakamoto 	if (fdc_intr_wait() == FAIL)   /* wait interrupt */
    491   1.1  sakamoto 		printf("fdc: recalibrate Timeout\n");
    492   1.1  sakamoto }
    493   1.1  sakamoto 
    494   1.1  sakamoto void
    495   1.8  kiyohara fdSpecify(int ctlr)
    496   1.1  sakamoto {
    497   1.8  kiyohara 
    498   1.1  sakamoto 	fdc_out(ctlr, CMD_SPECIFY);
    499   1.1  sakamoto 	fdc_out(ctlr, SPECIFY1);
    500   1.1  sakamoto 	fdc_out(ctlr, SPECIFY2);
    501   1.1  sakamoto }
    502   1.1  sakamoto 
    503   1.1  sakamoto void
    504   1.8  kiyohara fdDriveStatus(int ctlr, register int unit, register int head,
    505   1.8  kiyohara 	      register int *stat)
    506   1.1  sakamoto {
    507   1.3  sakamoto 	u_char result;
    508   1.1  sakamoto 
    509   1.1  sakamoto 	fdc_out(ctlr, CMD_DRV_SENSE);
    510   1.1  sakamoto 	fdc_out(ctlr, (head << 2) | unit);
    511   1.1  sakamoto 	fdc_in(ctlr, &result);
    512   1.1  sakamoto 	*stat = (int)(result & 0xff);
    513   1.1  sakamoto }
    514   1.1  sakamoto 
    515   1.1  sakamoto int
    516   1.8  kiyohara fdSeek(int ctlr, int unit, int cyl)
    517   1.1  sakamoto {
    518   1.1  sakamoto 	int ret_val = 0;
    519   1.1  sakamoto 
    520   1.1  sakamoto 	fdc_out(ctlr, CMD_SEEK);
    521   1.1  sakamoto 	fdc_out(ctlr, unit);
    522   1.1  sakamoto 	fdc_out(ctlr, cyl);
    523   1.1  sakamoto 
    524   1.3  sakamoto         if (fdc_intr_wait() == FAIL) {		/* wait interrupt */
    525   1.1  sakamoto 		printf("fdc: fdSeek Timeout\n");
    526   1.1  sakamoto 		ret_val = FAIL;
    527   1.1  sakamoto 	}
    528   1.1  sakamoto 
    529   1.1  sakamoto 	return(ret_val);
    530   1.1  sakamoto }
    531   1.1  sakamoto 
    532   1.1  sakamoto int
    533   1.8  kiyohara fdSenseInt(int ctlr, int *stat)
    534   1.1  sakamoto {
    535   1.3  sakamoto 	u_char result;
    536   1.1  sakamoto 
    537   1.1  sakamoto 	fdc_out(ctlr, CMD_SENSE_INT);
    538   1.1  sakamoto 
    539   1.1  sakamoto 	fdc_in(ctlr, &result);
    540   1.1  sakamoto 	*stat++ = (int)(result & 0xff);
    541   1.1  sakamoto 	fdc_in(ctlr, &result);
    542   1.1  sakamoto 	*stat++ = (int)(result & 0xff);
    543   1.1  sakamoto 
    544   1.3  sakamoto 	return (0);
    545   1.1  sakamoto }
    546   1.1  sakamoto 
    547   1.1  sakamoto int
    548   1.8  kiyohara fdReadWrite(FD_UNIT *un, int func, int cyl, int head, int sec, u_char *adrs)
    549   1.1  sakamoto {
    550   1.1  sakamoto 	int i;
    551   1.1  sakamoto 	int ctlr = un->ctlr;
    552   1.1  sakamoto 	int unit = un->unit;
    553   1.1  sakamoto 	int *stat = un->stat;
    554   1.3  sakamoto 	u_char result;
    555   1.1  sakamoto 
    556   1.1  sakamoto #if 0
    557   1.1  sakamoto printf("%s:", (func == F_READ ? "READ" : "WRITE"));
    558   1.1  sakamoto printf("cyl = %d", cyl);
    559   1.1  sakamoto printf("head = %d", head);
    560   1.1  sakamoto printf("sec = %d", sec);
    561   1.1  sakamoto printf("secsize = %d", un->un_type->secsize);
    562   1.1  sakamoto printf("seccount = %d", un->un_type->seccount);
    563   1.1  sakamoto printf("gap = %d", un->un_type->gap);
    564   1.1  sakamoto printf("datalen = %d\n", un->un_type->datalen);
    565   1.1  sakamoto #endif
    566   1.1  sakamoto 
    567   1.1  sakamoto 	dma_setup(adrs, FDBLK, func, FD_DMA_CHAN);
    568   1.1  sakamoto 	fdc_out(ctlr, (func == F_READ ? CMD_READ : CMD_WRITE));
    569   1.1  sakamoto 	fdc_out(ctlr, (head<<2) | unit);
    570   1.1  sakamoto 	fdc_out(ctlr, cyl);			/* cyl */
    571   1.1  sakamoto 	fdc_out(ctlr, head);			/* head */
    572   1.1  sakamoto 	fdc_out(ctlr, sec);			/* sec */
    573   1.1  sakamoto 	fdc_out(ctlr, un->un_type->secsize);	/* secsize */
    574   1.1  sakamoto 	fdc_out(ctlr, un->un_type->seccount);	/* EOT (end of track) */
    575   1.1  sakamoto 	fdc_out(ctlr, un->un_type->gap);	/* GAP3 */
    576   1.1  sakamoto 	fdc_out(ctlr, un->un_type->datalen);	/* DTL (data length) */
    577   1.1  sakamoto 
    578   1.1  sakamoto 	if (fdc_intr_wait() == FAIL) {  /* wait interrupt */
    579   1.1  sakamoto 		printf("fdc: DMA transfer Timeout\n");
    580   1.1  sakamoto 		return (FAIL);
    581   1.1  sakamoto 	}
    582   1.1  sakamoto 
    583   1.1  sakamoto 	for (i = 0; i < 7; i++) {
    584   1.1  sakamoto 		fdc_in(ctlr, &result);
    585   1.1  sakamoto 		stat[i] = (int)(result & 0xff);
    586   1.1  sakamoto 	}
    587   1.1  sakamoto 	if (stat[0] & ST0_IC_MASK) {	/* not normal terminate */
    588   1.1  sakamoto 		if ((stat[1] & ~ST1_EN) || stat[2])
    589   1.1  sakamoto 		goto bad;
    590   1.1  sakamoto 	}
    591   1.1  sakamoto 	if (!dma_finished(FD_DMA_CHAN)) {
    592   1.1  sakamoto 		printf("DMA not finished\n");
    593   1.1  sakamoto 		goto bad;
    594   1.1  sakamoto 	}
    595   1.1  sakamoto 	return (SUCCESS);
    596   1.1  sakamoto 
    597   1.1  sakamoto bad:
    598   1.1  sakamoto 	printf("       func: %s\n", (func == F_READ ? "F_READ" : "F_WRITE"));
    599   1.1  sakamoto 	printf("	st0 = 0x%x\n", stat[0]);
    600   1.1  sakamoto 	printf("	st1 = 0x%x\n", stat[1]);
    601   1.1  sakamoto 	printf("	st2 = 0x%x\n", stat[2]);
    602   1.1  sakamoto 	printf("	  c = 0x%x\n", stat[3]);
    603   1.1  sakamoto 	printf("	  h = 0x%x\n", stat[4]);
    604   1.1  sakamoto 	printf("	  r = 0x%x\n", stat[5]);
    605   1.1  sakamoto 	printf("	  n = 0x%x\n", stat[6]);
    606   1.1  sakamoto 	return (FAIL);
    607   1.1  sakamoto }
    608   1.1  sakamoto 
    609   1.1  sakamoto /*-----------------------------------------------------------------------
    610   1.1  sakamoto  * Interrupt Controller Operation Functions
    611   1.1  sakamoto  *-----------------------------------------------------------------------
    612   1.1  sakamoto  */
    613   1.1  sakamoto 
    614   1.1  sakamoto /* 8259A interrupt controller register */
    615   1.3  sakamoto #define	INT_CTL0	0x20
    616   1.3  sakamoto #define	INT_CTL1	0x21
    617   1.3  sakamoto #define	INT2_CTL0	0xA0
    618   1.3  sakamoto #define	INT2_CTL1	0xA1
    619   1.1  sakamoto 
    620   1.1  sakamoto #define	CASCADE_IRQ	2
    621   1.1  sakamoto 
    622   1.3  sakamoto #define	ICW1_AT		0x11    /* edge triggered, cascade, need ICW4 */
    623   1.3  sakamoto #define	ICW4_AT		0x01    /* not SFNM, not buffered, normal EOI, 8086 */
    624   1.1  sakamoto #define	OCW3_PL		0x0e	/* polling mode */
    625   1.1  sakamoto #define	OCW2_CLEAR	0x20	/* interrupt clear */
    626   1.1  sakamoto 
    627   1.1  sakamoto /*
    628   1.3  sakamoto  * IRC programing sequence
    629   1.1  sakamoto  *
    630   1.1  sakamoto  * after reset
    631   1.1  sakamoto  * 1.	ICW1 (write port:INT_CTL0 data:bit4=1)
    632   1.1  sakamoto  * 2.	ICW2 (write port:INT_CTL1)
    633   1.1  sakamoto  * 3.	ICW3 (write port:INT_CTL1)
    634   1.1  sakamoto  * 4.	ICW4 (write port:INT_CTL1)
    635   1.3  sakamoto  *
    636   1.1  sakamoto  * after ICW
    637   1.1  sakamoto  *	OCW1 (write port:INT_CTL1)
    638   1.1  sakamoto  *	OCW2 (write port:INT_CTL0 data:bit3=0,bit4=0)
    639   1.1  sakamoto  *	OCW3 (write port:INT_CTL0 data:bit3=1,bit4=0)
    640   1.1  sakamoto  *
    641   1.1  sakamoto  *	IMR  (read port:INT_CTL1)
    642   1.1  sakamoto  *	IRR  (read port:INT_CTL0)	OCW3(bit1=1,bit0=0)
    643   1.1  sakamoto  *	ISR  (read port:INT_CTL0)	OCW3(bit1=1,bit0=1)
    644   1.1  sakamoto  *	PL   (read port:INT_CTL0)	OCW3(bit2=1,bit1=1)
    645   1.1  sakamoto  */
    646   1.1  sakamoto 
    647   1.3  sakamoto u_int INT_MASK;
    648   1.3  sakamoto u_int INT2_MASK;
    649   1.1  sakamoto 
    650   1.1  sakamoto /*===========================================================================*
    651   1.1  sakamoto  *                             irq initialize                                *
    652   1.1  sakamoto  *===========================================================================*/
    653   1.3  sakamoto void
    654   1.9    cegger irq_init(void)
    655   1.1  sakamoto {
    656   1.1  sakamoto 	outb(INT_CTL0, ICW1_AT);		/* ICW1 */
    657   1.1  sakamoto 	outb(INT_CTL1, 0);			/* ICW2 for master */
    658   1.1  sakamoto 	outb(INT_CTL1, (1 << CASCADE_IRQ));	/* ICW3 tells slaves */
    659   1.1  sakamoto 	outb(INT_CTL1, ICW4_AT);		/* ICW4 */
    660   1.1  sakamoto 
    661   1.1  sakamoto 	outb(INT_CTL1, (INT_MASK = ~(1 << CASCADE_IRQ)));
    662   1.1  sakamoto 				/* IRQ mask(exclusive of cascade) */
    663   1.1  sakamoto 
    664   1.1  sakamoto 	outb(INT2_CTL0, ICW1_AT);		/* ICW1 */
    665   1.1  sakamoto 	outb(INT2_CTL1, 8); 			/* ICW2 for slave */
    666   1.1  sakamoto 	outb(INT2_CTL1, CASCADE_IRQ);		/* ICW3 is slave nr */
    667   1.1  sakamoto 	outb(INT2_CTL1, ICW4_AT);		/* ICW4 */
    668   1.1  sakamoto 
    669   1.1  sakamoto 	outb(INT2_CTL1, (INT2_MASK = ~0));	/* IRQ 8-15 mask */
    670   1.1  sakamoto }
    671   1.1  sakamoto 
    672   1.1  sakamoto /*===========================================================================*
    673   1.1  sakamoto  *                           irq polling check                               *
    674   1.1  sakamoto  *===========================================================================*/
    675   1.3  sakamoto int
    676   1.8  kiyohara irq_polling(int irq_no, int timeout)
    677   1.1  sakamoto {
    678   1.1  sakamoto 	int	irc_no;
    679   1.1  sakamoto 	int	data;
    680   1.1  sakamoto 	int	ret;
    681   1.1  sakamoto 
    682   1.1  sakamoto 	if (irq_no > 8) irc_no = 1;
    683   1.1  sakamoto 		else irc_no = 0;
    684   1.1  sakamoto 
    685   1.1  sakamoto 	outb(irc_no ? INT2_CTL1 : INT_CTL1, ~(1 << (irq_no >> (irc_no * 3))));
    686   1.1  sakamoto 
    687   1.3  sakamoto 	while (--timeout > 0) {
    688   1.1  sakamoto 		outb(irc_no ? INT2_CTL0 : INT_CTL0, OCW3_PL);
    689   1.1  sakamoto 						/* set polling mode */
    690   1.1  sakamoto 		data = inb(irc_no ? INT2_CTL0 : INT_CTL0);
    691   1.1  sakamoto 		if (data & 0x80) {	/* if interrupt request */
    692   1.1  sakamoto 			if ((irq_no >> (irc_no * 3)) == (data & 0x7)) {
    693   1.1  sakamoto 				ret = SUCCESS;
    694   1.1  sakamoto 				break;
    695   1.1  sakamoto 			}
    696   1.1  sakamoto 		}
    697   1.1  sakamoto 	}
    698   1.1  sakamoto 	if (!timeout) ret = FAIL;
    699   1.1  sakamoto 
    700   1.1  sakamoto 	if (irc_no) {				/* interrupt clear */
    701   1.1  sakamoto 		outb(INT2_CTL0, OCW2_CLEAR | (irq_no >> 3));
    702   1.1  sakamoto 		outb(INT_CTL0, OCW2_CLEAR | CASCADE_IRQ);
    703   1.1  sakamoto 	} else {
    704   1.1  sakamoto 		outb(INT_CTL0, OCW2_CLEAR | irq_no);
    705   1.1  sakamoto 	}
    706   1.1  sakamoto 
    707   1.1  sakamoto 	outb(INT_CTL1, INT_MASK);
    708   1.1  sakamoto 	outb(INT2_CTL1, INT2_MASK);
    709   1.1  sakamoto 
    710   1.1  sakamoto 	return (ret);
    711   1.1  sakamoto }
    712   1.1  sakamoto 
    713   1.1  sakamoto /*---------------------------------------------------------------------------*
    714   1.1  sakamoto  *			DMA Controller Define			 	     *
    715   1.1  sakamoto  *---------------------------------------------------------------------------*/
    716   1.1  sakamoto /* DMA Controller Registers */
    717   1.3  sakamoto #define	DMA_ADDR	0x004    /* port for low 16 bits of DMA address */
    718   1.3  sakamoto #define	DMA_LTOP	0x081    /* port for top low 8bit DMA addr(ch2) */
    719   1.3  sakamoto #define	DMA_HTOP	0x481    /* port for top high 8bit DMA addr(ch2) */
    720   1.3  sakamoto #define	DMA_COUNT	0x005    /* port for DMA count (count =  bytes - 1) */
    721   1.1  sakamoto #define	DMA_DEVCON	0x008    /* DMA device control register */
    722   1.1  sakamoto #define	DMA_SR		0x008    /* DMA status register */
    723   1.1  sakamoto #define	DMA_RESET	0x00D    /* DMA software reset register */
    724   1.3  sakamoto #define	DMA_FLIPFLOP	0x00C    /* DMA byte pointer flip-flop */
    725   1.3  sakamoto #define	DMA_MODE	0x00B    /* DMA mode port */
    726   1.3  sakamoto #define	DMA_INIT	0x00A    /* DMA init port */
    727   1.1  sakamoto 
    728   1.3  sakamoto #define	DMA_RESET_VAL	0x06
    729   1.1  sakamoto /* DMA channel commands. */
    730   1.3  sakamoto #define	DMA_READ	0x46    /* DMA read opcode */
    731   1.3  sakamoto #define	DMA_WRITE	0x4A    /* DMA write opcode */
    732   1.1  sakamoto 
    733   1.1  sakamoto /*===========================================================================*
    734   1.1  sakamoto  *				dma_setup				     *
    735   1.1  sakamoto  *===========================================================================*/
    736   1.3  sakamoto void
    737   1.8  kiyohara dma_setup(u_char *buf, int size, int func, int chan)
    738   1.1  sakamoto {
    739   1.3  sakamoto 	u_long pbuf = local_to_PCI((u_long)buf);
    740   1.1  sakamoto 
    741   1.1  sakamoto #if 0
    742   1.1  sakamoto 	outb(DMA_RESET, 0);
    743   1.1  sakamoto 	DELAY(1);
    744   1.1  sakamoto 	outb(DMA_DEVCON, 0x00);
    745   1.3  sakamoto 	outb(DMA_INIT, DMA_RESET_VAL);	/* reset the dma controller */
    746   1.1  sakamoto #endif
    747   1.1  sakamoto 	outb(DMA_MODE, func == F_READ ? DMA_READ : DMA_WRITE);
    748   1.3  sakamoto 	outb(DMA_FLIPFLOP, 0);		/* write anything to reset it */
    749   1.1  sakamoto 
    750   1.1  sakamoto 	outb(DMA_ADDR, (int)pbuf >>  0);
    751   1.1  sakamoto 	outb(DMA_ADDR, (int)pbuf >>  8);
    752   1.1  sakamoto 	outb(DMA_LTOP, (int)pbuf >> 16);
    753   1.1  sakamoto 	outb(DMA_HTOP, (int)pbuf >> 24);
    754   1.1  sakamoto 
    755   1.1  sakamoto 	outb(DMA_COUNT, (size - 1) >> 0);
    756   1.1  sakamoto 	outb(DMA_COUNT, (size - 1) >> 8);
    757   1.3  sakamoto 	outb(DMA_INIT, chan);		/* some sort of enable */
    758   1.1  sakamoto }
    759   1.1  sakamoto 
    760   1.1  sakamoto int
    761   1.8  kiyohara dma_finished(int chan)
    762   1.1  sakamoto {
    763   1.8  kiyohara 
    764   1.1  sakamoto 	return ((inb(DMA_SR) & 0x0f) == (1 << chan));
    765   1.1  sakamoto }
    766