static int fd_intr(void *arg) { struct fd_softc *sc = arg; sc->fd_intrcnt.ev_count++; fd_reset(sc); return 0; }
void fd_attach(device_t parent, device_t self, void *aux) { struct fd_softc *sc = device_private(self); struct confargs *ca = aux; sc->fd_bst = ca->ca_bustag; if (bus_space_map(ca->ca_bustag, ca->ca_addr, 0x1000000, BUS_SPACE_MAP_LINEAR, &sc->fd_bsh) != 0) { printf("%s: cannot map registers\n", device_xname(self)); return; } evcnt_attach_dynamic(&sc->fd_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(self), "intr"); bus_intr_establish(sc->fd_bst, SYS_INTR_FDC, 0, 0, fd_intr, sc); fd_reset(sc); printf(": not fully implemented\n"); }
int main() { char buffer[80]; char* data; uint16_t value; uint8_t cmd; // wait _delay_ms( 100 ); USART_init(); FD_DDR |= FD_DIR|FD_STEP; // STATUS_DDR |= STATUS_LED; fd_reset(); _delay_ms(100); // print welcome USART_writeln( "100 Fl0ppy Music 0.1.1 (c) 2013 Matthias Hannig" ); // checkout leds... hc4094_init(); hc4094_write( 0xff ); hc4094_write( 0b01111111 ); hc4094_strobe(); hc4094_output(1); // setup timer TCCR1A = 0; TCCR1B = (1<<WGM12)|(1<<CS12)|(1<<CS10); // Clear on match, Prescale: 1024 // TCCR1B = (1<<CS12)|(1<<CS10); // Clear on 0xffff, Prescale: 1024 // TCCR1B = (1<<CS12); // Clear on 0xffff, Prescale: 256 sei(); uint8_t leds = 0; uint16_t pos = 0; for(;;) { hc4094_write( ~(1<<leds) ); hc4094_strobe(); // play imperial march if( imperial_tones_seq[pos] == 255 ) { pos = 0; continue; } if( imperial_tones_seq[pos] == 0 ) { fd_stop(); } else { fd_play(); } // Wedding mode. // There was no time left for everything else. *sigh* fd_set_tone( imperial_tones_seq[pos] ); wait_ms( imperial_delay_seq[pos] ); pos++; leds++; if( leds > 8 ) { leds = 1; } // Default serial interface /* cli(); data = USART_has_data(); if( data != NULL ) { // parse and process data memset( buffer, 0, 80 ); strncpy( buffer, data, 3 ); cmd = atoi( buffer ); strncpy( buffer, data+3, 80 ); value = atoi( buffer ); switch( cmd ) { case 100: USART_writeln( "100 Fl0ppy Music 0.1.1 (c) 2013 Matthias Hannig" ); break; // set tone case 200: if( value > 0 ) { fd_play(); } else { fd_stop(); } fd_set_tone( value ); leds++; if( leds > 8 ) { leds = 0; } hc4094_write( ~(1<<leds) ); hc4094_strobe(); break; } } sei(); */ } }
static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) { uint16_t nb = 0; int tries; uint8_t err = 0; uint8_t *driveptr = &fd_tab[minor & 1]; irqflags_t irq; if(rawflag == 1 && d_blkoff(BLKSHIFT)) return -1; udata.u_nblock *= 2; if (rawflag == 2) goto bad2; irq = di(); if (fd_selected != minor) { uint8_t err = fd_motor_on(minor|(minor > 1 ? 0: 0x10)); if (err) goto bad; motorct = 150; /* 3 seconds */ } irqrestore(irq); // kprintf("Issue command: %c drive %d block %d for %d\n", "wr"[is_read], minor, udata.u_block, udata.u_nblock); fd_cmd[0] = rawflag; fd_cmd[1] = is_read ? FD_READ : FD_WRITE; /* There are 16 256 byte sectors for DSDD. These are organised so that we switch head then step. Sectors 0-15 (our block 0-7) Track 0, side 0 Sectors 16-31 (our block 8-15) Track 0, side 1 etc */ fd_cmd[2] = udata.u_block / 16; /* Get the track we need */ fd_cmd[3] = ((udata.u_block & 15) << 1); /* 0 - 1 base is corrected in asm */ fd_cmd[4] = is_read ? OPDIR_READ: OPDIR_WRITE; fd_data = (uint16_t)udata.u_dptr; while (udata.u_nblock--) { for (tries = 0; tries < 4 ; tries++) { // kprintf("Sector: %d Head: %d Track %d\n", (fd_cmd[3]&15)+1, fd_cmd[3]>>4, fd_cmd[2]); err = fd_operation(driveptr); if (err == 0) break; if (tries > 1) fd_reset(driveptr); } /* FIXME: should we try the other half and then bale out ? */ if (tries == 3) goto bad; fd_data += 256; fd_cmd[3]++; /* Next sector for next block */ if (fd_cmd[3] == 32) { /* Next track */ fd_cmd[3] = 0; fd_cmd[2]++; } nb++; } return nb << (BLKSHIFT - 1); bad: kprintf("fd%d: error %x\n", minor, err); bad2: udata.u_error = EIO; return -1; }
static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) { int8_t tries; uint8_t err = 0; uint8_t drive = minor & 3; uint8_t trackno, sector; uint8_t large = !(minor & 0x10); const uint8_t *skew = skewtab[large]; /* skew table */ if(rawflag == 2) goto bad2; fd_map = rawflag; if (rawflag && d_blkoff(BLKSHIFT)) return -1; /* Command to go to the controller after any seek is done */ fd_cmd[0] = is_read ? FD_READ : FD_WRITE; /* Control byte: autowait, DD, motor, 5", drive bit */ fd_cmd[1] = 0xE0 | selmap[drive]; if (large) fd_cmd[1] = 0x10; /* turn on 8" bit */ /* Directon of xfer */ fd_cmd[2] = is_read ? OPDIR_READ: OPDIR_WRITE; fd_cmd[5] = 0x10 | delay[drive]; /* * Restore the track register to match this drive */ if (track[drive] != 0xFF) fd_track = track[drive]; else fd_reset(); /* * Begin transfers */ while (udata.u_done < udata.u_nblock) { /* Need to consider SS v DS here */ if (large) { fd_aux = 0x4C | (udata.u_block & 16) ? 2 : 0; trackno = udata.u_block / 32; sector = udata.u_block % 16; } else { trackno = udata.u_block / 20; sector = udata.u_block % 20; if (sector > 9) { sector -= 10; fd_aux = 0x5E; /* side 1 */ } else fd_aux = 0x5C; } /* Buffer */ fd_cmd[3] = ((uint16_t)udata.u_dptr) & 0xFF; fd_cmd[4] = ((uint16_t)udata.u_dptr) >> 8; for (tries = 0; tries < 4 ; tries++) { (void)fd_data; fd_sector = skew[sector]; /* Also makes 1 based */ if (fd_track != trackno) { fd_data = trackno; if (fd_seek()) { fd_reset(); continue; } } /* Do the read or write */ err = fd_operation(); if (err == 0) break; /* Try and recover */ if (tries > 1) fd_reset(); } if (tries == 4) goto bad; udata.u_block++; udata.u_done++; } /* Save the track */ track[drive] = fd_track; return udata.u_done << 9; bad: track[drive] = fd_track; kprintf("fd%d: error %x\n", minor, err); bad2: udata.u_error = EIO; return -1; }