SLIDE 19 Transferring data (1/2)
12814 PRIVATE int do_transfer(struct wini *wn, unsigned int precomp, unsigned int count, 12815 unsigned int sector, unsigned int opcode) 12816 { 12817 struct command cmd; 12818 unsigned secspcyl = wn->pheads * wn->psectors; 12819 12820 cmd.precomp = precomp; 12821 cmd.count = count; 12822 cmd.command = opcode == DEV_SCATTER ? CMD_WRITE : CMD_READ; 12823 /* 12826 if (wn->ldhpref & LDH_LBA) { 12827 cmd.sector = (sector >> 0) & 0xFF; 12828 cmd.cyl_lo = (sector >> 8) & 0xFF; 12829 cmd.cyl_hi = (sector >> 16) & 0xFF; 12830 cmd.ldh = wn->ldhpref | ((sector >> 24) & 0xF); 12831 } else { 12832 int cylinder, head, sec; 12833 cylinder = sector / secspcyl; 12834 head = (sector % secspcyl) / wn->psectors; 12835 sec = sector % wn->psectors; 12836 cmd.sector = sec + 1; 12837 cmd.cyl_lo = cylinder & BYTE; 12838 cmd.cyl_hi = (cylinder >> 8) & BYTE; 12839 cmd.ldh = wn->ldhpref | head; 12840 } 12841 12842 return com_out(&cmd); 12843 }
03 – 36 Input/Output/3.7 Disks
Transferring data (2/2)
04125 /* Macro shorthand to set (port,value)-pair. */ 04126 #define pv_set(pv, p, v) ((pv).port = (p), (pv).value = (v)) ..... 12947 PRIVATE int com_out(cmd) 12948 struct command *cmd; /* Command block */ 12949 { 12950 /* Output the command block to the winchester controller and return status */ 12951 12952 struct wini *wn = w_wn; 12953 unsigned base_cmd = wn->base_cmd; 12954 unsigned base_ctl = wn->base_ctl; 12955 pvb_pair_t outbyte[7]; /* vector for sys_voutb() */ 12956 int s; /* status for sys_(v)outb() */ ..... 12965 /* Select drive. */ 12966 if ((s=sys_outb(base_cmd + REG_LDH, cmd->ldh)) != OK) 12967 panic(w_name(),"Couldn’t write register to select drive",s); 12968 12969 if (!w_waitfor(STATUS_BSY, 0)) { 12970 printf("%s: com_out: drive not ready\n", w_name()); 12971 return(ERR); 12972 } 12973 12974 /* Schedule a wakeup call, some controllers are flaky. This is done with 12975 * a synchronous alarm. If a timeout occurs a SYN_ALARM message is sent 12976 * from HARDWARE, so that w_intr_wait() can call w_timeout() in case the 12977 * controller was not able to execute the command. Leftover timeouts are 12978 * simply ignored by the main loop. 12979 */ 12980 sys_setalarm(wakeup_ticks, 0); 12981 12982 wn->w_status = STATUS_ADMBSY; 12983 w_command = cmd->command; 12984 pv_set(outbyte[0], base_ctl + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0); 12985 pv_set(outbyte[1], base_cmd + REG_PRECOMP, cmd->precomp); 12986 pv_set(outbyte[2], base_cmd + REG_COUNT, cmd->count); 12987 pv_set(outbyte[3], base_cmd + REG_SECTOR, cmd->sector); 12988 pv_set(outbyte[4], base_cmd + REG_CYL_LO, cmd->cyl_lo); 12989 pv_set(outbyte[5], base_cmd + REG_CYL_HI, cmd->cyl_hi); 12990 pv_set(outbyte[6], base_cmd + REG_COMMAND, cmd->command); 12991 if ((s=sys_voutb(outbyte,7)) != OK) 12992 panic(w_name(),"Couldn’t write registers with sys_voutb()",s); 12993 return(OK); 12994 }
03 – 37 Input/Output/3.7 Disks