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