00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "at_wini.h"
00018
00019 #include <minix/sysutil.h>
00020 #include <minix/keymap.h>
00021 #include <sys/ioc_disk.h>
00022 #include <ibm/pci.h>
00023
00024 #define ATAPI_DEBUG 0
00025
00026
00027
00028
00029 #define REG_CMD_BASE0 0x1F0
00030 #define REG_CMD_BASE1 0x170
00031 #define REG_CTL_BASE0 0x3F6
00032 #define REG_CTL_BASE1 0x376
00033
00034 #define PCI_CTL_OFF 2
00035 #define PCI_DMA_2ND_OFF 8
00036
00037
00038
00039 #define REG_DATA 0
00040 #define REG_PRECOMP 1
00041 #define REG_COUNT 2
00042 #define REG_SECTOR 3
00043 #define REG_CYL_LO 4
00044 #define REG_CYL_HI 5
00045 #define REG_LDH 6
00046 #define LDH_DEFAULT 0xA0
00047 #define LDH_LBA 0x40
00048 #define LDH_DEV 0x10
00049 #define ldh_init(drive) (LDH_DEFAULT | ((drive) << 4))
00050
00051
00052 #define REG_STATUS 7
00053 #define STATUS_BSY 0x80
00054 #define STATUS_RDY 0x40
00055 #define STATUS_WF 0x20
00056 #define STATUS_SC 0x10
00057 #define STATUS_DRQ 0x08
00058 #define STATUS_CRD 0x04
00059 #define STATUS_IDX 0x02
00060 #define STATUS_ERR 0x01
00061 #define STATUS_ADMBSY 0x100
00062 #define REG_ERROR 1
00063 #define ERROR_BB 0x80
00064 #define ERROR_ECC 0x40
00065 #define ERROR_ID 0x10
00066 #define ERROR_AC 0x04
00067 #define ERROR_TK 0x02
00068 #define ERROR_DM 0x01
00069
00070
00071 #define REG_COMMAND 7
00072 #define CMD_IDLE 0x00
00073 #define CMD_RECALIBRATE 0x10
00074 #define CMD_READ 0x20
00075 #define CMD_READ_EXT 0x24
00076 #define CMD_READ_DMA_EXT 0x25
00077 #define CMD_WRITE 0x30
00078 #define CMD_WRITE_EXT 0x34
00079 #define CMD_WRITE_DMA_EXT 0x35
00080 #define CMD_READVERIFY 0x40
00081 #define CMD_FORMAT 0x50
00082 #define CMD_SEEK 0x70
00083 #define CMD_DIAG 0x90
00084 #define CMD_SPECIFY 0x91
00085 #define CMD_READ_DMA 0xC8
00086 #define CMD_WRITE_DMA 0xCA
00087 #define ATA_IDENTIFY 0xEC
00088
00089 #define REG_CTL 0
00090 #define CTL_NORETRY 0x80
00091 #define CTL_NOECC 0x40
00092 #define CTL_EIGHTHEADS 0x08
00093 #define CTL_RESET 0x04
00094 #define CTL_INTDISABLE 0x02
00095 #define REG_CTL_ALTSTAT 0
00096
00097
00098 #define ID_GENERAL 0x00
00099 #define ID_GEN_NOT_ATA 0x8000
00100 #define ID_CAPABILITIES 0x31
00101 #define ID_CAP_LBA 0x0200
00102 #define ID_CAP_DMA 0x0100
00103 #define ID_FIELD_VALIDITY 0x35
00104 #define ID_FV_88 0x04
00105 #define ID_MULTIWORD_DMA 0x3f
00106 #define ID_MWDMA_2_SEL 0x0400
00107 #define ID_MWDMA_1_SEL 0x0200
00108 #define ID_MWDMA_0_SEL 0x0100
00109 #define ID_MWDMA_2_SUP 0x0004
00110 #define ID_MWDMA_1_SUP 0x0002
00111 #define ID_MWDMA_0_SUP 0x0001
00112 #define ID_CSS 0x53
00113 #define ID_CSS_LBA48 0x0400
00114 #define ID_ULTRA_DMA 0x58
00115 #define ID_UDMA_5_SEL 0x2000
00116 #define ID_UDMA_4_SEL 0x1000
00117 #define ID_UDMA_3_SEL 0x0800
00118 #define ID_UDMA_2_SEL 0x0400
00119 #define ID_UDMA_1_SEL 0x0200
00120 #define ID_UDMA_0_SEL 0x0100
00121 #define ID_UDMA_5_SUP 0x0020
00122 #define ID_UDMA_4_SUP 0x0010
00123 #define ID_UDMA_3_SUP 0x0008
00124 #define ID_UDMA_2_SUP 0x0004
00125 #define ID_UDMA_1_SUP 0x0002
00126 #define ID_UDMA_0_SUP 0x0001
00127
00128
00129 #define DMA_COMMAND 0
00130 #define DMA_CMD_WRITE 0x08
00131 #define DMA_CMD_START 0x01
00132 #define DMA_STATUS 2
00133 #define DMA_ST_D1_DMACAP 0x40
00134 #define DMA_ST_D0_DMACAP 0x20
00135 #define DMA_ST_INT 0x04
00136 #define DMA_ST_ERROR 0x02
00137 #define DMA_ST_BM_ACTIVE 0x01
00138 #define DMA_PRDTP 4
00139
00140
00141 #define LBA48_CHECK_SIZE 0x0f000000
00142 #define LBA_MAX_SIZE 0x0fffffff
00143
00144
00145
00146 #if ENABLE_ATAPI
00147 #define ERROR_SENSE 0xF0
00148 #define SENSE_NONE 0x00
00149 #define SENSE_RECERR 0x10
00150 #define SENSE_NOTRDY 0x20
00151 #define SENSE_MEDERR 0x30
00152 #define SENSE_HRDERR 0x40
00153 #define SENSE_ILRQST 0x50
00154 #define SENSE_UATTN 0x60
00155 #define SENSE_DPROT 0x70
00156 #define SENSE_ABRT 0xb0
00157 #define SENSE_MISCOM 0xe0
00158 #define ERROR_MCR 0x08
00159 #define ERROR_ABRT 0x04
00160 #define ERROR_EOM 0x02
00161 #define ERROR_ILI 0x01
00162 #define REG_FEAT 1
00163 #define FEAT_OVERLAP 0x02
00164 #define FEAT_DMA 0x01
00165 #define REG_IRR 2
00166 #define IRR_REL 0x04
00167 #define IRR_IO 0x02
00168 #define IRR_COD 0x01
00169 #define REG_SAMTAG 3
00170 #define REG_CNT_LO 4
00171 #define REG_CNT_HI 5
00172 #define REG_DRIVE 6
00173 #endif
00174
00175 #define REG_STATUS 7
00176 #define STATUS_BSY 0x80
00177 #define STATUS_DRDY 0x40
00178 #define STATUS_DMADF 0x20
00179 #define STATUS_SRVCDSC 0x10
00180 #define STATUS_DRQ 0x08
00181 #define STATUS_CORR 0x04
00182 #define STATUS_CHECK 0x01
00183
00184 #ifdef ENABLE_ATAPI
00185 #define ATAPI_PACKETCMD 0xA0
00186 #define ATAPI_IDENTIFY 0xA1
00187 #define SCSI_READ10 0x28
00188 #define SCSI_SENSE 0x03
00189
00190 #define CD_SECTOR_SIZE 2048
00191 #endif
00192
00193
00194 #define NO_IRQ 0
00195
00196 #define ATAPI_PACKETSIZE 12
00197 #define SENSE_PACKETSIZE 18
00198
00199
00200 struct command {
00201 u8_t precomp;
00202 u8_t count;
00203 u8_t sector;
00204 u8_t cyl_lo;
00205 u8_t cyl_hi;
00206 u8_t ldh;
00207 u8_t command;
00208
00209
00210 u8_t count_prev;
00211 u8_t sector_prev;
00212 u8_t cyl_lo_prev;
00213 u8_t cyl_hi_prev;
00214 };
00215
00216
00217 #define ERR (-1)
00218 #define ERR_BAD_SECTOR (-2)
00219
00220
00221 #define WAKEUP (32*HZ)
00222
00223
00224 #define MAX_DRIVES 8
00225 #define COMPAT_DRIVES 4
00226 #if _WORD_SIZE > 2
00227 #define MAX_SECS 256
00228 #else
00229 #define MAX_SECS 127
00230 #endif
00231 #define MAX_ERRORS 4
00232 #define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE)
00233 #define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
00234 #define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE)
00235 #define DELAY_USECS 1000
00236 #define DELAY_TICKS 1
00237 #define DEF_TIMEOUT_TICKS 300
00238 #define RECOVERY_USECS 500000
00239 #define RECOVERY_TICKS 30
00240 #define INITIALIZED 0x01
00241 #define DEAF 0x02
00242 #define SMART 0x04
00243 #if ENABLE_ATAPI
00244 #define ATAPI 0x08
00245 #else
00246 #define ATAPI 0
00247 #endif
00248 #define IDENTIFIED 0x10
00249 #define IGNORING 0x20
00250
00251
00252 int timeout_ticks = DEF_TIMEOUT_TICKS, max_errors = MAX_ERRORS;
00253 int wakeup_ticks = WAKEUP;
00254 long w_standard_timeouts = 0, w_pci_debug = 0, w_instance = 0,
00255 disable_dma = 0, atapi_debug = 0;
00256
00257 int w_testing = 0, w_silent = 0;
00258
00259 int w_next_drive = 0;
00260
00261
00262
00263
00264
00265
00266
00267 PRIVATE struct wini {
00268 unsigned state;
00269 unsigned short w_status;
00270 unsigned base_cmd;
00271 unsigned base_ctl;
00272 unsigned base_dma;
00273 unsigned irq;
00274 unsigned irq_mask;
00275 unsigned irq_need_ack;
00276 int irq_hook_id;
00277 int lba48;
00278 int dma;
00279 unsigned lcylinders;
00280 unsigned lheads;
00281 unsigned lsectors;
00282 unsigned pcylinders;
00283 unsigned pheads;
00284 unsigned psectors;
00285 unsigned ldhpref;
00286 unsigned precomp;
00287 unsigned max_count;
00288 unsigned open_ct;
00289 struct device part[DEV_PER_DRIVE];
00290 struct device subpart[SUB_PER_DRIVE];
00291 } wini[MAX_DRIVES], *w_wn;
00292
00293 PRIVATE int w_device = -1;
00294 PRIVATE int w_controller = -1;
00295 PRIVATE int w_major = -1;
00296 PRIVATE char w_id_string[40];
00297
00298 PRIVATE int win_tasknr;
00299 PRIVATE int w_command;
00300 PRIVATE u8_t w_byteval;
00301 PRIVATE int w_drive;
00302 PRIVATE int w_controller;
00303 PRIVATE struct device *w_dv;
00304
00305
00306
00307
00308 #define ATA_DMA_SECTORS 64
00309 #define ATA_DMA_BUF_SIZE (ATA_DMA_SECTORS*SECTOR_SIZE)
00310
00311 PRIVATE char dma_buf[ATA_DMA_BUF_SIZE];
00312 PRIVATE phys_bytes dma_buf_phys;
00313
00314 #define N_PRDTE 1024
00315
00316 PRIVATE struct prdte
00317 {
00318 u32_t prdte_base;
00319 u16_t prdte_count;
00320 u8_t prdte_reserved;
00321 u8_t prdte_flags;
00322 } prdt[N_PRDTE];
00323 PRIVATE phys_bytes prdt_phys;
00324
00325 #define PRDTE_FL_EOT 0x80
00326
00327
00328 PRIVATE struct
00329 {
00330 u16_t vendor;
00331 u16_t device;
00332 } raid_table[]=
00333 {
00334 { 0x1106, 0x3149 },
00335 { 0, 0 }
00336 };
00337
00338 FORWARD _PROTOTYPE( void init_params, (void) );
00339 FORWARD _PROTOTYPE( void init_drive, (struct wini *w, int base_cmd,
00340 int base_ctl, int base_dma, int irq, int ack, int hook,
00341 int drive) );
00342 FORWARD _PROTOTYPE( void init_params_pci, (int) );
00343 FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
00344 FORWARD _PROTOTYPE( struct device *w_prepare, (int dev) );
00345 FORWARD _PROTOTYPE( int w_identify, (void) );
00346 FORWARD _PROTOTYPE( char *w_name, (void) );
00347 FORWARD _PROTOTYPE( int w_specify, (void) );
00348 FORWARD _PROTOTYPE( int w_io_test, (void) );
00349 FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position,
00350 iovec_t *iov, unsigned nr_req) );
00351 FORWARD _PROTOTYPE( int com_out, (struct command *cmd) );
00352 FORWARD _PROTOTYPE( int com_out_ext, (struct command *cmd) );
00353 FORWARD _PROTOTYPE( void setup_dma, (unsigned *sizep, int proc_nr,
00354 iovec_t *iov, int do_write, int *do_copyoutp) );
00355 FORWARD _PROTOTYPE( void w_need_reset, (void) );
00356 FORWARD _PROTOTYPE( void ack_irqs, (unsigned int) );
00357 FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
00358 FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr) );
00359 FORWARD _PROTOTYPE( int w_hw_int, (struct driver *dp, message *m_ptr) );
00360 FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) );
00361 FORWARD _PROTOTYPE( void w_timeout, (void) );
00362 FORWARD _PROTOTYPE( int w_reset, (void) );
00363 FORWARD _PROTOTYPE( void w_intr_wait, (void) );
00364 FORWARD _PROTOTYPE( int at_intr_wait, (void) );
00365 FORWARD _PROTOTYPE( int w_waitfor, (int mask, int value) );
00366 FORWARD _PROTOTYPE( int w_waitfor_dma, (int mask, int value) );
00367 FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry) );
00368 #if ENABLE_ATAPI
00369 FORWARD _PROTOTYPE( int atapi_sendpacket, (u8_t *packet, unsigned cnt) );
00370 FORWARD _PROTOTYPE( int atapi_intr_wait, (void) );
00371 FORWARD _PROTOTYPE( int atapi_open, (void) );
00372 FORWARD _PROTOTYPE( void atapi_close, (void) );
00373 FORWARD _PROTOTYPE( int atapi_transfer, (int proc_nr, int opcode,
00374 off_t position, iovec_t *iov, unsigned nr_req) );
00375 #endif
00376
00377
00378 PRIVATE struct driver w_dtab = {
00379 w_name,
00380 w_do_open,
00381 w_do_close,
00382 do_diocntl,
00383 w_prepare,
00384 w_transfer,
00385 nop_cleanup,
00386 w_geometry,
00387 nop_signal,
00388 nop_alarm,
00389 nop_cancel,
00390 nop_select,
00391 w_other,
00392 w_hw_int
00393 };
00394
00395
00396
00397
00398 PUBLIC int main()
00399 {
00400
00401 struct sigaction sa;
00402
00403 sa.sa_handler = SIG_MESS;
00404 sigemptyset(&sa.sa_mask);
00405 sa.sa_flags = 0;
00406 if (sigaction(SIGTERM,&sa,NULL)<0) panic("AT","sigaction failed", errno);
00407
00408
00409 init_params();
00410 signal(SIGTERM, SIG_IGN);
00411 driver_task(&w_dtab);
00412 return(OK);
00413 }
00414
00415
00416
00417
00418 PRIVATE void init_params()
00419 {
00420
00421
00422 u16_t parv[2];
00423 unsigned int vector, size;
00424 int drive, nr_drives;
00425 struct wini *wn;
00426 u8_t params[16];
00427 int s;
00428
00429
00430 env_parse("ata_std_timeout", "d", 0, &w_standard_timeouts, 0, 1);
00431 env_parse("ata_pci_debug", "d", 0, &w_pci_debug, 0, 1);
00432 env_parse("ata_instance", "d", 0, &w_instance, 0, 8);
00433 env_parse("ata_no_dma", "d", 0, &disable_dma, 0, 1);
00434 env_parse("atapi_debug", "d", 0, &atapi_debug, 0, 1);
00435
00436 if (disable_dma)
00437 printf("DMA for ATA devices is disabled.\n");
00438
00439 s= sys_umap(SELF, D, (vir_bytes)dma_buf, sizeof(dma_buf), &dma_buf_phys);
00440 if (s != 0)
00441 panic("at_wini", "can't map dma buffer", s);
00442
00443 s= sys_umap(SELF, D, (vir_bytes)prdt, sizeof(prdt), &prdt_phys);
00444 if (s != 0)
00445 panic("at_wini", "can't map prd table", s);
00446
00447 if (w_instance == 0) {
00448
00449 if ((s=sys_vircopy(SELF, BIOS_SEG, NR_HD_DRIVES_ADDR,
00450 SELF, D, (vir_bytes) params, NR_HD_DRIVES_SIZE)) != OK)
00451 panic(w_name(), "Couldn't read BIOS", s);
00452 if ((nr_drives = params[0]) > 2) nr_drives = 2;
00453
00454 for (drive = 0, wn = wini; drive < COMPAT_DRIVES; drive++, wn++) {
00455 if (drive < nr_drives) {
00456
00457 vector = (drive == 0) ? BIOS_HD0_PARAMS_ADDR:BIOS_HD1_PARAMS_ADDR;
00458 size = (drive == 0) ? BIOS_HD0_PARAMS_SIZE:BIOS_HD1_PARAMS_SIZE;
00459 if ((s=sys_vircopy(SELF, BIOS_SEG, vector,
00460 SELF, D, (vir_bytes) parv, size)) != OK)
00461 panic(w_name(), "Couldn't read BIOS", s);
00462
00463
00464 if ((s=sys_vircopy(
00465 SELF, BIOS_SEG, hclick_to_physb(parv[1]) + parv[0],
00466 SELF, D, (phys_bytes) params, 16L))!=OK)
00467 panic(w_name(),"Couldn't copy parameters", s);
00468
00469
00470 wn->lcylinders = bp_cylinders(params);
00471 wn->lheads = bp_heads(params);
00472 wn->lsectors = bp_sectors(params);
00473 wn->precomp = bp_precomp(params) >> 2;
00474 }
00475
00476
00477 init_drive(wn,
00478 drive < 2 ? REG_CMD_BASE0 : REG_CMD_BASE1,
00479 drive < 2 ? REG_CTL_BASE0 : REG_CTL_BASE1,
00480 0 , NO_IRQ, 0, 0, drive);
00481 w_next_drive++;
00482 }
00483 }
00484
00485
00486
00487
00488 if (w_instance == 0)
00489 init_params_pci(0);
00490 else
00491 init_params_pci(w_instance*2-1);
00492
00493 }
00494
00495 #define ATA_IF_NOTCOMPAT1 (1L << 0)
00496 #define ATA_IF_NOTCOMPAT2 (1L << 2)
00497
00498
00499
00500
00501 PRIVATE void init_drive(struct wini *w, int base_cmd, int base_ctl,
00502 int base_dma, int irq, int ack, int hook, int drive)
00503 {
00504 w->state = 0;
00505 w->w_status = 0;
00506 w->base_cmd = base_cmd;
00507 w->base_ctl = base_ctl;
00508 w->base_dma = base_dma;
00509 w->irq = irq;
00510 w->irq_mask = 1 << irq;
00511 w->irq_need_ack = ack;
00512 w->irq_hook_id = hook;
00513 w->ldhpref = ldh_init(drive);
00514 w->max_count = MAX_SECS << SECTOR_SHIFT;
00515 w->lba48 = 0;
00516 w->dma = 0;
00517 }
00518
00519
00520
00521
00522 PRIVATE void init_params_pci(int skip)
00523 {
00524 int i, r, devind, drive;
00525 int irq, irq_hook, raid;
00526 u8_t bcr, scr, interface;
00527 u16_t vid, did;
00528 u32_t base_dma, t3;
00529
00530 pci_init();
00531 for(drive = w_next_drive; drive < MAX_DRIVES; drive++)
00532 wini[drive].state = IGNORING;
00533 for(r = pci_first_dev(&devind, &vid, &did); r != 0;
00534 r = pci_next_dev(&devind, &vid, &did)) {
00535
00536 raid= 0;
00537
00538
00539
00540
00541 bcr= pci_attr_r8(devind, PCI_BCR);
00542 scr= pci_attr_r8(devind, PCI_SCR);
00543 interface= pci_attr_r8(devind, PCI_PIFR);
00544 t3= ((bcr << 16) | (scr << 8) | interface);
00545 if (bcr == PCI_BCR_MASS_STORAGE && scr == PCI_MS_IDE)
00546 ;
00547 else if (t3 == PCI_T3_RAID)
00548 {
00549 for (i= 0; raid_table[i].vendor != 0; i++)
00550 {
00551 if (raid_table[i].vendor == vid &&
00552 raid_table[i].device == did)
00553 {
00554 break;
00555 }
00556 }
00557 if (raid_table[i].vendor == 0)
00558 {
00559 printf(
00560 "atapci skipping unsupported RAID controller 0x%04x / 0x%04x\n",
00561 vid, did);
00562 continue;
00563 }
00564 printf("found supported RAID controller\n");
00565 raid= 1;
00566 }
00567 else
00568 continue;
00569
00570
00571
00572
00573 irq = pci_attr_r8(devind, PCI_ILR);
00574
00575
00576 if (raid || (interface & (ATA_IF_NOTCOMPAT1 | ATA_IF_NOTCOMPAT2))) {
00577 int s;
00578
00579 if (w_next_drive >= MAX_DRIVES)
00580 {
00581
00582
00583
00584 continue;
00585 }
00586
00587 irq_hook = irq;
00588 if (skip > 0) {
00589 if (w_pci_debug)
00590 {
00591 printf(
00592 "atapci skipping controller (remain %d)\n",
00593 skip);
00594 }
00595 skip--;
00596 continue;
00597 }
00598 if ((s=sys_irqsetpolicy(irq, 0, &irq_hook)) != OK) {
00599 printf("atapci: couldn't set IRQ policy %d\n", irq);
00600 continue;
00601 }
00602 if ((s=sys_irqenable(&irq_hook)) != OK) {
00603 printf("atapci: couldn't enable IRQ line %d\n", irq);
00604 continue;
00605 }
00606 }
00607
00608 base_dma = pci_attr_r32(devind, PCI_BAR_5) & 0xfffffffc;
00609
00610
00611 if (raid || (interface & ATA_IF_NOTCOMPAT1)) {
00612 u32_t base_cmd, base_ctl;
00613
00614 base_cmd = pci_attr_r32(devind, PCI_BAR) & 0xfffffffc;
00615 base_ctl = pci_attr_r32(devind, PCI_BAR_2) & 0xfffffffc;
00616 if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) {
00617 init_drive(&wini[w_next_drive],
00618 base_cmd, base_ctl+PCI_CTL_OFF,
00619 base_dma, irq, 1, irq_hook, 0);
00620 init_drive(&wini[w_next_drive+1],
00621 base_cmd, base_ctl+PCI_CTL_OFF,
00622 base_dma, irq, 1, irq_hook, 1);
00623 if (w_pci_debug)
00624 printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq);
00625 w_next_drive += 2;
00626 } else printf("atapci: ignored drives on primary channel, base %x\n", base_cmd);
00627 }
00628 else
00629 {
00630
00631 for (i= 0; i<MAX_DRIVES; i++)
00632 {
00633 if (wini[i].base_cmd == REG_CMD_BASE0)
00634 wini[i].base_dma= base_dma;
00635 }
00636 }
00637
00638
00639 if (raid || (interface & ATA_IF_NOTCOMPAT2)) {
00640 u32_t base_cmd, base_ctl;
00641
00642 base_cmd = pci_attr_r32(devind, PCI_BAR_3) & 0xfffffffc;
00643 base_ctl = pci_attr_r32(devind, PCI_BAR_4) & 0xfffffffc;
00644 if (base_dma != 0)
00645 base_dma += PCI_DMA_2ND_OFF;
00646 if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) {
00647 init_drive(&wini[w_next_drive],
00648 base_cmd, base_ctl+PCI_CTL_OFF, base_dma,
00649 irq, 1, irq_hook, 2);
00650 init_drive(&wini[w_next_drive+1],
00651 base_cmd, base_ctl+PCI_CTL_OFF, base_dma,
00652 irq, 1, irq_hook, 3);
00653 if (w_pci_debug)
00654 printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq);
00655 w_next_drive += 2;
00656 } else printf("atapci: ignored drives on secondary channel, base %x\n", base_cmd);
00657 }
00658 else
00659 {
00660
00661 for (i= 0; i<MAX_DRIVES; i++)
00662 {
00663 if (wini[i].base_cmd == REG_CMD_BASE1 && base_dma != 0)
00664 wini[i].base_dma= base_dma+PCI_DMA_2ND_OFF;
00665 }
00666 }
00667 }
00668 }
00669
00670
00671
00672
00673 PRIVATE int w_do_open(dp, m_ptr)
00674 struct driver *dp;
00675 message *m_ptr;
00676 {
00677
00678
00679 struct wini *wn;
00680
00681 if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
00682
00683 wn = w_wn;
00684
00685
00686 if (wn->state & IGNORING) return ENXIO;
00687
00688
00689
00690
00691 if (!(wn->state & IDENTIFIED) || (wn->state & DEAF)) {
00692
00693 if (w_identify() != OK) {
00694 #if VERBOSE
00695 printf("%s: probe failed\n", w_name());
00696 #endif
00697 if (wn->state & DEAF) w_reset();
00698 wn->state = IGNORING;
00699 return(ENXIO);
00700 }
00701
00702
00703
00704
00705
00706 if (!(wn->state & ATAPI) && w_io_test() != OK) {
00707 wn->state |= IGNORING;
00708 return(ENXIO);
00709 }
00710
00711 #if VERBOSE
00712 printf("%s: AT driver detected ", w_name());
00713 if (wn->state & (SMART|ATAPI)) {
00714 printf("%.40s\n", w_id_string);
00715 } else {
00716 printf("%ux%ux%u\n", wn->pcylinders, wn->pheads, wn->psectors);
00717 }
00718 #endif
00719 }
00720
00721 #if ENABLE_ATAPI
00722 if ((wn->state & ATAPI) && (m_ptr->COUNT & W_BIT))
00723 return(EACCES);
00724 #endif
00725
00726
00727
00728
00729 if (wn->open_ct == 0) {
00730 #if ENABLE_ATAPI
00731 if (wn->state & ATAPI) {
00732 int r;
00733 if ((r = atapi_open()) != OK) return(r);
00734 }
00735 #endif
00736
00737
00738 partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY, wn->state & ATAPI);
00739 }
00740 wn->open_ct++;
00741 return(OK);
00742 }
00743
00744
00745
00746
00747 PRIVATE struct device *w_prepare(int device)
00748 {
00749
00750 struct wini *prev_wn;
00751 prev_wn = w_wn;
00752 w_device = device;
00753
00754 if (device < NR_MINORS) {
00755 w_drive = device / DEV_PER_DRIVE;
00756 w_wn = &wini[w_drive];
00757 w_dv = &w_wn->part[device % DEV_PER_DRIVE];
00758 } else
00759 if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {
00760 w_drive = device / SUB_PER_DRIVE;
00761 w_wn = &wini[w_drive];
00762 w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
00763 } else {
00764 w_device = -1;
00765 return(NIL_DEV);
00766 }
00767 return(w_dv);
00768 }
00769
00770
00771
00772
00773 PRIVATE int w_identify()
00774 {
00775
00776
00777
00778
00779 struct wini *wn = w_wn;
00780 struct command cmd;
00781 int i, s;
00782 int id_dma, ultra_dma;
00783 u32_t dma_base;
00784 u16_t w;
00785 unsigned long dma_status;
00786 unsigned long size;
00787 #define id_byte(n) (&tmp_buf[2 * (n)])
00788 #define id_word(n) (((u16_t) id_byte(n)[0] << 0) \
00789 |((u16_t) id_byte(n)[1] << 8))
00790 #define id_longword(n) (((u32_t) id_byte(n)[0] << 0) \
00791 |((u32_t) id_byte(n)[1] << 8) \
00792 |((u32_t) id_byte(n)[2] << 16) \
00793 |((u32_t) id_byte(n)[3] << 24))
00794
00795
00796 cmd.ldh = wn->ldhpref;
00797 cmd.command = ATA_IDENTIFY;
00798 if (com_simple(&cmd) == OK && w_waitfor(STATUS_DRQ, STATUS_DRQ) &&
00799 !(wn->w_status & (STATUS_ERR|STATUS_WF))) {
00800
00801
00802 if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, SECTOR_SIZE)) != OK)
00803 panic(w_name(),"Call to sys_insw() failed", s);
00804
00805 if (id_word(0) & ID_GEN_NOT_ATA)
00806 {
00807 printf("%s: not an ATA device?\n", w_name());
00808 return ERR;
00809 }
00810
00811
00812 wn->state |= SMART;
00813
00814
00815 for (i = 0; i < 40; i++) w_id_string[i] = id_byte(27)[i^1];
00816
00817
00818 wn->pcylinders = id_word(1);
00819 wn->pheads = id_word(3);
00820 wn->psectors = id_word(6);
00821 size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;
00822
00823 w= id_word(ID_CAPABILITIES);
00824 if ((w & ID_CAP_LBA) && size > 512L*1024*2) {
00825
00826
00827
00828 wn->ldhpref |= LDH_LBA;
00829 size = id_longword(60);
00830
00831 w= id_word(ID_CSS);
00832 if (size < LBA48_CHECK_SIZE)
00833 {
00834
00835 }
00836 else if (w & ID_CSS_LBA48) {
00837
00838 if (id_longword(102)) {
00839
00840
00841
00842
00843
00844 size = ULONG_MAX;
00845 } else {
00846
00847 size = id_longword(100);
00848 }
00849 wn->lba48 = 1;
00850 }
00851
00852
00853
00854
00855 w= id_word(ID_CAPABILITIES);
00856 id_dma= !!(w & ID_CAP_DMA);
00857 w= id_byte(ID_FIELD_VALIDITY)[0];
00858 ultra_dma= !!(w & ID_FV_88);
00859 dma_base= wn->base_dma;
00860 if (dma_base)
00861 {
00862 if (sys_inb(dma_base + DMA_STATUS, &dma_status) != OK)
00863 {
00864 panic(w_name(),
00865 "unable to read DMA status register",
00866 NO_NUM);
00867 }
00868 }
00869 if (disable_dma)
00870 ;
00871 else if (id_dma && dma_base)
00872 {
00873 w= id_word(ID_MULTIWORD_DMA);
00874 if (w & (ID_MWDMA_2_SUP|ID_MWDMA_1_SUP|ID_MWDMA_0_SUP))
00875 {
00876 printf(
00877 "%s: multiword DMA modes supported:%s%s%s\n",
00878 w_name(),
00879 (w & ID_MWDMA_0_SUP) ? " 0" : "",
00880 (w & ID_MWDMA_1_SUP) ? " 1" : "",
00881 (w & ID_MWDMA_2_SUP) ? " 2" : "");
00882 }
00883 if (w & (ID_MWDMA_0_SEL|ID_MWDMA_1_SEL|ID_MWDMA_2_SEL))
00884 {
00885 printf(
00886 "%s: multiword DMA mode selected:%s%s%s\n",
00887 w_name(),
00888 (w & ID_MWDMA_0_SEL) ? " 0" : "",
00889 (w & ID_MWDMA_1_SEL) ? " 1" : "",
00890 (w & ID_MWDMA_2_SEL) ? " 2" : "");
00891 }
00892 if (ultra_dma)
00893 {
00894 w= id_word(ID_ULTRA_DMA);
00895 if (w & (ID_UDMA_0_SUP|ID_UDMA_1_SUP|
00896 ID_UDMA_2_SUP|ID_UDMA_3_SUP|
00897 ID_UDMA_4_SUP|ID_UDMA_5_SUP))
00898 {
00899 printf(
00900 "%s: Ultra DMA modes supported:%s%s%s%s%s%s\n",
00901 w_name(),
00902 (w & ID_UDMA_0_SUP) ? " 0" : "",
00903 (w & ID_UDMA_1_SUP) ? " 1" : "",
00904 (w & ID_UDMA_2_SUP) ? " 2" : "",
00905 (w & ID_UDMA_3_SUP) ? " 3" : "",
00906 (w & ID_UDMA_4_SUP) ? " 4" : "",
00907 (w & ID_UDMA_5_SUP) ? " 5" : "");
00908 }
00909 if (w & (ID_UDMA_0_SEL|ID_UDMA_1_SEL|
00910 ID_UDMA_2_SEL|ID_UDMA_3_SEL|
00911 ID_UDMA_4_SEL|ID_UDMA_5_SEL))
00912 {
00913 printf(
00914 "%s: Ultra DMA mode selected:%s%s%s%s%s%s\n",
00915 w_name(),
00916 (w & ID_UDMA_0_SEL) ? " 0" : "",
00917 (w & ID_UDMA_1_SEL) ? " 1" : "",
00918 (w & ID_UDMA_2_SEL) ? " 2" : "",
00919 (w & ID_UDMA_3_SEL) ? " 3" : "",
00920 (w & ID_UDMA_4_SEL) ? " 4" : "",
00921 (w & ID_UDMA_5_SEL) ? " 5" : "");
00922 }
00923 }
00924 wn->dma= 1;
00925 }
00926 else if (id_dma || dma_base)
00927 {
00928 printf("id_dma %d, dma_base 0x%x\n", id_dma, dma_base);
00929 }
00930 else
00931 printf("no DMA support\n");
00932
00933 #if 0
00934 if (wn->dma && wn == &wini[0])
00935 {
00936 printf("disabling DMA for drive 0\n");
00937 wn->dma= 0;
00938 }
00939 #endif
00940 }
00941
00942 if (wn->lcylinders == 0) {
00943
00944 wn->lcylinders = wn->pcylinders;
00945 wn->lheads = wn->pheads;
00946 wn->lsectors = wn->psectors;
00947 while (wn->lcylinders > 1024) {
00948 wn->lheads *= 2;
00949 wn->lcylinders /= 2;
00950 }
00951 }
00952 #if ENABLE_ATAPI
00953 } else
00954 if (cmd.command = ATAPI_IDENTIFY,
00955 com_simple(&cmd) == OK && w_waitfor(STATUS_DRQ, STATUS_DRQ) &&
00956 !(wn->w_status & (STATUS_ERR|STATUS_WF))) {
00957
00958 wn->state |= ATAPI;
00959
00960
00961 if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, 512)) != OK)
00962 panic(w_name(),"Call to sys_insw() failed", s);
00963
00964
00965 for (i = 0; i < 40; i++) w_id_string[i] = id_byte(27)[i^1];
00966
00967 size = 0;
00968 #endif
00969 } else {
00970
00971
00972
00973 if (wn->lcylinders == 0) { return(ERR); }
00974 wn->pcylinders = wn->lcylinders;
00975 wn->pheads = wn->lheads;
00976 wn->psectors = wn->lsectors;
00977 size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;
00978 }
00979
00980
00981 wn->part[0].dv_size = mul64u(size, SECTOR_SIZE);
00982
00983
00984 if (w_specify() != OK && w_specify() != OK) {
00985 return(ERR);
00986 }
00987
00988 if (wn->irq == NO_IRQ) {
00989
00990 wn->irq = w_drive < 2 ? AT_WINI_0_IRQ : AT_WINI_1_IRQ;
00991 wn->irq_hook_id = wn->irq;
00992 if ((s=sys_irqsetpolicy(wn->irq, IRQ_REENABLE, &wn->irq_hook_id)) != OK)
00993 panic(w_name(), "couldn't set IRQ policy", s);
00994 if ((s=sys_irqenable(&wn->irq_hook_id)) != OK)
00995 panic(w_name(), "couldn't enable IRQ line", s);
00996 }
00997 wn->state |= IDENTIFIED;
00998 return(OK);
00999 }
01000
01001
01002
01003
01004 PRIVATE char *w_name()
01005 {
01006
01007 static char name[] = "AT-D0";
01008
01009 name[4] = '0' + w_drive;
01010 return name;
01011 }
01012
01013
01014
01015
01016 PRIVATE int w_io_test(void)
01017 {
01018 int r, save_dev;
01019 int save_timeout, save_errors, save_wakeup;
01020 iovec_t iov;
01021 #ifdef CD_SECTOR_SIZE
01022 static char buf[CD_SECTOR_SIZE];
01023 #else
01024 static char buf[SECTOR_SIZE];
01025 #endif
01026
01027 iov.iov_addr = (vir_bytes) buf;
01028 iov.iov_size = sizeof(buf);
01029 save_dev = w_device;
01030
01031
01032 save_timeout = timeout_ticks;
01033 save_errors = max_errors;
01034 save_wakeup = wakeup_ticks;
01035
01036 if (!w_standard_timeouts) {
01037 timeout_ticks = HZ * 4;
01038 wakeup_ticks = HZ * 6;
01039 max_errors = 3;
01040 }
01041
01042 w_testing = 1;
01043
01044
01045 if (w_prepare(w_drive * DEV_PER_DRIVE) == NIL_DEV)
01046 panic(w_name(), "Couldn't switch devices", NO_NUM);
01047
01048 r = w_transfer(SELF, DEV_GATHER, 0, &iov, 1);
01049
01050
01051 if (w_prepare(save_dev) == NIL_DEV)
01052 panic(w_name(), "Couldn't switch back devices", NO_NUM);
01053
01054
01055 timeout_ticks = save_timeout;
01056 max_errors = save_errors;
01057 wakeup_ticks = save_wakeup;
01058 w_testing = 0;
01059
01060
01061 if (r != OK || iov.iov_size != 0) {
01062 return ERR;
01063 }
01064
01065
01066
01067 return OK;
01068 }
01069
01070
01071
01072
01073 PRIVATE int w_specify()
01074 {
01075
01076
01077 struct wini *wn = w_wn;
01078 struct command cmd;
01079
01080 if ((wn->state & DEAF) && w_reset() != OK) {
01081 return(ERR);
01082 }
01083
01084 if (!(wn->state & ATAPI)) {
01085
01086 cmd.precomp = wn->precomp;
01087 cmd.count = wn->psectors;
01088 cmd.ldh = w_wn->ldhpref | (wn->pheads - 1);
01089 cmd.command = CMD_SPECIFY;
01090
01091
01092 if (com_simple(&cmd) != OK) return(ERR);
01093
01094 if (!(wn->state & SMART)) {
01095
01096 cmd.sector = 0;
01097 cmd.cyl_lo = 0;
01098 cmd.cyl_hi = 0;
01099 cmd.ldh = w_wn->ldhpref;
01100 cmd.command = CMD_RECALIBRATE;
01101
01102 if (com_simple(&cmd) != OK) return(ERR);
01103 }
01104 }
01105 wn->state |= INITIALIZED;
01106 return(OK);
01107 }
01108
01109
01110
01111
01112 PRIVATE int do_transfer(struct wini *wn, unsigned int precomp,
01113 unsigned int count, unsigned int sector,
01114 unsigned int opcode, int do_dma)
01115 {
01116 struct command cmd;
01117 unsigned int sector_high;
01118 unsigned secspcyl = wn->pheads * wn->psectors;
01119 int do_lba48;
01120
01121 sector_high= 0;
01122
01123 do_lba48= 0;
01124 if (sector >= LBA48_CHECK_SIZE || sector_high != 0)
01125 {
01126 if (wn->lba48)
01127 do_lba48= 1;
01128 else if (sector > LBA_MAX_SIZE || sector_high != 0)
01129 {
01130
01131 return EIO;
01132 }
01133 }
01134
01135 cmd.precomp = precomp;
01136 cmd.count = count;
01137 if (do_dma)
01138 {
01139 cmd.command = opcode == DEV_SCATTER ? CMD_WRITE_DMA :
01140 CMD_READ_DMA;
01141 }
01142 else
01143 cmd.command = opcode == DEV_SCATTER ? CMD_WRITE : CMD_READ;
01144
01145 if (do_lba48) {
01146 if (do_dma)
01147 {
01148 cmd.command = ((opcode == DEV_SCATTER) ?
01149 CMD_WRITE_DMA_EXT : CMD_READ_DMA_EXT);
01150 }
01151 else
01152 {
01153 cmd.command = ((opcode == DEV_SCATTER) ?
01154 CMD_WRITE_EXT : CMD_READ_EXT);
01155 }
01156 cmd.count_prev= (count >> 8);
01157 cmd.sector = (sector >> 0) & 0xFF;
01158 cmd.cyl_lo = (sector >> 8) & 0xFF;
01159 cmd.cyl_hi = (sector >> 16) & 0xFF;
01160 cmd.sector_prev= (sector >> 24) & 0xFF;
01161 cmd.cyl_lo_prev= (sector_high) & 0xFF;
01162 cmd.cyl_hi_prev= (sector_high >> 8) & 0xFF;
01163 cmd.ldh = wn->ldhpref;
01164
01165 return com_out_ext(&cmd);
01166 } else if (wn->ldhpref & LDH_LBA) {
01167 cmd.sector = (sector >> 0) & 0xFF;
01168 cmd.cyl_lo = (sector >> 8) & 0xFF;
01169 cmd.cyl_hi = (sector >> 16) & 0xFF;
01170 cmd.ldh = wn->ldhpref | ((sector >> 24) & 0xF);
01171 } else {
01172 int cylinder, head, sec;
01173 cylinder = sector / secspcyl;
01174 head = (sector % secspcyl) / wn->psectors;
01175 sec = sector % wn->psectors;
01176 cmd.sector = sec + 1;
01177 cmd.cyl_lo = cylinder & BYTE;
01178 cmd.cyl_hi = (cylinder >> 8) & BYTE;
01179 cmd.ldh = wn->ldhpref | head;
01180 }
01181
01182 return com_out(&cmd);
01183 }
01184
01185
01186
01187
01188 PRIVATE int w_transfer(proc_nr, opcode, position, iov, nr_req)
01189 int proc_nr;
01190 int opcode;
01191 off_t position;
01192 iovec_t *iov;
01193 unsigned nr_req;
01194 {
01195 struct wini *wn = w_wn;
01196 iovec_t *iop, *iov_end = iov + nr_req;
01197 int n, r, s, errors, do_dma, do_write, do_copyout;
01198 unsigned long v, block, w_status;
01199 unsigned long dv_size = cv64ul(w_dv->dv_size);
01200 unsigned cylinder, head, sector, nbytes;
01201 unsigned dma_buf_offset;
01202
01203 #if ENABLE_ATAPI
01204 if (w_wn->state & ATAPI) {
01205 return atapi_transfer(proc_nr, opcode, position, iov, nr_req);
01206 }
01207 #endif
01208
01209
01210
01211
01212 if ((position & SECTOR_MASK) != 0) return(EINVAL);
01213
01214 errors = 0;
01215
01216 while (nr_req > 0) {
01217
01218 nbytes = 0;
01219 for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size;
01220 if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
01221
01222
01223 if (position >= dv_size) return(OK);
01224 if (position + nbytes > dv_size) nbytes = dv_size - position;
01225 block = div64u(add64ul(w_dv->dv_base, position), SECTOR_SIZE);
01226
01227 do_dma= wn->dma;
01228 do_write= (opcode == DEV_SCATTER);
01229
01230 if (nbytes >= wn->max_count) {
01231
01232 nbytes = wn->max_count;
01233 }
01234
01235
01236 if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
01237
01238 if (do_dma)
01239 {
01240 setup_dma(&nbytes, proc_nr, iov, do_write, &do_copyout);
01241 #if 0
01242 printf("nbytes = %d\n", nbytes);
01243 #endif
01244 }
01245
01246
01247 r = do_transfer(wn, wn->precomp, (nbytes >> SECTOR_SHIFT),
01248 block, opcode, do_dma);
01249
01250 if (opcode == DEV_SCATTER) {
01251
01252
01253
01254
01255 if (sys_inb((wn->base_ctl+REG_CTL_ALTSTAT), &w_status) != OK)
01256 panic(w_name(), "couldn't get status", NO_NUM);
01257 }
01258
01259 if (do_dma)
01260 {
01261
01262
01263
01264
01265 if ((r = at_intr_wait()) != OK)
01266 {
01267
01268
01269
01270 if (r == ERR_BAD_SECTOR || ++errors == max_errors) {
01271 w_command = CMD_IDLE;
01272 return(EIO);
01273 }
01274 continue;
01275 }
01276
01277
01278 w_waitfor_dma(DMA_ST_INT, DMA_ST_INT);
01279
01280 r= sys_inb(wn->base_dma + DMA_STATUS, &v);
01281 if (r != 0) panic("at_wini", "w_transfer: sys_inb failed", r);
01282
01283 #if 0
01284 printf("dma_status: 0x%x\n", v);
01285 #endif
01286 if (!(v & DMA_ST_INT))
01287 {
01288
01289 if (v & DMA_ST_BM_ACTIVE)
01290 panic(w_name(), "DMA did not complete", NO_NUM);
01291 else if (v & DMA_ST_ERROR)
01292 {
01293 printf("at_wini: DMA error\n");
01294 r= EIO;
01295 break;
01296 }
01297 else
01298 {
01299 #if 0
01300 printf("DMA buffer too small\n");
01301 #endif
01302 panic(w_name(), "DMA buffer too small", NO_NUM);
01303 }
01304 }
01305 else if (v & DMA_ST_BM_ACTIVE)
01306 panic(w_name(), "DMA buffer too large", NO_NUM);
01307
01308 dma_buf_offset= 0;
01309 while (r == OK && nbytes > 0)
01310 {
01311 n= iov->iov_size;
01312 if (n > nbytes)
01313 n= nbytes;
01314
01315 if (do_copyout)
01316 {
01317 s= sys_vircopy(SELF, D,
01318 (vir_bytes)dma_buf+dma_buf_offset,
01319 proc_nr, D, iov->iov_addr, n);
01320 if (s != OK)
01321 {
01322 panic(w_name(),
01323 "w_transfer: sys_vircopy failed",
01324 s);
01325 }
01326 }
01327
01328
01329 nbytes -= n;
01330 position += n;
01331 iov->iov_addr += n;
01332 if ((iov->iov_size -= n) == 0)
01333 { iov++; nr_req--; }
01334 dma_buf_offset += n;
01335 }
01336 }
01337
01338 while (r == OK && nbytes > 0) {
01339
01340
01341
01342
01343
01344 if (opcode == DEV_GATHER) {
01345
01346 if ((r = at_intr_wait()) != OK) {
01347
01348 if (w_wn->w_status & STATUS_DRQ) {
01349 if ((s=sys_insw(wn->base_cmd+REG_DATA,
01350 SELF, tmp_buf,
01351 SECTOR_SIZE)) != OK)
01352 {
01353 panic(w_name(),
01354 "Call to sys_insw() failed",
01355 s);
01356 }
01357 }
01358 break;
01359 }
01360 }
01361
01362
01363 if (!w_waitfor(STATUS_BSY, 0)) { r = ERR; break; }
01364
01365
01366 if (!w_waitfor(STATUS_DRQ, STATUS_DRQ)) { r = ERR; break; }
01367
01368
01369 if (opcode == DEV_GATHER) {
01370 if ((s=sys_insw(wn->base_cmd + REG_DATA, proc_nr,
01371 (void *) iov->iov_addr, SECTOR_SIZE)) != OK)
01372 {
01373 panic(w_name(),"Call to sys_insw() failed", s);
01374 }
01375 } else {
01376 if ((s=sys_outsw(wn->base_cmd + REG_DATA, proc_nr,
01377 (void *) iov->iov_addr, SECTOR_SIZE)) != OK)
01378 {
01379 panic(w_name(),"Call to sys_outsw() failed",
01380 s);
01381 }
01382
01383
01384 if ((r = at_intr_wait()) != OK) break;
01385 }
01386
01387
01388 nbytes -= SECTOR_SIZE;
01389 position += SECTOR_SIZE;
01390 iov->iov_addr += SECTOR_SIZE;
01391 if ((iov->iov_size -= SECTOR_SIZE) == 0) { iov++; nr_req--; }
01392 }
01393
01394
01395 if (r != OK) {
01396
01397 if (r == ERR_BAD_SECTOR || ++errors == max_errors) {
01398 w_command = CMD_IDLE;
01399 return(EIO);
01400 }
01401 }
01402 }
01403
01404 w_command = CMD_IDLE;
01405 return(OK);
01406 }
01407
01408
01409
01410
01411 PRIVATE int com_out(cmd)
01412 struct command *cmd;
01413 {
01414
01415
01416 struct wini *wn = w_wn;
01417 unsigned base_cmd = wn->base_cmd;
01418 unsigned base_ctl = wn->base_ctl;
01419 pvb_pair_t outbyte[7];
01420 int s;
01421
01422 if (w_wn->state & IGNORING) return ERR;
01423
01424 if (!w_waitfor(STATUS_BSY, 0)) {
01425 printf("%s: controller not ready\n", w_name());
01426 return(ERR);
01427 }
01428
01429
01430 if ((s=sys_outb(base_cmd + REG_LDH, cmd->ldh)) != OK)
01431 panic(w_name(),"Couldn't write register to select drive",s);
01432
01433 if (!w_waitfor(STATUS_BSY, 0)) {
01434 printf("%s: com_out: drive not ready\n", w_name());
01435 return(ERR);
01436 }
01437
01438
01439
01440
01441
01442
01443
01444 sys_setalarm(wakeup_ticks, 0);
01445
01446 wn->w_status = STATUS_ADMBSY;
01447 w_command = cmd->command;
01448 pv_set(outbyte[0], base_ctl + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0);
01449 pv_set(outbyte[1], base_cmd + REG_PRECOMP, cmd->precomp);
01450 pv_set(outbyte[2], base_cmd + REG_COUNT, cmd->count);
01451 pv_set(outbyte[3], base_cmd + REG_SECTOR, cmd->sector);
01452 pv_set(outbyte[4], base_cmd + REG_CYL_LO, cmd->cyl_lo);
01453 pv_set(outbyte[5], base_cmd + REG_CYL_HI, cmd->cyl_hi);
01454 pv_set(outbyte[6], base_cmd + REG_COMMAND, cmd->command);
01455 if ((s=sys_voutb(outbyte,7)) != OK)
01456 panic(w_name(),"Couldn't write registers with sys_voutb()",s);
01457 return(OK);
01458 }
01459
01460
01461
01462
01463 PRIVATE int com_out_ext(cmd)
01464 struct command *cmd;
01465 {
01466
01467
01468 struct wini *wn = w_wn;
01469 unsigned base_cmd = wn->base_cmd;
01470 unsigned base_ctl = wn->base_ctl;
01471 pvb_pair_t outbyte[11];
01472 int s;
01473 unsigned long w_status;
01474
01475 if (w_wn->state & IGNORING) return ERR;
01476
01477 if (!w_waitfor(STATUS_BSY, 0)) {
01478 printf("%s: controller not ready\n", w_name());
01479 return(ERR);
01480 }
01481
01482
01483 if ((s=sys_outb(base_cmd + REG_LDH, cmd->ldh)) != OK)
01484 panic(w_name(),"Couldn't write register to select drive",s);
01485
01486 if (!w_waitfor(STATUS_BSY, 0)) {
01487 printf("%s: com_out: drive not ready\n", w_name());
01488 return(ERR);
01489 }
01490
01491
01492
01493
01494
01495
01496
01497 sys_setalarm(wakeup_ticks, 0);
01498
01499 wn->w_status = STATUS_ADMBSY;
01500 w_command = cmd->command;
01501 pv_set(outbyte[0], base_ctl + REG_CTL, 0);
01502 pv_set(outbyte[1], base_cmd + REG_COUNT, cmd->count_prev);
01503 pv_set(outbyte[2], base_cmd + REG_SECTOR, cmd->sector_prev);
01504 pv_set(outbyte[3], base_cmd + REG_CYL_LO, cmd->cyl_lo_prev);
01505 pv_set(outbyte[4], base_cmd + REG_CYL_HI, cmd->cyl_hi_prev);
01506 pv_set(outbyte[5], base_cmd + REG_COUNT, cmd->count);
01507 pv_set(outbyte[6], base_cmd + REG_SECTOR, cmd->sector);
01508 pv_set(outbyte[7], base_cmd + REG_CYL_LO, cmd->cyl_lo);
01509 pv_set(outbyte[8], base_cmd + REG_CYL_HI, cmd->cyl_hi);
01510
01511 pv_set(outbyte[10], base_cmd + REG_COMMAND, cmd->command);
01512 if ((s=sys_voutb(outbyte, 11)) != OK)
01513 panic(w_name(),"Couldn't write registers with sys_voutb()",s);
01514
01515 return(OK);
01516 }
01517
01518
01519
01520
01521 PRIVATE void setup_dma(sizep, proc_nr, iov, do_write, do_copyoutp)
01522 unsigned *sizep;
01523 int proc_nr;
01524 iovec_t *iov;
01525 int do_write;
01526 int *do_copyoutp;
01527 {
01528 phys_bytes phys, user_phys;
01529 unsigned n, offset, size;
01530 int i, j, r, bad;
01531 unsigned long v;
01532 struct wini *wn = w_wn;
01533
01534
01535 size= *sizep;
01536 i= 0;
01537 j= 0;
01538 bad= 0;
01539 offset= 0;
01540
01541 #if 0
01542 printf("setup_dma: proc_nr %d\n", proc_nr);
01543 #endif
01544
01545 while (size > 0)
01546 {
01547 #if 0
01548 printf(
01549 "setup_dma: iov[%d]: addr 0x%x, size %d offset %d, size %d\n",
01550 i, iov[i].iov_addr, iov[i].iov_size, offset, size);
01551 #endif
01552
01553 n= iov[i].iov_size-offset;
01554 if (n > size)
01555 n= size;
01556 if (n == 0 || (n & 1))
01557 panic("at_wini", "bad size in iov", iov[i].iov_size);
01558 r= sys_umap(proc_nr, D, iov[i].iov_addr+offset, n, &user_phys);
01559 if (r != 0)
01560 panic("at_wini", "can't map user buffer", r);
01561 if (user_phys & 1)
01562 {
01563
01564 printf("setup_dma: user buffer is not aligned\n");
01565 bad= 1;
01566 break;
01567 }
01568
01569
01570 if (user_phys/0x10000 != (user_phys+n-1)/0x10000)
01571 n= ((user_phys/0x10000)+1)*0x10000 - user_phys;
01572
01573
01574
01575
01576
01577 if (j >= N_PRDTE)
01578 {
01579
01580 bad= 1;
01581 break;
01582 }
01583
01584 prdt[j].prdte_base= user_phys;
01585 prdt[j].prdte_count= n;
01586 prdt[j].prdte_reserved= 0;
01587 prdt[j].prdte_flags= 0;
01588 j++;
01589
01590 offset += n;
01591 if (offset >= iov[i].iov_size)
01592 {
01593 i++;
01594 offset= 0;
01595 }
01596
01597 size -= n;
01598 }
01599
01600 if (!bad)
01601 {
01602 if (j <= 0 || j > N_PRDTE)
01603 panic("at_wini", "bad prdt index", j);
01604 prdt[j-1].prdte_flags |= PRDTE_FL_EOT;
01605
01606 #if 0
01607 for (i= 0; i<j; i++)
01608 {
01609 printf("prdt[%d]: base 0x%x, size %d, flags 0x%x\n",
01610 i, prdt[i].prdte_base, prdt[i].prdte_count,
01611 prdt[i].prdte_flags);
01612 }
01613 #endif
01614 }
01615
01616
01617
01618
01619
01620 *do_copyoutp= (!do_write && bad);
01621
01622 if (bad)
01623 {
01624
01625 size= *sizep;
01626 if (size > ATA_DMA_BUF_SIZE)
01627 *sizep= size= ATA_DMA_BUF_SIZE;
01628
01629 if (do_write)
01630 {
01631
01632 for (offset= 0; offset < size; offset += n)
01633 {
01634 n= size-offset;
01635 if (n > iov->iov_size)
01636 n= iov->iov_size;
01637
01638 r= sys_vircopy(proc_nr, D, iov->iov_addr,
01639 SELF, D, (vir_bytes)dma_buf+offset,
01640 n);
01641 if (r != OK)
01642 {
01643 panic(w_name(),
01644 "setup_dma: sys_vircopy failed",
01645 r);
01646 }
01647 iov++;
01648 }
01649 }
01650
01651
01652 phys= dma_buf_phys;
01653 if (phys & 1)
01654 {
01655
01656 panic("at_wini", "bad buffer alignment in setup_dma",
01657 phys);
01658 }
01659 for (j= 0; j<N_PRDTE; i++)
01660 {
01661 if (size == 0)
01662 {
01663 panic("at_wini", "bad size in setup_dma",
01664 size);
01665 }
01666 if (size & 1)
01667 {
01668
01669 panic("at_wini",
01670 "bad size alignment in setup_dma",
01671 size);
01672 }
01673 n= size;
01674
01675
01676 if (phys / 0x10000 != (phys+n-1) / 0x10000)
01677 {
01678 n= ((phys/0x10000)+1)*0x10000 - phys;
01679 }
01680 prdt[j].prdte_base= phys;
01681 prdt[j].prdte_count= n;
01682 prdt[j].prdte_reserved= 0;
01683 prdt[j].prdte_flags= 0;
01684
01685 size -= n;
01686 if (size == 0)
01687 {
01688 prdt[j].prdte_flags |= PRDTE_FL_EOT;
01689 break;
01690 }
01691 }
01692 if (size != 0)
01693 panic("at_wini", "size to large for prdt", NO_NUM);
01694
01695 #if 0
01696 for (i= 0; i<=j; i++)
01697 {
01698 printf("prdt[%d]: base 0x%x, size %d, flags 0x%x\n",
01699 i, prdt[i].prdte_base, prdt[i].prdte_count,
01700 prdt[i].prdte_flags);
01701 }
01702 #endif
01703 }
01704
01705
01706 r= sys_outb(wn->base_dma + DMA_COMMAND, 0);
01707 if (r != 0) panic("at_wini", "setup_dma: sys_outb failed", r);
01708
01709
01710 r= sys_inb(wn->base_dma + DMA_STATUS, &v);
01711 if (r != 0) panic("at_wini", "setup_dma: sys_inb failed", r);
01712 if (v & DMA_ST_BM_ACTIVE)
01713 panic("at_wini", "Bus master IDE active", NO_NUM);
01714
01715 if (prdt_phys & 3)
01716 panic("at_wini", "prdt not aligned", prdt_phys);
01717 r= sys_outl(wn->base_dma + DMA_PRDTP, prdt_phys);
01718 if (r != 0) panic("at_wini", "setup_dma: sys_outl failed", r);
01719
01720
01721 r= sys_outb(wn->base_dma + DMA_STATUS, DMA_ST_INT | DMA_ST_ERROR);
01722 if (r != 0) panic("at_wini", "setup_dma: sys_outb failed", r);
01723
01724
01725 v= DMA_CMD_START;
01726 if (!do_write)
01727 {
01728
01729 v |= DMA_CMD_WRITE;
01730 }
01731 r= sys_outb(wn->base_dma + DMA_COMMAND, v);
01732 if (r != 0) panic("at_wini", "setup_dma: sys_outb failed", r);
01733
01734 #if 0
01735 r= sys_inb(wn->base_dma + DMA_STATUS, &v);
01736 if (r != 0) panic("at_wini", "setup_dma: sys_inb failed", r);
01737 printf("dma status: 0x%x\n", v);
01738 #endif
01739 }
01740
01741
01742
01743
01744
01745 PRIVATE void w_need_reset()
01746 {
01747
01748 struct wini *wn;
01749 int dr = 0;
01750
01751 for (wn = wini; wn < &wini[MAX_DRIVES]; wn++, dr++) {
01752 if (wn->base_cmd == w_wn->base_cmd) {
01753 wn->state |= DEAF;
01754 wn->state &= ~INITIALIZED;
01755 }
01756 }
01757 }
01758
01759
01760
01761
01762 PRIVATE int w_do_close(dp, m_ptr)
01763 struct driver *dp;
01764 message *m_ptr;
01765 {
01766
01767 if (w_prepare(m_ptr->DEVICE) == NIL_DEV)
01768 return(ENXIO);
01769 w_wn->open_ct--;
01770 #if ENABLE_ATAPI
01771 if (w_wn->open_ct == 0 && (w_wn->state & ATAPI)) atapi_close();
01772 #endif
01773 return(OK);
01774 }
01775
01776
01777
01778
01779 PRIVATE int com_simple(cmd)
01780 struct command *cmd;
01781 {
01782
01783 int r;
01784
01785 if (w_wn->state & IGNORING) return ERR;
01786
01787 if ((r = com_out(cmd)) == OK) r = at_intr_wait();
01788 w_command = CMD_IDLE;
01789 return(r);
01790 }
01791
01792
01793
01794
01795 PRIVATE void w_timeout(void)
01796 {
01797 struct wini *wn = w_wn;
01798
01799 switch (w_command) {
01800 case CMD_IDLE:
01801 break;
01802 case CMD_READ:
01803 case CMD_READ_EXT:
01804 case CMD_WRITE:
01805 case CMD_WRITE_EXT:
01806
01807
01808
01809 if (wn->max_count > 8 * SECTOR_SIZE) {
01810 wn->max_count = 8 * SECTOR_SIZE;
01811 } else {
01812 wn->max_count = SECTOR_SIZE;
01813 }
01814
01815 default:
01816
01817 if (w_testing) wn->state |= IGNORING;
01818 else if (!w_silent) printf("%s: timeout on command 0x%02x\n",
01819 w_name(), w_command);
01820 w_need_reset();
01821 wn->w_status = 0;
01822 }
01823 }
01824
01825
01826
01827
01828 PRIVATE int w_reset()
01829 {
01830
01831
01832
01833 int s;
01834 struct wini *wn = w_wn;
01835
01836
01837 if (w_wn->state & IGNORING) return ERR;
01838
01839
01840 tickdelay(RECOVERY_TICKS);
01841
01842
01843 if ((s=sys_outb(wn->base_ctl + REG_CTL, CTL_RESET)) != OK)
01844 panic(w_name(),"Couldn't strobe reset bit",s);
01845 tickdelay(DELAY_TICKS);
01846 if ((s=sys_outb(wn->base_ctl + REG_CTL, 0)) != OK)
01847 panic(w_name(),"Couldn't strobe reset bit",s);
01848 tickdelay(DELAY_TICKS);
01849
01850
01851 if (!w_waitfor(STATUS_BSY, 0)) {
01852 printf("%s: reset failed, drive busy\n", w_name());
01853 return(ERR);
01854 }
01855
01856
01857
01858 for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
01859 if (wn->base_cmd == w_wn->base_cmd) {
01860 wn->state &= ~DEAF;
01861 if (w_wn->irq_need_ack) {
01862
01863 sys_irqenable(&w_wn->irq_hook_id);
01864 }
01865 }
01866 }
01867
01868
01869 return(OK);
01870 }
01871
01872
01873
01874
01875 PRIVATE void w_intr_wait()
01876 {
01877
01878
01879 int r;
01880 unsigned long w_status;
01881 message m;
01882
01883 if (w_wn->irq != NO_IRQ) {
01884
01885 while (w_wn->w_status & (STATUS_ADMBSY|STATUS_BSY)) {
01886 int rr;
01887 if((rr=receive(ANY, &m)) != OK) {
01888 printf("w_intr_wait: receive from ANY failed (%d)\n",
01889 r);
01890 continue;
01891 }
01892 if (m.m_type == SYN_ALARM) {
01893 w_timeout();
01894 } else if (m.m_type == HARD_INT) {
01895 r= sys_inb(w_wn->base_cmd + REG_STATUS, &w_status);
01896 if (r != 0)
01897 panic("at_wini", "sys_inb failed", r);
01898 w_wn->w_status= w_status;
01899 ack_irqs(m.NOTIFY_ARG);
01900 } else if (m.m_type == DEV_PING) {
01901 notify(m.m_source);
01902 } else {
01903 printf("AT_WINI got unexpected message %d from %d\n",
01904 m.m_type, m.m_source);
01905 }
01906 }
01907 } else {
01908
01909 (void) w_waitfor(STATUS_BSY, 0);
01910 }
01911 }
01912
01913
01914
01915
01916 PRIVATE int at_intr_wait()
01917 {
01918
01919 int r, s;
01920 unsigned long inbval;
01921
01922 w_intr_wait();
01923 if ((w_wn->w_status & (STATUS_BSY | STATUS_WF | STATUS_ERR)) == 0) {
01924 r = OK;
01925 } else {
01926 if ((s=sys_inb(w_wn->base_cmd + REG_ERROR, &inbval)) != OK)
01927 panic(w_name(),"Couldn't read register",s);
01928 if ((w_wn->w_status & STATUS_ERR) && (inbval & ERROR_BB)) {
01929 r = ERR_BAD_SECTOR;
01930 } else {
01931 r = ERR;
01932 }
01933 }
01934 w_wn->w_status |= STATUS_ADMBSY;
01935 return(r);
01936 }
01937
01938
01939
01940
01941 PRIVATE int w_waitfor(mask, value)
01942 int mask;
01943 int value;
01944 {
01945
01946
01947
01948
01949
01950 unsigned long w_status;
01951 clock_t t0, t1;
01952 int s;
01953
01954 getuptime(&t0);
01955 do {
01956 if ((s=sys_inb(w_wn->base_cmd + REG_STATUS, &w_status)) != OK)
01957 panic(w_name(),"Couldn't read register",s);
01958 w_wn->w_status= w_status;
01959 if ((w_wn->w_status & mask) == value) {
01960 return 1;
01961 }
01962 } while ((s=getuptime(&t1)) == OK && (t1-t0) < timeout_ticks );
01963 if (OK != s) printf("AT_WINI: warning, get_uptime failed: %d\n",s);
01964
01965 w_need_reset();
01966 return(0);
01967 }
01968
01969
01970
01971
01972 PRIVATE int w_waitfor_dma(mask, value)
01973 int mask;
01974 int value;
01975 {
01976
01977
01978
01979
01980
01981 unsigned long w_status;
01982 clock_t t0, t1;
01983 int s;
01984
01985 getuptime(&t0);
01986 do {
01987 if ((s=sys_inb(w_wn->base_dma + DMA_STATUS, &w_status)) != OK)
01988 panic(w_name(),"Couldn't read register",s);
01989 if ((w_status & mask) == value) {
01990 return 1;
01991 }
01992 } while ((s=getuptime(&t1)) == OK && (t1-t0) < timeout_ticks );
01993 if (OK != s) printf("AT_WINI: warning, get_uptime failed: %d\n",s);
01994
01995 return(0);
01996 }
01997
01998
01999
02000
02001 PRIVATE void w_geometry(entry)
02002 struct partition *entry;
02003 {
02004 struct wini *wn = w_wn;
02005
02006 if (wn->state & ATAPI) {
02007 entry->cylinders = div64u(wn->part[0].dv_size, SECTOR_SIZE) / (64*32);
02008 entry->heads = 64;
02009 entry->sectors = 32;
02010 } else {
02011 entry->cylinders = wn->lcylinders;
02012 entry->heads = wn->lheads;
02013 entry->sectors = wn->lsectors;
02014 }
02015 }
02016
02017 #if ENABLE_ATAPI
02018
02019
02020
02021 PRIVATE int atapi_open()
02022 {
02023
02024
02025
02026
02027 w_wn->part[0].dv_size = mul64u(800L*1024, 1024);
02028 return(OK);
02029 }
02030
02031
02032
02033
02034 PRIVATE void atapi_close()
02035 {
02036
02037 }
02038
02039 void sense_request(void)
02040 {
02041 int r, i;
02042 static u8_t sense[100], packet[ATAPI_PACKETSIZE];
02043
02044 packet[0] = SCSI_SENSE;
02045 packet[1] = 0;
02046 packet[2] = 0;
02047 packet[3] = 0;
02048 packet[4] = SENSE_PACKETSIZE;
02049 packet[5] = 0;
02050 packet[7] = 0;
02051 packet[8] = 0;
02052 packet[9] = 0;
02053 packet[10] = 0;
02054 packet[11] = 0;
02055
02056 for(i = 0; i < SENSE_PACKETSIZE; i++) sense[i] = 0xff;
02057 r = atapi_sendpacket(packet, SENSE_PACKETSIZE);
02058 if (r != OK) { printf("request sense command failed\n"); return; }
02059 if (atapi_intr_wait() <= 0) { printf("WARNING: request response failed\n"); }
02060
02061 if (sys_insw(w_wn->base_cmd + REG_DATA, SELF, (void *) sense, SENSE_PACKETSIZE) != OK)
02062 printf("WARNING: sense reading failed\n");
02063
02064 printf("sense data:");
02065 for(i = 0; i < SENSE_PACKETSIZE; i++) printf(" %02x", sense[i]);
02066 printf("\n");
02067 }
02068
02069
02070
02071
02072 PRIVATE int atapi_transfer(proc_nr, opcode, position, iov, nr_req)
02073 int proc_nr;
02074 int opcode;
02075 off_t position;
02076 iovec_t *iov;
02077 unsigned nr_req;
02078 {
02079 struct wini *wn = w_wn;
02080 iovec_t *iop, *iov_end = iov + nr_req;
02081 int r, s, errors, fresh;
02082 u64_t pos;
02083 unsigned long block;
02084 unsigned long dv_size = cv64ul(w_dv->dv_size);
02085 unsigned nbytes, nblocks, count, before, chunk;
02086 static u8_t packet[ATAPI_PACKETSIZE];
02087
02088 errors = fresh = 0;
02089
02090 while (nr_req > 0 && !fresh) {
02091
02092
02093
02094 pos = add64ul(w_dv->dv_base, position);
02095 block = div64u(pos, CD_SECTOR_SIZE);
02096 before = rem64u(pos, CD_SECTOR_SIZE);
02097
02098
02099 nbytes = count = 0;
02100 for (iop = iov; iop < iov_end; iop++) {
02101 nbytes += iop->iov_size;
02102 if ((before + nbytes) % CD_SECTOR_SIZE == 0) count = nbytes;
02103 }
02104
02105
02106 if (count != 0) nbytes = count;
02107
02108
02109 if ((before | nbytes) & 1) return(EINVAL);
02110
02111
02112 if (position >= dv_size) return(OK);
02113 if (position + nbytes > dv_size) nbytes = dv_size - position;
02114
02115 nblocks = (before + nbytes + CD_SECTOR_SIZE - 1) / CD_SECTOR_SIZE;
02116 if (ATAPI_DEBUG) {
02117 printf("block=%lu, before=%u, nbytes=%u, nblocks=%u\n",
02118 block, before, nbytes, nblocks);
02119 }
02120
02121
02122 if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO);
02123
02124
02125 packet[0] = SCSI_READ10;
02126 packet[1] = 0;
02127 packet[2] = (block >> 24) & 0xFF;
02128 packet[3] = (block >> 16) & 0xFF;
02129 packet[4] = (block >> 8) & 0xFF;
02130 packet[5] = (block >> 0) & 0xFF;
02131 packet[7] = (nblocks >> 8) & 0xFF;
02132 packet[8] = (nblocks >> 0) & 0xFF;
02133 packet[9] = 0;
02134 packet[10] = 0;
02135 packet[11] = 0;
02136
02137
02138 r = atapi_sendpacket(packet, nblocks * CD_SECTOR_SIZE);
02139 if (r != OK) goto err;
02140
02141
02142 while ((r = atapi_intr_wait()) > 0) {
02143 count = r;
02144
02145 if (ATAPI_DEBUG) {
02146 printf("before=%u, nbytes=%u, count=%u\n",
02147 before, nbytes, count);
02148 }
02149
02150 while (before > 0 && count > 0) {
02151 chunk = before;
02152 if (chunk > count) chunk = count;
02153 if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
02154 if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, chunk)) != OK)
02155 panic(w_name(),"Call to sys_insw() failed", s);
02156 before -= chunk;
02157 count -= chunk;
02158 }
02159
02160 while (nbytes > 0 && count > 0) {
02161 chunk = nbytes;
02162 if (chunk > count) chunk = count;
02163 if (chunk > iov->iov_size) chunk = iov->iov_size;
02164 if ((s=sys_insw(wn->base_cmd + REG_DATA, proc_nr, (void *) iov->iov_addr, chunk)) != OK)
02165 panic(w_name(),"Call to sys_insw() failed", s);
02166 position += chunk;
02167 nbytes -= chunk;
02168 count -= chunk;
02169 iov->iov_addr += chunk;
02170 fresh = 0;
02171 if ((iov->iov_size -= chunk) == 0) {
02172 iov++;
02173 nr_req--;
02174 fresh = 1;
02175 }
02176 }
02177
02178 while (count > 0) {
02179 chunk = count;
02180 if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE;
02181 if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, chunk)) != OK)
02182 panic(w_name(),"Call to sys_insw() failed", s);
02183 count -= chunk;
02184 }
02185 }
02186
02187 if (r < 0) {
02188 err:
02189 if (atapi_debug) sense_request();
02190 if (++errors == max_errors) {
02191 w_command = CMD_IDLE;
02192 if (atapi_debug) printf("giving up (%d)\n", errors);
02193 return(EIO);
02194 }
02195 if (atapi_debug) printf("retry (%d)\n", errors);
02196 }
02197 }
02198
02199 w_command = CMD_IDLE;
02200 return(OK);
02201 }
02202
02203
02204
02205
02206 PRIVATE int atapi_sendpacket(packet, cnt)
02207 u8_t *packet;
02208 unsigned cnt;
02209 {
02210
02211 struct wini *wn = w_wn;
02212 pvb_pair_t outbyte[6];
02213 int s;
02214
02215 if (wn->state & IGNORING) return ERR;
02216
02217
02218 if ((s=sys_outb(wn->base_cmd + REG_DRIVE, wn->ldhpref)) != OK)
02219 panic(w_name(),"Couldn't select master/ slave drive",s);
02220
02221 if (!w_waitfor(STATUS_BSY | STATUS_DRQ, 0)) {
02222 printf("%s: atapi_sendpacket: drive not ready\n", w_name());
02223 return(ERR);
02224 }
02225
02226
02227
02228
02229
02230
02231
02232 sys_setalarm(wakeup_ticks, 0);
02233
02234 #if _WORD_SIZE > 2
02235 if (cnt > 0xFFFE) cnt = 0xFFFE;
02236 #endif
02237
02238 w_command = ATAPI_PACKETCMD;
02239 pv_set(outbyte[0], wn->base_cmd + REG_FEAT, 0);
02240 pv_set(outbyte[1], wn->base_cmd + REG_IRR, 0);
02241 pv_set(outbyte[2], wn->base_cmd + REG_SAMTAG, 0);
02242 pv_set(outbyte[3], wn->base_cmd + REG_CNT_LO, (cnt >> 0) & 0xFF);
02243 pv_set(outbyte[4], wn->base_cmd + REG_CNT_HI, (cnt >> 8) & 0xFF);
02244 pv_set(outbyte[5], wn->base_cmd + REG_COMMAND, w_command);
02245 if (atapi_debug) printf("cmd: %x ", w_command);
02246 if ((s=sys_voutb(outbyte,6)) != OK)
02247 panic(w_name(),"Couldn't write registers with sys_voutb()",s);
02248
02249 if (!w_waitfor(STATUS_BSY | STATUS_DRQ, STATUS_DRQ)) {
02250 printf("%s: timeout (BSY|DRQ -> DRQ)\n", w_name());
02251 return(ERR);
02252 }
02253 wn->w_status |= STATUS_ADMBSY;
02254
02255
02256 if ((s=sys_outsw(wn->base_cmd + REG_DATA, SELF, packet, ATAPI_PACKETSIZE)) != OK)
02257 panic(w_name(),"sys_outsw() failed", s);
02258
02259 {
02260 int p;
02261 if (atapi_debug) {
02262 printf("sent command:");
02263 for(p = 0; p < ATAPI_PACKETSIZE; p++) { printf(" %02x", packet[p]); }
02264 printf("\n");
02265 }
02266 }
02267 return(OK);
02268 }
02269
02270
02271 #endif
02272
02273
02274
02275
02276 PRIVATE int w_other(dr, m)
02277 struct driver *dr;
02278 message *m;
02279 {
02280 int r, timeout, prev;
02281
02282 if (m->m_type != DEV_IOCTL ) {
02283 return EINVAL;
02284 }
02285
02286 if (m->REQUEST == DIOCTIMEOUT) {
02287 if ((r=sys_datacopy(m->IO_ENDPT, (vir_bytes)m->ADDRESS,
02288 SELF, (vir_bytes)&timeout, sizeof(timeout))) != OK)
02289 return r;
02290
02291 if (timeout == 0) {
02292
02293 timeout_ticks = DEF_TIMEOUT_TICKS;
02294 max_errors = MAX_ERRORS;
02295 wakeup_ticks = WAKEUP;
02296 w_silent = 0;
02297 } else if (timeout < 0) {
02298 return EINVAL;
02299 } else {
02300 prev = wakeup_ticks;
02301
02302 if (!w_standard_timeouts) {
02303
02304
02305
02306 wakeup_ticks = timeout;
02307 max_errors = 3;
02308 w_silent = 1;
02309
02310 if (timeout_ticks > timeout)
02311 timeout_ticks = timeout;
02312 }
02313
02314 if ((r=sys_datacopy(SELF, (vir_bytes)&prev,
02315 m->IO_ENDPT, (vir_bytes)m->ADDRESS, sizeof(prev))) != OK)
02316 return r;
02317 }
02318
02319 return OK;
02320 } else if (m->REQUEST == DIOCOPENCT) {
02321 int count;
02322 if (w_prepare(m->DEVICE) == NIL_DEV) return ENXIO;
02323 count = w_wn->open_ct;
02324 if ((r=sys_datacopy(SELF, (vir_bytes)&count,
02325 m->IO_ENDPT, (vir_bytes)m->ADDRESS, sizeof(count))) != OK)
02326 return r;
02327 return OK;
02328 }
02329 return EINVAL;
02330 }
02331
02332
02333
02334
02335 PRIVATE int w_hw_int(dr, m)
02336 struct driver *dr;
02337 message *m;
02338 {
02339
02340 ack_irqs(m->NOTIFY_ARG);
02341
02342 return OK;
02343 }
02344
02345
02346
02347
02348
02349 PRIVATE void ack_irqs(unsigned int irqs)
02350 {
02351 unsigned int drive;
02352 unsigned long w_status;
02353
02354 for (drive = 0; drive < MAX_DRIVES && irqs; drive++) {
02355 if (!(wini[drive].state & IGNORING) && wini[drive].irq_need_ack &&
02356 (wini[drive].irq_mask & irqs)) {
02357 if (sys_inb((wini[drive].base_cmd + REG_STATUS),
02358 &w_status) != OK)
02359 {
02360 panic(w_name(), "couldn't ack irq on drive %d\n",
02361 drive);
02362 }
02363 wini[drive].w_status= w_status;
02364 if (sys_irqenable(&wini[drive].irq_hook_id) != OK)
02365 printf("couldn't re-enable drive %d\n", drive);
02366 irqs &= ~wini[drive].irq_mask;
02367 }
02368 }
02369 }
02370
02371
02372 #define STSTR(a) if (status & STATUS_ ## a) { strcat(str, #a); strcat(str, " "); }
02373 #define ERRSTR(a) if (e & ERROR_ ## a) { strcat(str, #a); strcat(str, " "); }
02374 char *strstatus(int status)
02375 {
02376 static char str[200];
02377 str[0] = '\0';
02378
02379 STSTR(BSY);
02380 STSTR(DRDY);
02381 STSTR(DMADF);
02382 STSTR(SRVCDSC);
02383 STSTR(DRQ);
02384 STSTR(CORR);
02385 STSTR(CHECK);
02386 return str;
02387 }
02388
02389 char *strerr(int e)
02390 {
02391 static char str[200];
02392 str[0] = '\0';
02393
02394 ERRSTR(BB);
02395 ERRSTR(ECC);
02396 ERRSTR(ID);
02397 ERRSTR(AC);
02398 ERRSTR(TK);
02399 ERRSTR(DM);
02400
02401 return str;
02402 }
02403
02404 #if ENABLE_ATAPI
02405
02406
02407
02408
02409 PRIVATE int atapi_intr_wait()
02410 {
02411
02412
02413
02414 struct wini *wn = w_wn;
02415 pvb_pair_t inbyte[4];
02416 int s;
02417 int e;
02418 int len;
02419 int irr;
02420 int r;
02421 int phase;
02422
02423 w_intr_wait();
02424
02425
02426 inbyte[0].port = wn->base_cmd + REG_ERROR;
02427 inbyte[1].port = wn->base_cmd + REG_CNT_LO;
02428 inbyte[2].port = wn->base_cmd + REG_CNT_HI;
02429 inbyte[3].port = wn->base_cmd + REG_IRR;
02430 if ((s=sys_vinb(inbyte, 4)) != OK)
02431 panic(w_name(),"ATAPI failed sys_vinb()", s);
02432 e = inbyte[0].value;
02433 len = inbyte[1].value;
02434 len |= inbyte[2].value << 8;
02435 irr = inbyte[3].value;
02436
02437 #if ATAPI_DEBUG
02438 printf("wn %p S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn, wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
02439 #endif
02440 if (wn->w_status & (STATUS_BSY | STATUS_CHECK)) {
02441 if (atapi_debug) {
02442 printf("atapi fail: S=%x=%s E=%02x=%s L=%04x I=%02x\n", wn->w_status, strstatus(wn->w_status), e, strerr(e), len, irr);
02443 }
02444 return ERR;
02445 }
02446
02447 phase = (wn->w_status & STATUS_DRQ) | (irr & (IRR_COD | IRR_IO));
02448
02449 switch (phase) {
02450 case IRR_COD | IRR_IO:
02451 if (ATAPI_DEBUG) printf("ACD: Phase Command Complete\n");
02452 r = OK;
02453 break;
02454 case 0:
02455 if (ATAPI_DEBUG) printf("ACD: Phase Command Aborted\n");
02456 r = ERR;
02457 break;
02458 case STATUS_DRQ | IRR_COD:
02459 if (ATAPI_DEBUG) printf("ACD: Phase Command Out\n");
02460 r = ERR;
02461 break;
02462 case STATUS_DRQ:
02463 if (ATAPI_DEBUG) printf("ACD: Phase Data Out %d\n", len);
02464 r = len;
02465 break;
02466 case STATUS_DRQ | IRR_IO:
02467 if (ATAPI_DEBUG) printf("ACD: Phase Data In %d\n", len);
02468 r = len;
02469 break;
02470 default:
02471 if (ATAPI_DEBUG) printf("ACD: Phase Unknown\n");
02472 r = ERR;
02473 break;
02474 }
02475
02476 #if 0
02477
02478 XXX while (phase == (IRR_IO | IRR_COD) && (wn->w_status & STATUS_CHECK)
02479 && (e & ERROR_SENSE) == SENSE_UATTN && --try > 0);
02480 #endif
02481
02482 wn->w_status |= STATUS_ADMBSY;
02483 return(r);
02484 }
02485 #endif