devfloppy.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. #include <u.h>
  2. #include "lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "ureg.h"
  8. #include "fs.h"
  9. #include "devfloppy.h"
  10. /* Intel 82077A (8272A compatible) floppy controller */
  11. /* This module expects the following functions to be defined
  12. * elsewhere:
  13. *
  14. * inb()
  15. * outb()
  16. * floppyexec()
  17. * floppyeject()
  18. * floppysetup0()
  19. * floppysetup1()
  20. * dmainit()
  21. * dmasetup()
  22. * dmaend()
  23. *
  24. * On DMA systems, floppyexec() should be an empty function;
  25. * on non-DMA systems, dmaend() should be an empty function;
  26. * dmasetup() may enforce maximum transfer sizes.
  27. */
  28. enum {
  29. /* file types */
  30. Qdir= 0,
  31. Qdata= (1<<2),
  32. Qctl= (2<<2),
  33. Qmask= (3<<2),
  34. DMAchan= 2, /* floppy dma channel */
  35. };
  36. #define DPRINT if(0)print
  37. FType floppytype[] =
  38. {
  39. { "3½HD", T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, },
  40. { "3½DD", T1440kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
  41. { "3½DD", T720kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
  42. { "5¼HD", T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },
  43. { "5¼DD", T1200kb, 512, 9, 2, 2, 40, 0x2A, 0x50, 1, },
  44. { "ATT3B1", T1200kb, 512, 8, 2, 2, 48, 0x2A, 0x50, 1, },
  45. { "5¼DD", T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, },
  46. };
  47. /*
  48. * bytes per sector encoding for the controller.
  49. * - index for b2c is is (bytes per sector/128).
  50. * - index for c2b is code from b2c
  51. */
  52. static int b2c[] =
  53. {
  54. [1] 0,
  55. [2] 1,
  56. [4] 2,
  57. [8] 3,
  58. };
  59. static int c2b[] =
  60. {
  61. 128,
  62. 256,
  63. 512,
  64. 1024,
  65. };
  66. FController fl;
  67. #define MOTORBIT(i) (1<<((i)+4))
  68. /*
  69. * predeclared
  70. */
  71. static int cmddone(void*);
  72. static void floppyformat(FDrive*, char*);
  73. static void floppykproc(void*);
  74. static void floppypos(FDrive*,long);
  75. static int floppyrecal(FDrive*);
  76. static int floppyresult(void);
  77. static void floppyrevive(void);
  78. static vlong pcfloppyseek(FDrive*, vlong);
  79. static int floppysense(void);
  80. static void floppywait(int);
  81. static long floppyxfer(FDrive*, int, void*, long, long);
  82. static void
  83. fldump(void)
  84. {
  85. DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),
  86. inb(Pdor), inb(Pmsr), inb(Pdir));
  87. }
  88. static void
  89. floppyalarm(Alarm* a)
  90. {
  91. FDrive *dp;
  92. for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
  93. if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5)
  94. floppyoff(dp);
  95. }
  96. alarm(5*1000, floppyalarm, 0);
  97. cancel(a);
  98. }
  99. /*
  100. * set floppy drive to its default type
  101. */
  102. static void
  103. floppysetdef(FDrive *dp)
  104. {
  105. FType *t;
  106. for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++)
  107. if(dp->dt == t->dt){
  108. dp->t = t;
  109. break;
  110. }
  111. }
  112. static void
  113. _floppydetach(void)
  114. {
  115. /*
  116. * stop the motors
  117. */
  118. fl.motor = 0;
  119. delay(10);
  120. outb(Pdor, fl.motor | Fintena | Fena);
  121. delay(10);
  122. }
  123. int
  124. floppyinit(void)
  125. {
  126. FDrive *dp;
  127. FType *t;
  128. ulong maxtsize;
  129. int mask;
  130. dmainit(DMAchan);
  131. floppysetup0(&fl);
  132. /*
  133. * init dependent parameters
  134. */
  135. maxtsize = 0;
  136. for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
  137. t->cap = t->bytes * t->heads * t->sectors * t->tracks;
  138. t->bcode = b2c[t->bytes/128];
  139. t->tsize = t->bytes * t->sectors;
  140. if(maxtsize < t->tsize)
  141. maxtsize = t->tsize;
  142. }
  143. fl.selected = fl.d;
  144. floppydetach = _floppydetach;
  145. floppydetach();
  146. /*
  147. * init drives
  148. */
  149. mask = 0;
  150. for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
  151. dp->dev = dp - fl.d;
  152. if(dp->dt == Tnone)
  153. continue;
  154. mask |= 1<<dp->dev;
  155. floppysetdef(dp);
  156. dp->cyl = -1; /* because we don't know */
  157. dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024);
  158. dp->ccyl = -1;
  159. dp->vers = 0;
  160. dp->maxtries = 5;
  161. }
  162. /*
  163. * first operation will recalibrate
  164. */
  165. fl.confused = 1;
  166. floppysetup1(&fl);
  167. /* to turn the motor off when inactive */
  168. alarm(5*1000, floppyalarm, 0);
  169. return mask;
  170. }
  171. void
  172. floppyinitdev(int i, char *name)
  173. {
  174. if(i >= fl.ndrive)
  175. panic("floppyinitdev");
  176. sprint(name, "fd%d", i);
  177. }
  178. void
  179. floppyprintdevs(int i)
  180. {
  181. if(i >= fl.ndrive)
  182. panic("floppyprintdevs");
  183. print(" fd%d", i);
  184. }
  185. int
  186. floppyboot(int dev, char *file, Boot *b)
  187. {
  188. Fs *fs;
  189. if(strncmp(file, "dos!", 4) == 0)
  190. file += 4;
  191. else if(strchr(file, '!') || strcmp(file, "")==0) {
  192. print("syntax is fd0!file\n");
  193. return -1;
  194. }
  195. fs = floppygetfspart(dev, "dos", 1);
  196. if(fs == nil)
  197. return -1;
  198. return fsboot(fs, file, b);
  199. }
  200. void
  201. floppyprintbootdevs(int dev)
  202. {
  203. print(" fd%d", dev);
  204. }
  205. /*
  206. * check if the floppy has been replaced under foot. cause
  207. * an error if it has.
  208. *
  209. * a seek and a read clears the condition. this was determined
  210. * experimentally, there has to be a better way.
  211. *
  212. * if the read fails, cycle through the possible floppy
  213. * density till one works or we've cycled through all
  214. * possibilities for this drive.
  215. */
  216. static int
  217. changed(FDrive *dp)
  218. {
  219. FType *start;
  220. /*
  221. * if floppy has changed or first time through
  222. */
  223. if((inb(Pdir)&Fchange) || dp->vers == 0){
  224. DPRINT("changed\n");
  225. fldump();
  226. dp->vers++;
  227. floppysetdef(dp);
  228. dp->maxtries = 3;
  229. start = dp->t;
  230. /* flopppyon fails if there's no drive */
  231. dp->confused = 1; /* make floppyon recal */
  232. if(floppyon(dp) < 0)
  233. return -1;
  234. pcfloppyseek(dp, dp->t->heads*dp->t->tsize);
  235. while(floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize) <= 0){
  236. /*
  237. * if the xfer attempt doesn't clear the changed bit,
  238. * there's no floppy in the drive
  239. */
  240. if(inb(Pdir)&Fchange)
  241. return -1;
  242. while(++dp->t){
  243. if(dp->t == &floppytype[nelem(floppytype)])
  244. dp->t = floppytype;
  245. if(dp->dt == dp->t->dt)
  246. break;
  247. }
  248. /* flopppyon fails if there's no drive */
  249. if(floppyon(dp) < 0)
  250. return -1;
  251. DPRINT("changed: trying %s\n", dp->t->name);
  252. fldump();
  253. if(dp->t == start)
  254. return -1;
  255. }
  256. }
  257. return 0;
  258. }
  259. static int
  260. readtrack(FDrive *dp, int cyl, int head)
  261. {
  262. int i, nn, sofar;
  263. ulong pos;
  264. nn = dp->t->tsize;
  265. if(dp->ccyl==cyl && dp->chead==head)
  266. return nn;
  267. pos = (cyl*dp->t->heads+head) * nn;
  268. for(sofar = 0; sofar < nn; sofar += i){
  269. dp->ccyl = -1;
  270. i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar);
  271. if(i <= 0)
  272. return -1;
  273. }
  274. dp->ccyl = cyl;
  275. dp->chead = head;
  276. return nn;
  277. }
  278. long
  279. floppyread(Fs *fs, void *a, long n)
  280. {
  281. FDrive *dp;
  282. long rv, offset;
  283. int sec, head, cyl;
  284. long len;
  285. uchar *aa;
  286. aa = a;
  287. dp = &fl.d[fs->dev];
  288. offset = dp->offset;
  289. floppyon(dp);
  290. if(changed(dp))
  291. return -1;
  292. for(rv = 0; rv < n; rv += len){
  293. /*
  294. * all xfers come out of the track cache
  295. */
  296. dp->len = n - rv;
  297. floppypos(dp, offset+rv);
  298. cyl = dp->tcyl;
  299. head = dp->thead;
  300. len = dp->len;
  301. sec = dp->tsec;
  302. if(readtrack(dp, cyl, head) < 0)
  303. break;
  304. memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
  305. }
  306. dp->offset = offset+rv;
  307. return rv;
  308. }
  309. void*
  310. floppygetfspart(int i, char *name, int chatty)
  311. {
  312. static Fs fs;
  313. if(strcmp(name, "dos") != 0){
  314. if(chatty)
  315. print("unknown partition fd%d!%s (use fd%d!dos)\n", i, name, i);
  316. return nil;
  317. }
  318. fs.dev = i;
  319. fs.diskread = floppyread;
  320. fs.diskseek = floppyseek;
  321. /* sometimes we get spurious errors and doing it again works */
  322. if(dosinit(&fs) < 0 && dosinit(&fs) < 0){
  323. if(chatty)
  324. print("fd%d!%s does not contain a FAT file system\n", i, name);
  325. return nil;
  326. }
  327. return &fs;
  328. }
  329. static int
  330. return0(void*)
  331. {
  332. return 0;
  333. }
  334. static void
  335. timedsleep(int (*f)(void*), void* arg, int ms)
  336. {
  337. int s;
  338. ulong end;
  339. end = m->ticks + 1 + MS2TK(ms);
  340. while(m->ticks < end && !(*f)(arg)){
  341. s = spllo();
  342. delay(10);
  343. splx(s);
  344. }
  345. }
  346. /*
  347. * start a floppy drive's motor.
  348. */
  349. static int
  350. floppyon(FDrive *dp)
  351. {
  352. int alreadyon;
  353. int tries;
  354. if(fl.confused)
  355. floppyrevive();
  356. /* start motor and select drive */
  357. dp->lasttouched = m->ticks;
  358. alreadyon = fl.motor & MOTORBIT(dp->dev);
  359. if(!alreadyon){
  360. fl.motor |= MOTORBIT(dp->dev);
  361. outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
  362. /* wait for drive to spin up */
  363. timedsleep(return0, 0, 750);
  364. /* clear any pending interrupts */
  365. floppysense();
  366. }
  367. /* set transfer rate */
  368. if(fl.rate != dp->t->rate){
  369. fl.rate = dp->t->rate;
  370. outb(Pdsr, fl.rate);
  371. }
  372. /* get drive to a known cylinder */
  373. if(dp->confused)
  374. for(tries = 0; tries < 4; tries++)
  375. if(floppyrecal(dp) >= 0)
  376. break;
  377. dp->lasttouched = m->ticks;
  378. fl.selected = dp;
  379. if(dp->confused)
  380. return -1;
  381. return 0;
  382. }
  383. /*
  384. * stop the floppy if it hasn't been used in 5 seconds
  385. */
  386. static void
  387. floppyoff(FDrive *dp)
  388. {
  389. fl.motor &= ~MOTORBIT(dp->dev);
  390. outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
  391. }
  392. /*
  393. * send a command to the floppy
  394. */
  395. static int
  396. floppycmd(void)
  397. {
  398. int i;
  399. int tries;
  400. fl.nstat = 0;
  401. for(i = 0; i < fl.ncmd; i++){
  402. for(tries = 0; ; tries++){
  403. if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
  404. break;
  405. if(tries > 1000){
  406. DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
  407. fldump();
  408. /* empty fifo, might have been a bad command */
  409. floppyresult();
  410. return -1;
  411. }
  412. microdelay(1);
  413. }
  414. outb(Pfdata, fl.cmd[i]);
  415. }
  416. return 0;
  417. }
  418. /*
  419. * get a command result from the floppy
  420. *
  421. * when the controller goes ready waiting for a command
  422. * (instead of sending results), we're done
  423. *
  424. */
  425. static int
  426. floppyresult(void)
  427. {
  428. int i, s;
  429. int tries;
  430. /* get the result of the operation */
  431. for(i = 0; i < sizeof(fl.stat); i++){
  432. /* wait for status byte */
  433. for(tries = 0; ; tries++){
  434. s = inb(Pmsr)&(Ffrom|Fready);
  435. if(s == Fready){
  436. fl.nstat = i;
  437. return fl.nstat;
  438. }
  439. if(s == (Ffrom|Fready))
  440. break;
  441. if(tries > 1000){
  442. DPRINT("floppyresult: %d stats\n", i);
  443. fldump();
  444. fl.confused = 1;
  445. return -1;
  446. }
  447. microdelay(1);
  448. }
  449. fl.stat[i] = inb(Pfdata);
  450. }
  451. fl.nstat = sizeof(fl.stat);
  452. return fl.nstat;
  453. }
  454. /*
  455. * calculate physical address of a logical byte offset into the disk
  456. *
  457. * truncate dp->length if it crosses a track boundary
  458. */
  459. static void
  460. floppypos(FDrive *dp, long off)
  461. {
  462. int lsec;
  463. int ltrack;
  464. int end;
  465. lsec = off/dp->t->bytes;
  466. ltrack = lsec/dp->t->sectors;
  467. dp->tcyl = ltrack/dp->t->heads;
  468. dp->tsec = (lsec % dp->t->sectors) + 1;
  469. dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
  470. /*
  471. * can't read across track boundaries.
  472. * if so, decrement the bytes to be read.
  473. */
  474. end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
  475. if(off+dp->len > end)
  476. dp->len = end - off;
  477. }
  478. /*
  479. * get the interrupt cause from the floppy.
  480. */
  481. static int
  482. floppysense(void)
  483. {
  484. fl.ncmd = 0;
  485. fl.cmd[fl.ncmd++] = Fsense;
  486. if(floppycmd() < 0)
  487. return -1;
  488. if(floppyresult() < 2){
  489. DPRINT("can't read sense response\n");
  490. fldump();
  491. fl.confused = 1;
  492. return -1;
  493. }
  494. return 0;
  495. }
  496. static int
  497. cmddone(void *a)
  498. {
  499. USED(a);
  500. return fl.ncmd == 0;
  501. }
  502. /*
  503. * Wait for a floppy interrupt. If none occurs in 5 seconds, we
  504. * may have missed one. This only happens on some portables which
  505. * do power management behind our backs. Call the interrupt
  506. * routine to try to clear any conditions.
  507. */
  508. static void
  509. floppywait(int slow)
  510. {
  511. timedsleep(cmddone, 0, slow ? 5000 : 1000);
  512. if(!cmddone(0)){
  513. floppyintr(0);
  514. fl.confused = 1;
  515. }
  516. }
  517. /*
  518. * we've lost the floppy position, go to cylinder 0.
  519. */
  520. static int
  521. floppyrecal(FDrive *dp)
  522. {
  523. dp->ccyl = -1;
  524. dp->cyl = -1;
  525. fl.ncmd = 0;
  526. fl.cmd[fl.ncmd++] = Frecal;
  527. fl.cmd[fl.ncmd++] = dp->dev;
  528. if(floppycmd() < 0)
  529. return -1;
  530. floppywait(1);
  531. if(fl.nstat < 2){
  532. DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
  533. fl.confused = 1;
  534. return -1;
  535. }
  536. if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
  537. DPRINT("recalibrate: failed\n");
  538. dp->confused = 1;
  539. return -1;
  540. }
  541. dp->cyl = fl.stat[1];
  542. if(dp->cyl != 0){
  543. DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);
  544. dp->cyl = -1;
  545. dp->confused = 1;
  546. return -1;
  547. }
  548. dp->confused = 0;
  549. return 0;
  550. }
  551. /*
  552. * if the controller or a specific drive is in a confused state,
  553. * reset it and get back to a kown state
  554. */
  555. static void
  556. floppyrevive(void)
  557. {
  558. FDrive *dp;
  559. /*
  560. * reset the controller if it's confused
  561. */
  562. if(fl.confused){
  563. DPRINT("floppyrevive in\n");
  564. fldump();
  565. /* reset controller and turn all motors off */
  566. splhi();
  567. fl.ncmd = 1;
  568. fl.cmd[0] = 0;
  569. outb(Pdor, 0);
  570. delay(10);
  571. outb(Pdor, Fintena|Fena);
  572. delay(10);
  573. spllo();
  574. fl.motor = 0;
  575. fl.confused = 0;
  576. floppywait(0);
  577. /* mark all drives in an unknown state */
  578. for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
  579. dp->confused = 1;
  580. /* set rate to a known value */
  581. outb(Pdsr, 0);
  582. fl.rate = 0;
  583. DPRINT("floppyrevive out\n");
  584. fldump();
  585. }
  586. }
  587. /*
  588. * seek to the target cylinder
  589. *
  590. * interrupt, no results
  591. */
  592. static vlong
  593. pcfloppyseek(FDrive *dp, vlong off)
  594. {
  595. floppypos(dp, off);
  596. if(dp->cyl == dp->tcyl){
  597. dp->offset = off;
  598. return off;
  599. }
  600. dp->cyl = -1;
  601. fl.ncmd = 0;
  602. fl.cmd[fl.ncmd++] = Fseek;
  603. fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
  604. fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
  605. if(floppycmd() < 0)
  606. return -1;
  607. floppywait(1);
  608. if(fl.nstat < 2){
  609. DPRINT("seek: confused\n");
  610. fl.confused = 1;
  611. return -1;
  612. }
  613. if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
  614. DPRINT("seek: failed\n");
  615. dp->confused = 1;
  616. return -1;
  617. }
  618. dp->cyl = dp->tcyl;
  619. dp->offset = off;
  620. DPRINT("seek to %d succeeded\n", dp->offset);
  621. return dp->offset;
  622. }
  623. /*
  624. * read or write to floppy. try up to three times.
  625. */
  626. static long
  627. floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
  628. {
  629. long offset;
  630. int tries;
  631. if(off >= dp->t->cap)
  632. return 0;
  633. if(off + n > dp->t->cap)
  634. n = dp->t->cap - off;
  635. /* retry on error (until it gets ridiculous) */
  636. for(tries = 0; tries < dp->maxtries; tries++){
  637. dp->len = n;
  638. if(pcfloppyseek(dp, off) < 0){
  639. DPRINT("xfer: seek failed\n");
  640. dp->confused = 1;
  641. continue;
  642. }
  643. /*
  644. * set up the dma (dp->len may be trimmed)
  645. */
  646. dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
  647. if(dp->len < 0){
  648. buggery:
  649. dmaend(DMAchan);
  650. continue;
  651. }
  652. /*
  653. * start operation
  654. */
  655. fl.ncmd = 0;
  656. fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
  657. fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
  658. fl.cmd[fl.ncmd++] = dp->tcyl;
  659. fl.cmd[fl.ncmd++] = dp->thead;
  660. fl.cmd[fl.ncmd++] = dp->tsec;
  661. fl.cmd[fl.ncmd++] = dp->t->bcode;
  662. fl.cmd[fl.ncmd++] = dp->t->sectors;
  663. fl.cmd[fl.ncmd++] = dp->t->gpl;
  664. fl.cmd[fl.ncmd++] = 0xFF;
  665. if(floppycmd() < 0)
  666. goto buggery;
  667. /*
  668. * give bus to DMA, floppyintr() will read result
  669. */
  670. floppywait(0);
  671. dmaend(DMAchan);
  672. /*
  673. * check for errors
  674. */
  675. if(fl.nstat < 7){
  676. DPRINT("xfer: confused\n");
  677. fl.confused = 1;
  678. continue;
  679. }
  680. if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
  681. DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
  682. fl.stat[1], fl.stat[2]);
  683. DPRINT("offset %lud len %ld\n", off, dp->len);
  684. if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){
  685. DPRINT("DMA overrun: retry\n");
  686. } else
  687. dp->confused = 1;
  688. continue;
  689. }
  690. /*
  691. * check for correct cylinder
  692. */
  693. offset = fl.stat[3] * dp->t->heads + fl.stat[4];
  694. offset = offset*dp->t->sectors + fl.stat[5] - 1;
  695. offset = offset * c2b[fl.stat[6]];
  696. if(offset != off+dp->len){
  697. DPRINT("xfer: ends on wrong cyl\n");
  698. dp->confused = 1;
  699. continue;
  700. }
  701. dp->lasttouched = m->ticks;
  702. dp->maxtries = 20;
  703. return dp->len;
  704. }
  705. return -1;
  706. }
  707. /*
  708. void
  709. floppymemwrite(void)
  710. {
  711. int i;
  712. int n;
  713. uchar *a;
  714. FDrive *dp;
  715. dp = &fl.d[0];
  716. a = (uchar*)0x80000000;
  717. n = 0;
  718. while(n < 1440*1024){
  719. i = floppyxfer(dp, Fwrite, a+n, n, 1440*1024-n);
  720. if(i <= 0)
  721. break;
  722. n += i;
  723. }
  724. print("floppymemwrite wrote %d bytes\n", n);
  725. splhi(); for(;;);
  726. }
  727. */
  728. static void
  729. floppyintr(Ureg *ur)
  730. {
  731. USED(ur);
  732. switch(fl.cmd[0]&~Fmulti){
  733. case Fread:
  734. case Fwrite:
  735. case Fformat:
  736. case Fdumpreg:
  737. floppyresult();
  738. break;
  739. case Fseek:
  740. case Frecal:
  741. default:
  742. floppysense(); /* to clear interrupt */
  743. break;
  744. }
  745. fl.ncmd = 0;
  746. }