From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1QaZRs-0005Z6-2u for mharc-grub-devel@gnu.org; Sat, 25 Jun 2011 16:27:24 -0400 Received: from eggs.gnu.org ([140.186.70.92]:40344) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QaZRn-0005Yd-BX for grub-devel@gnu.org; Sat, 25 Jun 2011 16:27:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QaZRl-0005M2-Fm for grub-devel@gnu.org; Sat, 25 Jun 2011 16:27:19 -0400 Received: from mail-wy0-f169.google.com ([74.125.82.169]:43046) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QaZRl-0005Lx-3P for grub-devel@gnu.org; Sat, 25 Jun 2011 16:27:17 -0400 Received: by wyg36 with SMTP id 36so3084111wyg.0 for ; Sat, 25 Jun 2011 13:27:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:message-id:date:from:user-agent:mime-version:to :subject:references:in-reply-to:x-enigmail-version:content-type; bh=G3gtIQOrXgH1fK0+65tHxqrs1ZHjg56HWWRmu+Dn9pA=; b=O1ayA331XqtzOyl0jwji2BKwIgFTTZfXird/UdjraO+8YTWqlTHC3IM1EVrU6f80BX 79t/S5U2aQGpW2rx7Car8Atd58LRI91A60t7T0gIozk0xeHNqeA9Sgm+GUw24LSJG9iS 5HqQ32OEaQGmbDL0T+8yCKM9PFoP3DnLC/Qn8= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:x-enigmail-version:content-type; b=WFbZfcQzMMbEuVLAk/KNKJC2meNwi/OuJGBICH/JWAzH/iSFgl/FnHeoqos8tyIuav w9KlP2lJGVV9TDT7/Y37Bu8ROBCdzAxn1pnoKG+SLpFrhj+9FTtDOR1TWoHr9eA1RdYT be44FUCYnLEKcDChZXXfNRD1sYhR/mCQP6s8E= Received: by 10.217.6.81 with SMTP id x59mr1451976wes.50.1309033636003; Sat, 25 Jun 2011 13:27:16 -0700 (PDT) Received: from debian.x201.phnet (gprs33.swisscom-mobile.ch [193.247.250.33]) by mx.google.com with ESMTPS id w58sm2011043weq.25.2011.06.25.13.27.13 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 25 Jun 2011 13:27:14 -0700 (PDT) Message-ID: <4E064497.50101@gmail.com> Date: Sat, 25 Jun 2011 22:27:03 +0200 From: =?UTF-8?B?VmxhZGltaXIgJ8+GLWNvZGVyL3BoY29kZXInIFNlcmJpbmVua28=?= User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.17) Gecko/20110606 Iceowl/1.0b2 Icedove/3.1.10 MIME-Version: 1.0 To: The development of GNU GRUB Subject: Re: [PATCH] EHCI driver - USB 2.0 support References: <1309029199.2532.35.camel@pracovna> In-Reply-To: <1309029199.2532.35.camel@pracovna> X-Enigmail-Version: 1.1.2 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="------------enig3AD38D5F345B2115800F5075" X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 74.125.82.169 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Jun 2011 20:27:21 -0000 This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enig3AD38D5F345B2115800F5075 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On 25.06.2011 21:13, Ale=C5=A1 Nesrsta wrote: > Hi, > > because I still see no EHCI driver in GRUB for long time, I slowly > prepared myself something what looks to be working... > EHCI driver code is based on UHCI (OHCI) GRUB driver, no other source > code was used (copied). Very good. > I shortly tested main functions: > - high speed device connected directly to EHCI port - working, OK > - low/full speed device connected directly to EHCI port - not working > but it is OK (it cannot work according to specification) Ir must be rerouted to companion. Some controllers (like in my thinkpad) have no companion. I haven't played with internals to see how it's done. > /* ehci.c - EHCI Support. */ > /* > * GRUB -- GRand Unified Bootloader > * Copyright (C) 2008 Free Software Foundation, Inc. Add 2011 here. > GRUB_MOD_LICENSE ("GPLv3+"); > > /* This simple GRUB implementation of EHCI driver: > * - assumes 32 bits architecture, no IRQ How exactly do you use this? > #define GRUB_EHCI_SPARAMS_PPC (1<<4) /* Power port control */ Please run indent on the file. > #define GRUB_EHCI_PORT_READ(e, port) \ > grub_ehci_oper_read32 ((e), GRUB_EHCI_PORT_STAT_CMD + (port)*4) > =20 Why not make it an inline static function? > #define GRUB_EHCI_PORT_RESBITS(e, port, bits) \ > { grub_ehci_oper_write32 ((e), GRUB_EHCI_PORT_STAT_CMD + (port)*4, \ > GRUB_EHCI_PORT_READ((e), (port)) & GRUB_EHCI_PORT_WMASK & ~(bits));= \ > GRUB_EHCI_PORT_READ((e), (port)); } > ditto > #define GRUB_EHCI_PORT_SETBITS(e, port, bits) \ > { grub_ehci_oper_write32 ((e), GRUB_EHCI_PORT_STAT_CMD + (port)*4, \ > (GRUB_EHCI_PORT_READ((e), (port)) & GRUB_EHCI_PORT_WMASK) | (bits))= ; \ > GRUB_EHCI_PORT_READ((e), (port)); } > ditto > /* EHCI Queue Element Transfer Descriptor (qTD) */ > /* Align to 32-byte boundaries */ > struct grub_ehci_td > { > /* EHCI HW part */ > grub_uint32_t next_td; /* Pointer to next qTD */ > grub_uint32_t alt_next_td; /* Pointer to alternate next qTD */ > grub_uint32_t token; /* Toggle, Len, Interrupt, Page, Error, PID, Sta= tus */ > grub_uint32_t buffer_page[GRUB_EHCI_TD_BUF_PAGES]; /* Buffer pointer = (+ cur. offset in page 0 */ > /* 64-bits part */ > grub_uint32_t buffer_page_high[GRUB_EHCI_TD_BUF_PAGES]; > /* EHCI driver part */ > grub_ehci_td_t link_td; /* pointer to next free/chained TD */ > grub_uint32_t size; > grub_uint32_t pad[1]; /* padding to some multiple of 32 bytes */ > } __attribute__((packed)); > packed isn't necessary here > /* EHCI Queue Head */ > /* Align to 32-byte boundaries */ > /* QH allocation is made in the similar/same way as in OHCI driver, > * because unlninking QH from the Asynchronous list is not so > * trivial as on UHCI (at least it is time consuming) */ > struct grub_ehci_qh > { > /* EHCI HW part */ > grub_uint32_t qh_hptr; /* Horiz. pointer & Terminate */ > grub_uint32_t ep_char; /* EP characteristics */ > grub_uint32_t ep_cap; /* EP capabilities */ > grub_uint32_t td_current; /* current TD link pointer */ > struct grub_ehci_td td_overlay; /* TD overlay area =3D 64 bytes */ > /* EHCI driver part */ > grub_uint32_t pad[4]; /* padding to some multiple of 32 bytes */ > } __attribute__((packed)); Same here > /* EHCC registers access functions */ > static inline grub_uint32_t > grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr) > { > return grub_le_to_cpu32 ( > *((grub_uint32_t *)((grub_uint32_t)e->iobase_ehcc + addr))); > } Convert to char * in order to do arithmetics, not grub_uint32_t. Also you need to use volatile attribute in last conversion. Same for following functions > /* Halt if EHCI HC not halted */ > static grub_err_t > grub_ehci_halt (struct grub_ehci *e) > { > grub_uint64_t maxtime; > > if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) > & GRUB_EHCI_ST_HC_HALTED) =3D=3D 0 ) /* EHCI is not halted */ > { > /* Halt EHCI */ > grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, > ~GRUB_EHCI_CMD_RUNSTOP > & grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); > /* Ensure command is written */ > grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND); > maxtime =3D grub_get_time_ms () + 1000; /* Fix: Should be 2ms ! *= / > while (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) > & GRUB_EHCI_ST_HC_HALTED) =3D=3D 0) > && (grub_get_time_ms () < maxtime)); > if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) > & GRUB_EHCI_ST_HC_HALTED) =3D=3D 0 ) > return GRUB_ERR_TIMEOUT; > } > =20 > return GRUB_ERR_NONE; > } > > /* EHCI HC reset */ > static grub_err_t > grub_ehci_reset (struct grub_ehci *e) > { > grub_uint64_t maxtime; > > grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, > GRUB_EHCI_CMD_HC_RESET > | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); > /* Ensure command is written */ > grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND); > /* XXX: How long time could take reset of HC ? */ > maxtime =3D grub_get_time_ms () + 1000; > while (((grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND) > & GRUB_EHCI_CMD_HC_RESET) !=3D 0) > && (grub_get_time_ms () < maxtime)); > if ((grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND) > & GRUB_EHCI_CMD_HC_RESET) !=3D 0 ) > return GRUB_ERR_TIMEOUT; > =20 > return GRUB_ERR_NONE; > } > > /* PCI iteration function... */ > static int NESTED_FUNC_ATTR > grub_ehci_pci_iter (grub_pci_device_t dev, > grub_pci_id_t pciid __attribute__((unused))) > { > grub_pci_address_t addr; > grub_uint8_t release; > grub_uint32_t class_code; > grub_uint32_t interf; > grub_uint32_t subclass; > grub_uint32_t class; > grub_uint32_t base, base_h; > struct grub_ehci *e; > grub_uint32_t eecp_offset; > grub_uint32_t fp; > int i; > grub_uint32_t usblegsup =3D 0; > grub_uint64_t maxtime; > grub_uint32_t n_ports; > =20 > grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n"); > > addr =3D grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); > class_code =3D grub_pci_read (addr) >> 8; > interf =3D class_code & 0xFF; > subclass =3D (class_code >> 8) & 0xFF; > class =3D class_code >> 16; > > /* If this is not an EHCI controller, just return. */ > if (class !=3D 0x0c || subclass !=3D 0x03 || interf !=3D 0x20) > return 0; > > grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n"); > > /* Check Serial Bus Release Number */ > addr =3D grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG); > release =3D grub_pci_read_byte (addr); > if (release !=3D 0x20) > { > grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n= ", release); > return 0; > } > > grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n"); > =20 > /* Determine EHCI EHCC registers base address. */ > addr =3D grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); > base =3D grub_pci_read (addr); > addr =3D grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); > base_h =3D grub_pci_read (addr); > /* Stop if not 32bit address type - this driver does not currently > * work with 64bit - maybe later... */ No need to specifically exclude those. Just zero-pad address. > /* Determine base address of EHCI operational registers */ > e->iobase =3D (grub_uint32_t *)((grub_uint32_t)e->iobase_ehcc + > (grub_uint32_t) grub_ehci_ehcc_read8 (e, > GRUB_EHCI_EHCC_CAPLEN));= > e->iobase should have volatile attribute > /* Reserve a page for the frame list - it is accurate for max. > * possible size of framelist. But currently it is not used. */ > e->framelist =3D grub_memalign (4096, 4096); > if (! e->framelist) > goto fail; > /* XXX: The currently allowed EHCI pointers are only 32 bits, > * make sure this code works on on 64 bits architectures. */ That's why you have to use dmaalign32 > /* Determine and change ownership. */ > /* XXX: Really should we handle it ? > * Is BIOS code active when GRUB is loaded and can BIOS properly > * "assist" in change of EHCI ownership ? */ > if (e->pcibase_eecp) /* Ownership can be changed via EECP only */ > { > usblegsup =3D grub_pci_read (e->pcibase_eecp); > if (usblegsup & GRUB_EHCI_BIOS_OWNED) > { > grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by= : BIOS\n"); > /* Ownership change - set OS_OWNED bit */ > /* XXX: Is PCI address for grub_pci_write_byte() correct ? */= > grub_pci_write_byte (e->pcibase_eecp + GRUB_EHCI_OS_OWNED_OFF= , 1); Arithmetics with PCI address aren't guaranteed to be available or to behave in a sane way. > /* Wait for finish of ownership change, EHCI specification > * doesn't say how long it can take... */ > maxtime =3D grub_get_time_ms () + 1000; > while ((grub_pci_read (e->pcibase_eecp) & GRUB_EHCI_BIOS_OWNE= D) > && (grub_get_time_ms () < maxtime)); > if (grub_pci_read (e->pcibase_eecp) & GRUB_EHCI_BIOS_OWNED) > { > grub_error (GRUB_ERR_TIMEOUT, "EHCI grub_ehci_pci_iter:EH= CI change ownership timeout"); In this case you have to take the ownership the hard way. You clean GRUB_EHCI_BIOS_OWNED yourself and disable all SMM interrupts (next EECP field) --=20 Regards Vladimir '=CF=86-coder/phcoder' Serbinenko --------------enig3AD38D5F345B2115800F5075 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iF4EAREKAAYFAk4GRJ8ACgkQNak7dOguQgkcBgEAs9A8w+OSbXzSnGTHYFFMq1Ah lzgG0ydH1Pm1guffxrgBAI0bKzeK7pqwGlrq5XCcOfB4OdI8md9YpNzC4Xpk57p0 =Z55p -----END PGP SIGNATURE----- --------------enig3AD38D5F345B2115800F5075--