devfloppy.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  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. /* there are no partitions on floppies */
  190. if(strncmp(file, "dos!", 4) == 0)
  191. file += 4;
  192. if(strchr(file, '!') != nil || strcmp(file, "") == 0) {
  193. print("syntax is fd0!file\n");
  194. return -1;
  195. }
  196. fs = floppygetfspart(dev, "dos", 1);
  197. if(fs == nil)
  198. return -1;
  199. return fsboot(fs, file, b);
  200. }
  201. void
  202. floppyprintbootdevs(int dev)
  203. {
  204. print(" fd%d", dev);
  205. }
  206. /*
  207. * check if the floppy has been replaced under foot. cause
  208. * an error if it has.
  209. *
  210. * a seek and a read clears the condition. this was determined
  211. * experimentally, there has to be a better way.
  212. *
  213. * if the read fails, cycle through the possible floppy
  214. * density till one works or we've cycled through all
  215. * possibilities for this drive.
  216. */
  217. static int
  218. changed(FDrive *dp)
  219. {
  220. FType *start;
  221. /*
  222. * if floppy has changed or first time through
  223. */
  224. if((inb(Pdir)&Fchange) || dp->vers == 0){
  225. DPRINT("changed\n");
  226. fldump();
  227. dp->vers++;
  228. floppysetdef(dp);
  229. dp->maxtries = 3;
  230. start = dp->t;
  231. /* flopppyon fails if there's no drive */
  232. dp->confused = 1; /* make floppyon recal */
  233. if(floppyon(dp) < 0)
  234. return -1;
  235. pcfloppyseek(dp, dp->t->heads*dp->t->tsize);
  236. while(floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize) <= 0){
  237. /*
  238. * if the xfer attempt doesn't clear the changed bit,
  239. * there's no floppy in the drive
  240. */
  241. if(inb(Pdir)&Fchange)
  242. return -1;
  243. while(++dp->t){
  244. if(dp->t == &floppytype[nelem(floppytype)])
  245. dp->t = floppytype;
  246. if(dp->dt == dp->t->dt)
  247. break;
  248. }
  249. /* flopppyon fails if there's no drive */
  250. if(floppyon(dp) < 0)
  251. return -1;
  252. DPRINT("changed: trying %s\n", dp->t->name);
  253. fldump();
  254. if(dp->t == start)
  255. return -1;
  256. }
  257. }
  258. return 0;
  259. }
  260. static int
  261. readtrack(FDrive *dp, int cyl, int head)
  262. {
  263. int i, nn, sofar;
  264. ulong pos;
  265. nn = dp->t->tsize;
  266. if(dp->ccyl==cyl && dp->chead==head)
  267. return nn;
  268. pos = (cyl*dp->t->heads+head) * nn;
  269. for(sofar = 0; sofar < nn; sofar += i){
  270. dp->ccyl = -1;
  271. i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar);
  272. if(i <= 0)
  273. return -1;
  274. }
  275. dp->ccyl = cyl;
  276. dp->chead = head;
  277. return nn;
  278. }
  279. long
  280. floppyread(Fs *fs, void *a, long n)
  281. {
  282. FDrive *dp;
  283. long rv, offset;
  284. int sec, head, cyl;
  285. long len;
  286. uchar *aa;
  287. aa = a;
  288. dp = &fl.d[fs->dev];
  289. offset = dp->offset;
  290. floppyon(dp);
  291. if(changed(dp))
  292. return -1;
  293. for(rv = 0; rv < n; rv += len){
  294. /*
  295. * all xfers come out of the track cache
  296. */
  297. dp->len = n - rv;
  298. floppypos(dp, offset+rv);
  299. cyl = dp->tcyl;
  300. head = dp->thead;
  301. len = dp->len;
  302. sec = dp->tsec;
  303. if(readtrack(dp, cyl, head) < 0)
  304. break;
  305. memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
  306. }
  307. dp->offset = offset+rv;
  308. return rv;
  309. }
  310. void*
  311. floppygetfspart(int i, char *name, int chatty)
  312. {
  313. static Fs fs;
  314. if(strcmp(name, "dos") != 0){
  315. if(chatty)
  316. print("unknown partition fd%d!%s (use fd%d!dos)\n", i, name, i);
  317. return nil;
  318. }
  319. fs.dev = i;
  320. fs.diskread = floppyread;
  321. fs.diskseek = floppyseek;
  322. /* sometimes we get spurious errors and doing it again works */
  323. if(dosinit(&fs) < 0 && dosinit(&fs) < 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 &fs;
  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. if (dp->t->bytes == 0 || dp->t->sectors == 0 || dp->t->heads == 0)
  467. panic("floppypos: zero geometry");
  468. lsec = off/dp->t->bytes;
  469. ltrack = lsec/dp->t->sectors;
  470. dp->tcyl = ltrack/dp->t->heads;
  471. dp->tsec = (lsec % dp->t->sectors) + 1;
  472. dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
  473. /*
  474. * can't read across track boundaries.
  475. * if so, decrement the bytes to be read.
  476. */
  477. end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
  478. if(off+dp->len > end)
  479. dp->len = end - off;
  480. }
  481. /*
  482. * get the interrupt cause from the floppy.
  483. */
  484. static int
  485. floppysense(void)
  486. {
  487. fl.ncmd = 0;
  488. fl.cmd[fl.ncmd++] = Fsense;
  489. if(floppycmd() < 0)
  490. return -1;
  491. if(floppyresult() < 2){
  492. DPRINT("can't read sense response\n");
  493. fldump();
  494. fl.confused = 1;
  495. return -1;
  496. }
  497. return 0;
  498. }
  499. static int
  500. cmddone(void *a)
  501. {
  502. USED(a);
  503. return fl.ncmd == 0;
  504. }
  505. /*
  506. * Wait for a floppy interrupt. If none occurs in 5 seconds, we
  507. * may have missed one. This only happens on some portables which
  508. * do power management behind our backs. Call the interrupt
  509. * routine to try to clear any conditions.
  510. */
  511. static void
  512. floppywait(int slow)
  513. {
  514. timedsleep(cmddone, 0, slow ? 5000 : 1000);
  515. if(!cmddone(0)){
  516. floppyintr(0);
  517. fl.confused = 1;
  518. }
  519. }
  520. /*
  521. * we've lost the floppy position, go to cylinder 0.
  522. */
  523. static int
  524. floppyrecal(FDrive *dp)
  525. {
  526. dp->ccyl = -1;
  527. dp->cyl = -1;
  528. fl.ncmd = 0;
  529. fl.cmd[fl.ncmd++] = Frecal;
  530. fl.cmd[fl.ncmd++] = dp->dev;
  531. if(floppycmd() < 0)
  532. return -1;
  533. floppywait(1);
  534. if(fl.nstat < 2){
  535. DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
  536. fl.confused = 1;
  537. return -1;
  538. }
  539. if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
  540. DPRINT("recalibrate: failed\n");
  541. dp->confused = 1;
  542. return -1;
  543. }
  544. dp->cyl = fl.stat[1];
  545. if(dp->cyl != 0){
  546. DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);
  547. dp->cyl = -1;
  548. dp->confused = 1;
  549. return -1;
  550. }
  551. dp->confused = 0;
  552. return 0;
  553. }
  554. /*
  555. * if the controller or a specific drive is in a confused state,
  556. * reset it and get back to a kown state
  557. */
  558. static void
  559. floppyrevive(void)
  560. {
  561. FDrive *dp;
  562. /*
  563. * reset the controller if it's confused
  564. */
  565. if(fl.confused){
  566. DPRINT("floppyrevive in\n");
  567. fldump();
  568. /* reset controller and turn all motors off */
  569. splhi();
  570. fl.ncmd = 1;
  571. fl.cmd[0] = 0;
  572. outb(Pdor, 0);
  573. delay(10);
  574. outb(Pdor, Fintena|Fena);
  575. delay(10);
  576. spllo();
  577. fl.motor = 0;
  578. fl.confused = 0;
  579. floppywait(0);
  580. /* mark all drives in an unknown state */
  581. for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
  582. dp->confused = 1;
  583. /* set rate to a known value */
  584. outb(Pdsr, 0);
  585. fl.rate = 0;
  586. DPRINT("floppyrevive out\n");
  587. fldump();
  588. }
  589. }
  590. /*
  591. * seek to the target cylinder
  592. *
  593. * interrupt, no results
  594. */
  595. static vlong
  596. pcfloppyseek(FDrive *dp, vlong off)
  597. {
  598. floppypos(dp, off);
  599. if(dp->cyl == dp->tcyl){
  600. dp->offset = off;
  601. return off;
  602. }
  603. dp->cyl = -1;
  604. fl.ncmd = 0;
  605. fl.cmd[fl.ncmd++] = Fseek;
  606. fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
  607. fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
  608. if(floppycmd() < 0)
  609. return -1;
  610. floppywait(1);
  611. if(fl.nstat < 2){
  612. DPRINT("seek: confused\n");
  613. fl.confused = 1;
  614. return -1;
  615. }
  616. if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
  617. DPRINT("seek: failed\n");
  618. dp->confused = 1;
  619. return -1;
  620. }
  621. dp->cyl = dp->tcyl;
  622. dp->offset = off;
  623. DPRINT("seek to %d succeeded\n", dp->offset);
  624. return dp->offset;
  625. }
  626. /*
  627. * read or write to floppy. try up to three times.
  628. */
  629. static long
  630. floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
  631. {
  632. long offset;
  633. int tries;
  634. if(off >= dp->t->cap)
  635. return 0;
  636. if(off + n > dp->t->cap)
  637. n = dp->t->cap - off;
  638. /* retry on error (until it gets ridiculous) */
  639. for(tries = 0; tries < dp->maxtries; tries++){
  640. dp->len = n;
  641. if(pcfloppyseek(dp, off) < 0){
  642. DPRINT("xfer: seek failed\n");
  643. dp->confused = 1;
  644. continue;
  645. }
  646. /*
  647. * set up the dma (dp->len may be trimmed)
  648. */
  649. dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
  650. if(dp->len < 0){
  651. buggery:
  652. dmaend(DMAchan);
  653. continue;
  654. }
  655. /*
  656. * start operation
  657. */
  658. fl.ncmd = 0;
  659. fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
  660. fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
  661. fl.cmd[fl.ncmd++] = dp->tcyl;
  662. fl.cmd[fl.ncmd++] = dp->thead;
  663. fl.cmd[fl.ncmd++] = dp->tsec;
  664. fl.cmd[fl.ncmd++] = dp->t->bcode;
  665. fl.cmd[fl.ncmd++] = dp->t->sectors;
  666. fl.cmd[fl.ncmd++] = dp->t->gpl;
  667. fl.cmd[fl.ncmd++] = 0xFF;
  668. if(floppycmd() < 0)
  669. goto buggery;
  670. /*
  671. * give bus to DMA, floppyintr() will read result
  672. */
  673. floppywait(0);
  674. dmaend(DMAchan);
  675. /*
  676. * check for errors
  677. */
  678. if(fl.nstat < 7){
  679. DPRINT("xfer: confused\n");
  680. fl.confused = 1;
  681. continue;
  682. }
  683. if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
  684. DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
  685. fl.stat[1], fl.stat[2]);
  686. DPRINT("offset %lud len %ld\n", off, dp->len);
  687. if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){
  688. DPRINT("DMA overrun: retry\n");
  689. } else
  690. dp->confused = 1;
  691. continue;
  692. }
  693. /*
  694. * check for correct cylinder
  695. */
  696. offset = fl.stat[3] * dp->t->heads + fl.stat[4];
  697. offset = offset*dp->t->sectors + fl.stat[5] - 1;
  698. offset = offset * c2b[fl.stat[6]];
  699. if(offset != off+dp->len){
  700. DPRINT("xfer: ends on wrong cyl\n");
  701. dp->confused = 1;
  702. continue;
  703. }
  704. dp->lasttouched = m->ticks;
  705. dp->maxtries = 20;
  706. return dp->len;
  707. }
  708. return -1;
  709. }
  710. /*
  711. void
  712. floppymemwrite(void)
  713. {
  714. int i;
  715. int n;
  716. uchar *a;
  717. FDrive *dp;
  718. dp = &fl.d[0];
  719. a = (uchar*)0x80000000;
  720. n = 0;
  721. while(n < 1440*1024){
  722. i = floppyxfer(dp, Fwrite, a+n, n, 1440*1024-n);
  723. if(i <= 0)
  724. break;
  725. n += i;
  726. }
  727. print("floppymemwrite wrote %d bytes\n", n);
  728. splhi(); for(;;);
  729. }
  730. */
  731. static void
  732. floppyintr(Ureg *ur)
  733. {
  734. USED(ur);
  735. switch(fl.cmd[0]&~Fmulti){
  736. case Fread:
  737. case Fwrite:
  738. case Fformat:
  739. case Fdumpreg:
  740. floppyresult();
  741. break;
  742. case Fseek:
  743. case Frecal:
  744. default:
  745. floppysense(); /* to clear interrupt */
  746. break;
  747. }
  748. fl.ncmd = 0;
  749. }