devfloppy.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  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 "dosfs.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. Dos *dos;
  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. dos = floppygetdospart(dev, "dos", 1);
  196. if(dos == nil)
  197. return -1;
  198. return dosboot(dos, 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(Dos *dos, 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[dos->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. floppygetdospart(int i, char *name, int chatty)
  311. {
  312. static Dos dos;
  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. dos.dev = i;
  319. dos.read = floppyread;
  320. dos.seek = floppyseek;
  321. dos.start = 0;
  322. /* sometimes we get spurious errors and doing it again works */
  323. if(dosinit(&dos) < 0 && dosinit(&dos) < 0){
  324. if(chatty)
  325. print("fd%d!%s does not contain a FAT file system\n", i, name);
  326. return nil;
  327. }
  328. return &dos;
  329. }
  330. static int
  331. return0(void*)
  332. {
  333. return 0;
  334. }
  335. static void
  336. timedsleep(int (*f)(void*), void* arg, int ms)
  337. {
  338. int s;
  339. ulong end;
  340. end = m->ticks + 1 + MS2TK(ms);
  341. while(m->ticks < end && !(*f)(arg)){
  342. s = spllo();
  343. delay(10);
  344. splx(s);
  345. }
  346. }
  347. /*
  348. * start a floppy drive's motor.
  349. */
  350. static int
  351. floppyon(FDrive *dp)
  352. {
  353. int alreadyon;
  354. int tries;
  355. if(fl.confused)
  356. floppyrevive();
  357. /* start motor and select drive */
  358. dp->lasttouched = m->ticks;
  359. alreadyon = fl.motor & MOTORBIT(dp->dev);
  360. if(!alreadyon){
  361. fl.motor |= MOTORBIT(dp->dev);
  362. outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
  363. /* wait for drive to spin up */
  364. timedsleep(return0, 0, 750);
  365. /* clear any pending interrupts */
  366. floppysense();
  367. }
  368. /* set transfer rate */
  369. if(fl.rate != dp->t->rate){
  370. fl.rate = dp->t->rate;
  371. outb(Pdsr, fl.rate);
  372. }
  373. /* get drive to a known cylinder */
  374. if(dp->confused)
  375. for(tries = 0; tries < 4; tries++)
  376. if(floppyrecal(dp) >= 0)
  377. break;
  378. dp->lasttouched = m->ticks;
  379. fl.selected = dp;
  380. if(dp->confused)
  381. return -1;
  382. return 0;
  383. }
  384. /*
  385. * stop the floppy if it hasn't been used in 5 seconds
  386. */
  387. static void
  388. floppyoff(FDrive *dp)
  389. {
  390. fl.motor &= ~MOTORBIT(dp->dev);
  391. outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
  392. }
  393. /*
  394. * send a command to the floppy
  395. */
  396. static int
  397. floppycmd(void)
  398. {
  399. int i;
  400. int tries;
  401. fl.nstat = 0;
  402. for(i = 0; i < fl.ncmd; i++){
  403. for(tries = 0; ; tries++){
  404. if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
  405. break;
  406. if(tries > 1000){
  407. DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
  408. fldump();
  409. /* empty fifo, might have been a bad command */
  410. floppyresult();
  411. return -1;
  412. }
  413. microdelay(1);
  414. }
  415. outb(Pfdata, fl.cmd[i]);
  416. }
  417. return 0;
  418. }
  419. /*
  420. * get a command result from the floppy
  421. *
  422. * when the controller goes ready waiting for a command
  423. * (instead of sending results), we're done
  424. *
  425. */
  426. static int
  427. floppyresult(void)
  428. {
  429. int i, s;
  430. int tries;
  431. /* get the result of the operation */
  432. for(i = 0; i < sizeof(fl.stat); i++){
  433. /* wait for status byte */
  434. for(tries = 0; ; tries++){
  435. s = inb(Pmsr)&(Ffrom|Fready);
  436. if(s == Fready){
  437. fl.nstat = i;
  438. return fl.nstat;
  439. }
  440. if(s == (Ffrom|Fready))
  441. break;
  442. if(tries > 1000){
  443. DPRINT("floppyresult: %d stats\n", i);
  444. fldump();
  445. fl.confused = 1;
  446. return -1;
  447. }
  448. microdelay(1);
  449. }
  450. fl.stat[i] = inb(Pfdata);
  451. }
  452. fl.nstat = sizeof(fl.stat);
  453. return fl.nstat;
  454. }
  455. /*
  456. * calculate physical address of a logical byte offset into the disk
  457. *
  458. * truncate dp->length if it crosses a track boundary
  459. */
  460. static void
  461. floppypos(FDrive *dp, long off)
  462. {
  463. int lsec;
  464. int ltrack;
  465. int end;
  466. lsec = off/dp->t->bytes;
  467. ltrack = lsec/dp->t->sectors;
  468. dp->tcyl = ltrack/dp->t->heads;
  469. dp->tsec = (lsec % dp->t->sectors) + 1;
  470. dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
  471. /*
  472. * can't read across track boundaries.
  473. * if so, decrement the bytes to be read.
  474. */
  475. end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
  476. if(off+dp->len > end)
  477. dp->len = end - off;
  478. }
  479. /*
  480. * get the interrupt cause from the floppy.
  481. */
  482. static int
  483. floppysense(void)
  484. {
  485. fl.ncmd = 0;
  486. fl.cmd[fl.ncmd++] = Fsense;
  487. if(floppycmd() < 0)
  488. return -1;
  489. if(floppyresult() < 2){
  490. DPRINT("can't read sense response\n");
  491. fldump();
  492. fl.confused = 1;
  493. return -1;
  494. }
  495. return 0;
  496. }
  497. static int
  498. cmddone(void *a)
  499. {
  500. USED(a);
  501. return fl.ncmd == 0;
  502. }
  503. /*
  504. * Wait for a floppy interrupt. If none occurs in 5 seconds, we
  505. * may have missed one. This only happens on some portables which
  506. * do power management behind our backs. Call the interrupt
  507. * routine to try to clear any conditions.
  508. */
  509. static void
  510. floppywait(int slow)
  511. {
  512. timedsleep(cmddone, 0, slow ? 5000 : 1000);
  513. if(!cmddone(0)){
  514. floppyintr(0);
  515. fl.confused = 1;
  516. }
  517. }
  518. /*
  519. * we've lost the floppy position, go to cylinder 0.
  520. */
  521. static int
  522. floppyrecal(FDrive *dp)
  523. {
  524. dp->ccyl = -1;
  525. dp->cyl = -1;
  526. fl.ncmd = 0;
  527. fl.cmd[fl.ncmd++] = Frecal;
  528. fl.cmd[fl.ncmd++] = dp->dev;
  529. if(floppycmd() < 0)
  530. return -1;
  531. floppywait(1);
  532. if(fl.nstat < 2){
  533. DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
  534. fl.confused = 1;
  535. return -1;
  536. }
  537. if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
  538. DPRINT("recalibrate: failed\n");
  539. dp->confused = 1;
  540. return -1;
  541. }
  542. dp->cyl = fl.stat[1];
  543. if(dp->cyl != 0){
  544. DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);
  545. dp->cyl = -1;
  546. dp->confused = 1;
  547. return -1;
  548. }
  549. dp->confused = 0;
  550. return 0;
  551. }
  552. /*
  553. * if the controller or a specific drive is in a confused state,
  554. * reset it and get back to a kown state
  555. */
  556. static void
  557. floppyrevive(void)
  558. {
  559. FDrive *dp;
  560. /*
  561. * reset the controller if it's confused
  562. */
  563. if(fl.confused){
  564. DPRINT("floppyrevive in\n");
  565. fldump();
  566. /* reset controller and turn all motors off */
  567. splhi();
  568. fl.ncmd = 1;
  569. fl.cmd[0] = 0;
  570. outb(Pdor, 0);
  571. delay(10);
  572. outb(Pdor, Fintena|Fena);
  573. delay(10);
  574. spllo();
  575. fl.motor = 0;
  576. fl.confused = 0;
  577. floppywait(0);
  578. /* mark all drives in an unknown state */
  579. for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
  580. dp->confused = 1;
  581. /* set rate to a known value */
  582. outb(Pdsr, 0);
  583. fl.rate = 0;
  584. DPRINT("floppyrevive out\n");
  585. fldump();
  586. }
  587. }
  588. /*
  589. * seek to the target cylinder
  590. *
  591. * interrupt, no results
  592. */
  593. static vlong
  594. pcfloppyseek(FDrive *dp, vlong off)
  595. {
  596. floppypos(dp, off);
  597. if(dp->cyl == dp->tcyl){
  598. dp->offset = off;
  599. return off;
  600. }
  601. dp->cyl = -1;
  602. fl.ncmd = 0;
  603. fl.cmd[fl.ncmd++] = Fseek;
  604. fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
  605. fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
  606. if(floppycmd() < 0)
  607. return -1;
  608. floppywait(1);
  609. if(fl.nstat < 2){
  610. DPRINT("seek: confused\n");
  611. fl.confused = 1;
  612. return -1;
  613. }
  614. if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
  615. DPRINT("seek: failed\n");
  616. dp->confused = 1;
  617. return -1;
  618. }
  619. dp->cyl = dp->tcyl;
  620. dp->offset = off;
  621. DPRINT("seek to %d succeeded\n", dp->offset);
  622. return dp->offset;
  623. }
  624. /*
  625. * read or write to floppy. try up to three times.
  626. */
  627. static long
  628. floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
  629. {
  630. long offset;
  631. int tries;
  632. if(off >= dp->t->cap)
  633. return 0;
  634. if(off + n > dp->t->cap)
  635. n = dp->t->cap - off;
  636. /* retry on error (until it gets ridiculous) */
  637. for(tries = 0; tries < dp->maxtries; tries++){
  638. dp->len = n;
  639. if(pcfloppyseek(dp, off) < 0){
  640. DPRINT("xfer: seek failed\n");
  641. dp->confused = 1;
  642. continue;
  643. }
  644. /*
  645. * set up the dma (dp->len may be trimmed)
  646. */
  647. dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
  648. if(dp->len < 0){
  649. buggery:
  650. dmaend(DMAchan);
  651. continue;
  652. }
  653. /*
  654. * start operation
  655. */
  656. fl.ncmd = 0;
  657. fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
  658. fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
  659. fl.cmd[fl.ncmd++] = dp->tcyl;
  660. fl.cmd[fl.ncmd++] = dp->thead;
  661. fl.cmd[fl.ncmd++] = dp->tsec;
  662. fl.cmd[fl.ncmd++] = dp->t->bcode;
  663. fl.cmd[fl.ncmd++] = dp->t->sectors;
  664. fl.cmd[fl.ncmd++] = dp->t->gpl;
  665. fl.cmd[fl.ncmd++] = 0xFF;
  666. if(floppycmd() < 0)
  667. goto buggery;
  668. /*
  669. * give bus to DMA, floppyintr() will read result
  670. */
  671. floppywait(0);
  672. dmaend(DMAchan);
  673. /*
  674. * check for errors
  675. */
  676. if(fl.nstat < 7){
  677. DPRINT("xfer: confused\n");
  678. fl.confused = 1;
  679. continue;
  680. }
  681. if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
  682. DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
  683. fl.stat[1], fl.stat[2]);
  684. DPRINT("offset %lud len %ld\n", off, dp->len);
  685. if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){
  686. DPRINT("DMA overrun: retry\n");
  687. } else
  688. dp->confused = 1;
  689. continue;
  690. }
  691. /*
  692. * check for correct cylinder
  693. */
  694. offset = fl.stat[3] * dp->t->heads + fl.stat[4];
  695. offset = offset*dp->t->sectors + fl.stat[5] - 1;
  696. offset = offset * c2b[fl.stat[6]];
  697. if(offset != off+dp->len){
  698. DPRINT("xfer: ends on wrong cyl\n");
  699. dp->confused = 1;
  700. continue;
  701. }
  702. dp->lasttouched = m->ticks;
  703. dp->maxtries = 20;
  704. return dp->len;
  705. }
  706. return -1;
  707. }
  708. /*
  709. void
  710. floppymemwrite(void)
  711. {
  712. int i;
  713. int n;
  714. uchar *a;
  715. FDrive *dp;
  716. dp = &fl.d[0];
  717. a = (uchar*)0x80000000;
  718. n = 0;
  719. while(n < 1440*1024){
  720. i = floppyxfer(dp, Fwrite, a+n, n, 1440*1024-n);
  721. if(i <= 0)
  722. break;
  723. n += i;
  724. }
  725. print("floppymemwrite wrote %d bytes\n", n);
  726. splhi(); for(;;);
  727. }
  728. */
  729. static void
  730. floppyintr(Ureg *ur)
  731. {
  732. USED(ur);
  733. switch(fl.cmd[0]&~Fmulti){
  734. case Fread:
  735. case Fwrite:
  736. case Fformat:
  737. case Fdumpreg:
  738. floppyresult();
  739. break;
  740. case Fseek:
  741. case Frecal:
  742. default:
  743. floppysense(); /* to clear interrupt */
  744. break;
  745. }
  746. fl.ncmd = 0;
  747. }